diff --git a/.gitignore b/.gitignore
index 665a9e77..1f8a30f7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,24 +1,18 @@
#files, the will be ignored by git
+#file with changes
+json/changes.json
+
#c9 files
.c9revisions
*tmp
-#minified scripts
-min
-
#node modules folder
node_modules
#temporary files folder
tmp
-#file used by c9
-apache-status
-
-#file used by nodester
-.nodester.appconfig
-
#log file
log.txt
diff --git a/.travis.yml b/.travis.yml
index 015e3dc5..954609f8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,7 @@ language: node_js
node_js:
- 0.6
- 0.8
- - 0.9
+ - 0.10
notifications:
#webhooks:
#http://requestb.in/12h5bl71
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..269eb583
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,16 @@
+If you would like to contribute - send pull request to dev branch.
+Getting dev version of **Cloud Commander**:
+
+ git clone git://github.com/coderaiser/cloudcmd.git
+ git checkout dev
+
+or by [link](https://github.com/coderaiser/cloudcmd/tree/dev "Dev version").
+
+It is possible thet dev version Cloud Commander will needed dev version of Minify,
+so to get it you should type a couple more commands:
+
+ cd node_modules
+ rm -rf minify
+ git clone git://github.com/coderaiser/minify
+ cd minify
+ git checkout dev
diff --git a/ChangeLog b/ChangeLog
index cf2cbab1..65146bfd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,100 @@
-2012.03.01, Version 0.1.9
+2012.04.22, v0.2.0
+
+* Added alerting about errors.
+
+* Removed Listeners array for DOM.
+
+* Added ability create folders.
+
+* Added filepicker.
+
+* Added ability to load files to cloud
+and get them out to file system.
+
+* Added SSL suport.
+
+* jquery updated to v1.9.1.
+
+* Fixed bug with multiple click events on f3 and f4 buttons.
+
+* Added ability to move files.
+
+* Added ability to degradate to http from https.
+
+* Fixed bug of multiple call of sockets.
+
+* If create directory command executed - loading spinner
+would be on top.
+
+* Refactored getShortSize.
+
+* Added update of size on file changing in editor.
+
+* Removed cache control of fs resour.
+
+* Added ability to copy files.
+
+* Fixed bug with saving json to localStorage, it's always
+writed root directory.
+
+* Moved out set current file from cloudfunc to client.js.
+
+* Changed the way file table building. From now templating used.
+
+* Changed sync reading of certs to async.
+
+* Updated dropbox to v0.9.2 and moved to packege.json
+from storage folder.
+
+* Updated socket.io to v0.9.14.
+
+* Fixed Util.time and Util.timeEnd
+
+* Added ability to select files with Insert key.
+
+* Added ability to delete selected files from DOM.
+
+* Added ability to recursivly get current folder size.
+
+* Added ability to get directory size, when space button
+is pressed and current file is directory.
+
+* Added ability to select all files on Ctrl + A
+
+* Fixed the href generation of renamed file.
+
+* Renamed promptNewFolder -> promptNewDir'.
+
+* Added function getSelectedNames.
+
+* Added ability to delete file when f8 key pressed.
+
+* Fixed bug with selectecting root directory with space.
+
+* Fixed bug with processing selected root directory.
+
+* Added ability to delete files.
+
+* Removed modules cache.js.
+
+* Fixed bug with writing new file.
+
+* Updated jquery to v2.0.0.
+
+* Improved CloudFunc module.
+
+* Fixed selection style in opera.
+
+* Fixed header of api fs GET.
+
+* Fixed bug with sending response on
+query other then json on /fs url.
+
+* Fixed bug with getting back to
+directory where file was removed.
+
+
+2012.03.01, v0.1.9
* Changed the way of getting github application id
(now it's just from config, rest api removed).
@@ -192,7 +288,7 @@ CloudCmd REST API.
* Added help screen (on F1 after viewer loads).
-2012.12.12, Version 0.1.8
+2012.12.12, v0.1.8
* Added ability to shutdown Cloud Commander
thru terminal command: "cloudcmd exit"
@@ -385,7 +481,7 @@ Just propose install git and clone from github repo.
* Fixed bug with appcache.
-2012.10.01, Version 0.1.7
+2012.10.01, v0.1.7
* Changed name of menu files, fixed npm and jitsu
problem with menu showing.
@@ -471,7 +567,7 @@ disabled in browsers.
* Added fix of 866 charset.
-2012.08.24, Version 0.1.6
+2012.08.24, v0.1.6
* From now jsload, cssload and anyload suport arrays.
@@ -524,7 +620,7 @@ current, file that was previously current must be unset automatically.
* Added ability to download files.
-2012.08.06, Version 0.1.5
+2012.08.06, v0.1.5
* Added tab support.
@@ -564,7 +660,7 @@ pressed couple times and CodeMirror not loaded fully.
and passive panels and show/hide any of panels.
-2012.07.27, Version 0.1.4
+2012.07.27, v0.1.4
* Added local version of Droids font for offline mode
@@ -600,7 +696,7 @@ be more faster, DOM, short, simple and logical.
* Added ability remove not loaded scripts from DOM.
-2012.07.19, Version 0.1.3
+2012.07.19, v0.1.3
* Fixed bug with nodester (jitsu env.HOME make him go done).
@@ -633,7 +729,7 @@ setted b char: "0b".
* Added supporting of Russian language in directory names.
-2012.07.14, Version 0.1.2
+2012.07.14, v0.1.2
* Added suport of jitsu.
@@ -644,7 +740,7 @@ setted b char: "0b".
* Changed the minimize function calls accroding to Minify 0.1.2 changes.
-2012.07.11, Version 0.1.1
+2012.07.11, v0.1.1
* Added onerror parametr to anyload in Clinet Side, so now we can process situation when
js-script(or something other) has not loaded.
@@ -663,4 +759,4 @@ post-processing functions passed like this {'client.js': function(){}}
* Added ability to read file data from Minify Cache, without writing to disk
* Changed the passing MoreProcessing agrument to jsScripts function Minify module,
-no it passes with a file name, and js file name writing only once.
\ No newline at end of file
+no it passes with a file name, and js file name writing only once.
diff --git a/ChangeLog.rus.md b/ChangeLog.rus.md
index 8541d4f5..84ba0b4f 100644
--- a/ChangeLog.rus.md
+++ b/ChangeLog.rus.md
@@ -1,5 +1,64 @@
-**2012.03.01**
+2012.04.22, v0.2.0
+===============
+Весна в разгаре, на деревьях появляются почки, наконец-то начинает теплеть.
+А это значит, что пришло время выпускать на свободу новую версию Командира.
+Много интересных вещей произошло и изменилось со времени прошлого релиза.
+Сейчас мы рассмотрим поближе, что же именно изменилось. Итак начнём.
+
+**Добавленна внешняя возможность:**
+- Всплывающее сообщение об ошибках
+- Создание папки.
+- FilePicker.
+- загружать файлы в облако и скачивать их в файловую систему.
+- SSL.
+- Перемещения файлов.
+- Перехода на http, если https-сервер запустить не удалось.
+- Если создаётся директория индикатор загрузки будет сверху.
+- Обновления размера файла после изминения оного в редакторе.
+- Копирования файлов.
+- Выделения файлов клавишей Insert.
+- Получения размера текущей папки при нажатии клавиши Space.
+- Выделение всех файлов по Ctrl + A.
+- Удаления файла по F8.
+- Удаления нескольких файлов.
+
+**Исправленные ошибки:**
+- Несколько обработчиков клика по нажатию клавиш F3 и F4.
+- Множественный вызов Sockets.
+- Запись json в localStorage: всегда обновлялось содержимое корневой директории.
+- В функциях Util.time и Util.timeEnd.
+- Генереация href файла, который переименовывается.
+- Выделение коревой директории клавишей Space
+- Обработка выделенной корневой директории.
+- Создание нового файла.
+- Стиль выделения в Опере.
+- Заголовок выдачи REST-фукнции fs метода GET.
+- Отправка данных в ответ на запрос отличный от ?json в пути /url.
+- Возвращение в папку, из которой был удален файл.
+
+**Обновлены:**
+- jquery до версии v2.0.0
+- dropbox до версии v0.9.2
+- socket.io до версии v0.9.14.
+
+**Внутренние изминения:**
+- Удален массив Listeners из модуля DOM.
+- Переделан и оптимизирована функция getShortSize в CloudFunc.
+- Контроль генерации заголовка кеша перенесен в модуль Main.
+- Установка текущего файла перенесена в Client из CloudFunc.
+- Изменён способ построения таблицы файлов. Теперь используются шаблоны.
+- Загрузка SSL-сертификатов теперь асинхронная.
+- Модуль DropBox перенесён в packege.json из папки Storage.
+- Удаления выделеного файла из DOM.
+- Рекурсивного получения размера текущей папки.
+- Переименована функция promptNewFolder -> promptNewDir.
+- Добавлена функция getSelectedNames.
+- Удален модуль Сache.
+- Оптимизирован модуль CloudFunc.
+
+2012.03.01, v0.1.9
+===============
Сегодня, в первый день весны, вышла новая версия облачного менеджера файлов: 0.1.9.
В связи с этим, есть двойной повод порадоватся: наконец, пришла весна,
с полной готовностью согревать серца жителей, после зимних холодов,
diff --git a/README.md b/README.md
index 9a73f3a6..9131212b 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,22 @@
-Cloud Commander [](http://travis-ci.org/coderaiser/cloudcmd)
+Cloud Commander v0.2.0 [![NPM version][NPMIMGURL]][NPMURL] [![Dependency Status][DependencyStatusIMGURL]][DependencyStatusURL] [![Build Status][BuildStatusIMGURL]][BuildStatusURL]
===============
+[![Flattr][FlattrIMGURL]][FlattrURL]
+[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
+[NPMURL]: http://badge.fury.io/js/cloudcmd
+[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
+
**Cloud Commander** - user friendly cloud file manager.
DEMO:
-[cloudfoundry] (http://cloudcmd.cloudfoundry.com "cloudfoundry"),
-[appfog] (http://cloudcmd.aws.af.cm "appfog").
+[cloudfoundry] (https://cloudcmd.cloudfoundry.com "cloudfoundry"),
+[appfog] (https://cloudcmd.aws.af.cm "appfog"),
+[jitsu] (https://cloudcmd.jit.su "jitsu").
-Google PageSpeed Score : [100](http://developers.google.com/speed/pagespeed/insights#url=http_3A_2F_2Fcloudcmd.cloudfoundry.com_2F&mobile=false "score") (out of 100)
+Google PageSpeed Score : [100](//developers.google.com/speed/pagespeed/insights#url=http_3A_2F_2Fcloudcmd.aws.af.cm_2F&mobile=false "score") (out of 100)
(or 96 if js or css minification disabled in config.json).

@@ -40,15 +51,18 @@ There is a short list:
- **Ctrl + d** - clear local cache (wich contains dir contents)
- **Alt + q** - disable key bindings
- **Alt + s** - get all key bindings back
+- **Ctrl + A** - select all files in a panel
- **up, down, enter** - filesystem navigation
- **Tab** - move thru panels
- **Page Up** - up on one page
- **Page Down** - down on one page
- **Home** - to begin of list
- **End** - to end of list
-- **Shift + F10** - show context menu
+- **F8, Delete** - remove current file
+- **Shift + Delete** - remove without prompt
+- **Insert** - select current file
- **F2** - rename current file
-- **Alt + g** - authorization in GitHub
+- **Shift + F10** - show context menu
Viewer's hot keys
---------------
@@ -70,12 +84,8 @@ Right mouse click button show context menu with items:
- Rename
- Delete
- Upload to (Dropbox, Github, GDrive)
-- Downloud
-
-
-Documentation
----------------
-JS Doc documentation could be found in [http://jsdoc.info/coderaiser/cloudcmd/](http://jsdoc.info/coderaiser/cloudcmd/)
+- Download
+- New (File, Dir, from cloud)
Installing
---------------
@@ -107,11 +117,46 @@ All main configuration could be done thrue config.json.
"server" : true, /* server mode or testing mode */
"logs" : false, /* logs or console ouput */
"socket" : true /* enable web sockets */
- "port" : 80, /* Cloud Commander port */
+ "port" : 80, /* http port */
+ "sslPort" : 443, /* https port */
"ip" : "127.0.0.1", /* Cloud Commander IP */
+ "ssl" : true /* should use https? */
"rest" : true /* enable rest interface */
}
```
+
+Server
+---------------
+Standard practices say no non-root process gets to talk to
+the Internet on a port less than 1024. Anyway I suggest you
+to start Cloud Commander as non-root. How it could be solved?
+There is a couple easy and fast ways. One of them is port forwarding by iptables.
+
+```sh
+@:/tmp/cloudcmd (dev) $ su iptables -t nat -L # look rules before
+@:/tmp/cloudcmd (dev) $ su iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8000
+@:/tmp/cloudcmd (dev) $ su iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 4430
+@:/tmp/cloudcmd (dev) $ su iptables -t nat -L # look reles after
+```
+You should see somethins like this ( **8000** and **4430** should be in config as **port** and **sslPort** )
+
+ target prot opt source destination
+ REDIRECT tcp -- anywhere anywhere tcp dpt:http redir ports 8000
+ REDIRECT tcp -- anywhere anywhere tcp dpt:https redir ports 4430
+
+If you would want to get things back just clear rules ( **1** and **2** it's rules numbers,
+in your list they could differ).
+
+```sh
+@:/tmp/cloudcmd (dev) $ su iptables -t nat -D PREROUTING 1
+@:/tmp/cloudcmd (dev) $ su iptables -t nat -D PREROUTING 2
+```
+
+To run Cloud Commander as daemon in linux you could set **log** to true in config and
+do something like this:
+
+ nohup node cloudcmd
+
Authorization
---------------
Thru openID Cloud Commander could authorize clients on GitHub.
@@ -210,6 +255,20 @@ so to get it you should type a couple more commands:
git clone git://github.com/coderaiser/minify
git checkout dev
+Version history
+---------------
+- *2012.04.22*, **[v0.2.0](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.2.0.zip)**
+- *2012.03.01*, **[v0.1.9](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.9.zip)**
+- *2012.12.12*, **[v0.1.8](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.8.zip)**
+- *2012.10.01*, **[v0.1.7](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.7.zip)**
+- *2012.08.24*, **[v0.1.6](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.6.zip)**
+- *2012.08.06*, **[v0.1.5](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.5.zip)**
+- *2012.07.27*, **[v0.1.4](//github.com/coderaiser/cloudcmd-archive/raw/master/cloudcmd-v0.1.4.zip)**
+- *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)**
+
Special Thanks
---------------
[Elena Zalitok](http://vk.com/politilena "Elena Zalitok") for logo.
diff --git a/cloudcmd.js b/cloudcmd.js
index 37ce4d7d..64716bbf 100644
--- a/cloudcmd.js
+++ b/cloudcmd.js
@@ -23,12 +23,21 @@
INDEX = HTMLDIR + 'index.html',
CONFIG_PATH = JSONDIR + 'config.json',
+
+ CA = DIR + 'ssl/sub.class1.server.ca.pem',
+ KEY = DIR + 'ssl/ssl.key',
+ CERT = DIR + 'ssl/ssl.crt',
+
+ FILE_TMPL = HTMLDIR + 'file.html',
+
+ PATH_TMPL = HTMLDIR + 'path.html',
+
+ FileTemplate, PathTemplate,
+
FS = CloudFunc.FS;
-
- /* reinit main dir os if we on
- * Win32 should be backslashes */
+ /* reinit main dir os if we on Win32 should be backslashes */
DIR = main.DIR;
-
+
readConfig(init);
@@ -36,8 +45,7 @@
* additional processing of index file
*/
function indexProcessing(pData){
- var lReplace_s,
- lData = pData.data,
+ var lData = pData.data,
lAdditional = pData.additional;
/*
@@ -46,9 +54,9 @@
* минифицированый
*/
if(Minify.allowed.css){
- var lPath = '/' + Util.removeStr(Minify.MinFolder, DIR);
- lReplace_s = ' ';
- lData = Util.removeStr(lData, lReplace_s)
+ var lPath = '/' + Util.removeStr(Minify.MinFolder, DIR),
+ lReplace = ' ';
+ lData = Util.removeStr(lData, lReplace)
.replace('/css/style.css', lPath + 'all.min.css');
}
@@ -73,9 +81,14 @@
* init and process of appcache if it allowed in config
*/
function appCacheProcessing(){
- var lFiles = [
- {'//themes.googleusercontent.com/static/fonts/droidsansmono/v4/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff' : './font/DroidSansMono.woff'},
- {'//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js' : './lib/client/jquery.js'}];
+ var lFONT_REMOTE = '//themes.googleusercontent.com/static/fonts/droidsansmono/v4/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff',
+ lFONT_LOCAL = './font/DroidSansMono.woff',
+ lJQUERY_REMOTE = 'http://code.jquery.com/jquery-2.0.0.min.js',
+ lJQUERY_LOCAL = './lib/client/jquery.js',
+ lFiles = [{}, {}];
+
+ lFiles[0][lFONT_REMOTE] = lFONT_LOCAL;
+ lFiles[1][lJQUERY_REMOTE] = lJQUERY_LOCAL;
if(Config.minification.css)
lFiles.push('node_modules/minify/min/all.min.css');
@@ -121,7 +134,7 @@
/**
* rest interface
- * @pConnectionData {request, responce}
+ * @pParams pConnectionData {request, responce}
*/
function rest(pConnectionData){
return Util.exec(main.rest, pConnectionData);
@@ -151,8 +164,7 @@
/* if command line parameter testing resolved
* setting config to testing, so server
* not created, just init and
- * all logs writed to screen
- */
+ * all logs writed to screen */
var lArg = process.argv;
lArg = lArg[lArg.length - 1];
if ( lArg === 'test' || lArg === 'test\r') {
@@ -165,22 +177,46 @@
'from now all logs will be writed to log.txt');
writeLogsToFile();
}
- }
- if(Config.server)
- fs.watch(CONFIG_PATH, function(){
- /* every catch up - calling twice */
- setTimeout(function() {
- readConfig();
- }, 1000);
+ if(Config.server)
+ fs.watch(CONFIG_PATH, function(){
+ /* every catch up - calling twice */
+ setTimeout(function() {
+ readConfig();
+ }, 1000);
+ });
+
+ var 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);
+ }
});
-
- server.start({
- appcache : appCacheProcessing,
- minimize : minimize,
- rest : rest,
- route : route
- });
+ }
+ else
+ Util.log('read error: config.json');
}
function readConfig(pCallBack){
@@ -220,12 +256,16 @@
if( Util.strCmp(p.name, ['/auth', '/auth/github']) ){
Util.log('* Routing' +
'-> ' + p.name);
- pParams.name = main.HTMLDIR + p.name + '.html';
- lRet = main.sendFile( pParams );
+
+ pParams.name = main.HTMLDIR + p.name + '.html';
+ lRet = main.sendFile( pParams );
}
- else if( Util.isContainStr(p.name, FS) || Util.strCmp( p.name, '/') ){
- if( Util.isContainStr(p.name, 'no-js/') )
- return noJSTMPRedirection(pParams);
+ else if( Util.isContainStrAtBegin(p.name, FS) || Util.strCmp( p.name, '/') ){
+
+ if( Util.isContainStrAtBegin(p.name, FS + 'no-js/') ){
+ var lURL = Util.removeStr(pParams.name, 'no-js/');
+ return main.redirect(pParams, lURL);
+ }
lRet = sendCommanderContent(p);
}
@@ -241,7 +281,7 @@
var lRet = main.checkParams(pParams);
if(lRet){
var p = pParams;
- p.name = Util.removeStr(p.name, CloudFunc.FS) || main.SLASH;
+ p.name = Util.removeStrOneTime(p.name, CloudFunc.FS) || main.SLASH;
fs.stat(p.name, function(pError, pStat){
if(!pError)
@@ -260,6 +300,7 @@
function processCommanderContent(pParams){
var lRet = main.checkParams(pParams);
+
if(lRet){
var p = pParams;
main.commander.getDirContent(p.name, function(pError, pJSON){
@@ -270,11 +311,11 @@
p.name +='.json';
main.sendResponse(p);
}
- else if(!lQuery){ /* get back html*/
+ else{ /* get back html*/
p.name = Minify.allowed.html ? Minify.getName(INDEX) : INDEX;
fs.readFile(p.name, function(pError, pData){
if(!pError){
- var lPanel = CloudFunc.buildFromJSON(pJSON),
+ var lPanel = CloudFunc.buildFromJSON(pJSON, FileTemplate, PathTemplate),
lList = '
' +
'';
@@ -294,16 +335,6 @@
}
}
- function noJSTMPRedirection(pParams){
- var MOVED_PERMANENTLY = 301,
- lPath = Util.removeStr(pParams.name, 'no-js/');
-
- pParams.response.writeHead(MOVED_PERMANENTLY, {'Location': lPath});
- pParams.response.end();
-
- return true;
- }
-
/* function sets stdout to file log.txt */
function writeLogsToFile(){
diff --git a/css/reset.css b/css/reset.css
index cd411656..17497957 100644
--- a/css/reset.css
+++ b/css/reset.css
@@ -26,7 +26,12 @@ body { margin: 0; font-size: 1em; line-height: 1.4; }
::selection { background: #fe57a1; color: #fff; text-shadow: none; }
*/
::-moz-selection{ text-shadow: none; opacity: 0;}
-::selection { text-shadow: none; opacity: 0;}
+::selection {
+ text-shadow: none;
+ opacity: 0;
+ background-color:white; /* opera */
+}
+
/* =============================================================================
Links
diff --git a/css/style.css b/css/style.css
index ec1a380d..b68f19c2 100644
--- a/css/style.css
+++ b/css/style.css
@@ -1,352 +1,353 @@
-/*
-@import url(//fonts.googleapis.com/css?family=Droid+Sans+Mono);
-*/
-
-/* символьный шрифт от гитхаба*/
-@font-face {
- font-family: "GeneralFoundicons";
- src: url('/font/general_foundicons.woff') format('woff');
- font-weight: normal;
- font-style: normal;
-}
-
-/* http://fontello.com/ */
-@font-face {
- font-family: 'Fontello';
- src: url("/font/fontello.eot");
- src: url("/font/fontello.eot?#iefix") format('embedded-opentype'), url("/font/fontello.woff") format('woff'), url("/font/fontello.ttf") format('truetype'), url("/font/fontello.svg#cloudcmd") format('svg');
- font-weight: normal;
- font-style: normal;
-}
-
-@font-face {
- font-family: 'Droid Sans Mono';
- font-style: normal;
- font-weight: normal;
- src: local('Droid Sans Mono'), local('DroidSansMono'), url('http://themes.googleusercontent.com/static/fonts/droidsansmono/v4/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff') format('woff');
-}
-
-body{
- font:16px "Droid Sans Mono";
- background-color:white;
-}
-
-.path-icon{
- position: relative;
- top: 3px;
- left: -4px;
- display: inline-block;
- /* размер иконки и позиция на png-файле*/
- width: 15px;
- height: 15px;
- font-family:'FoundationIconsGeneralEnclosed';
- font-size:30px;
- color: #46A4C3;/*#55BF3F; green*/
- text-shadow:black 0 2px 1px;
-}
-.path-icon:hover{
- cursor:pointer;
-}
-.path-icon:active{
- position: relative;
- top: 4px;
- text-shadow:black 0 0 1px;
-}
-.icon{
- display:inline-block;
- width:16px;
- height:16px;
- margin-left:0.5%;
- /* font-family: 'GeneralFoundicons'; */
- font-family: 'Fontello';
-}
-.error::before{
- position: relative;
- font-size: 14px;
- color: rgb(222, 41, 41);
- cursor :default;
- content: '\2757';
-}
-.loading{
- position:relative;
- top:1px;
- background:url(/img/spinner.gif);
-}
-.error:hover{
- color:rgb(222, 41, 41);
- color:rgba(222, 41, 41, 0.81);
-}
-.refresh-icon{
- background:url(/img/panel_refresh.png) no-repeat;
-}
-.refresh-icon:active{
- /*background-position-y: -15px;*/
- background:url(/img/panel_refresh.png) 0 -15px no-repeat;
-}
-
-.cmd-button{
- width: 10%;
- margin: 20px 2px 0 2px;
- overflow: hidden;
- color: rgb(49,123,249);
- text-overflow: ellipsis;
- white-space: nowrap;
- background-color: white;
- border: 1.5px solid rgba(49,123,249,.40);
-}
-
-.cmd-button:hover{
- border: 1.5px solid rgb(0,0,0);
-}
-
-.cmd-button:active{
- color: white;
- background-color: rgb(49,123,249);
-}
-
-.clear-cache{
- margin-right: 6px;
- margin-left: 7px;
- background:url(/img/console_clear.png) -4px -4px no-repeat;
-}
-.clear-cache:active{
- top:5px;
-}
-
-.links{
- color:red;
-}
-
-.mini-icon {
- position: relative;
- top: 2px;
- left: -5px;
- float: left;
- width: 16px;
- height: 16px;
- margin-left: 6px;
- /* отступ перед картинкой
- * для нормального отображения
- * рамки
- */
-}
-/* уменьшаем отступ
- * между между иконкой и
- * именем файла во время
- * установления курсора
- */
-.current-file > .mini-icon{
- left: -6px;
-}
-/* freeupex */
-.directory{
- /*list-style-image*/
- background-image:url('/img/dir.png');
- background-position: 0 0;
- background-repeat: no-repeat;
-}
-.text-file{
- /*list-style-image*/
- background-image:url('/img/txt.png');
- background-position: 0 0;
- background-repeat: no-repeat;
-}
-#fm{
- height: 90%;
- margin: 26px 26px 0 26px;
-}
-.fm-header{
- font-weight: bold;
-}
-#path{
- margin-left:1.5%;
-}
-.left, #left{
- float:left;
-}
-/* фон файла, на котором курсор*/
-.current-file{
- border: 1.5px solid rgba(49, 123, 249, .40);
-}
-.selected-file{
- color:white;
- background-color: rgb(49, 123, 249);
- background-color: rgba(49, 123, 249, .40);
-}
-
-.right, #right{
- float:right;
-}
-.panel{
- width: 46%;
- overflow-y: auto;
- border: 1.5px solid rgba(49, 123, 249, .40);
-}
-#keyspanel{
- text-align: center;
-}
-/* информация о файлах и папках*/
-.name{
- float: left;
- width: 37%;
- /* если длина имени файла больше 16 символов
- * отрезаем лишнее, оставляя лишь 16,
- * и добавляем две точки и тайтл
- */
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-.size{
- float:left;
- width:16%;
- /* Ставим отступ, что бы
- * size не налазил на uid
- * (owner)
- */
- margin-right: 27px;
- /* Ставим выравнивание,
- * что бы размер был в
- * одной ровной колонке
- */
- text-align: right;
-}
-.mode{
- float: right;
- width: 25%;
-}
-
-/* changin ul to panel for high speed parsing*/
-.panel, li{
- list-style-type:none;
- /* making cursor just arrow,
- * not text editing cursor
- */
- cursor:default;
-}
-button{
- width:10%;
-}
-a{
- text-decoration:none;
-}
-a:hover, a:active {
- color: #06e;
- cursor:pointer;
-}
-
-/* Если размер окна очень маленький
- * располагаем имя и атрибуты файла
- * друг-под-другом
-*/
-/* responsive design */
-@media only screen and (max-width: 600px){
- .panel{
- width:94% !important;
- }
- /* если правая панель не помещаеться - прячем её */
- #right{
- display:none;
- }
- /* текущий файл под курсором */
- .current-file{
- background-color: rgb(49, 123, 249);
- background-color: rgba(49, 123, 249, .40);
- color:white;
- }
- /* делаем иконки под курсом белыми*/
- .current-file > .mini-icon{
- color:white;
- }
- .current-file > .text-file::before{
- color:white;
- }
-
- .fm-header{
- display:none;
- }
-
- /* меняем иконки на шрифтовые*/
- .mini-icon {
- color: rgb(246, 224, 124);
- color: rgba(246, 224, 124, 0.56);
- font: 60px 'Fontello';
- width: 40%;
- height: 0;
- margin-left: 0;
- float: right;
- position: relative;
- top: 10px
- }
- .directory::before{
- content: '\1f4c1';
- }
- .text-file::before{
- color: rgb(26, 224, 124);
- color: rgba(26, 224, 124, 0.56);
- content: '\1f4c4';
- }
- .text-file{
- background-image:none;
- }
-
- /* убираем заголовок*/
- .fm_header{
- display:none;
- }
- .mode,.size,.owner{
- /* располагаем элементы
- * один под другим
- */
- display: table;
- float: none;
- width: 0;
-
- text-align: left;
- }
- /* выводим заголовки рядом с полями */
- .name::before{
- content: 'name:';
- font-weight: bold;
- font-size: 13px;
- }
- .mode::before{
- content: 'mode:';
- font-weight: bold;
- font-size: 13px;
- }
- .size::before{
- content: 'size:';
- font-weight: bold;
- font-size: 13px;
- }
- .owner::before{
- content: 'owner:';
- font-weight: bold;
- font-size: 13px;
- }
-
- .name{
- float: none;
- width:100%;
- font-size: 18px;
- }
-}
-@media only screen and (min-width: 601px) and (max-width: 785px){
- .panel{
- width:94% !important;
- }
- #right{
- display:none;
- }
-}
-
-@media only screen and (min-width:786px) and (max-width: 1155px){
- .panel{
- width:94% !important;
- }
- /* если правая панель не помещаеться - прячем её */
- #right{
- display:none;
- }
+/*
+@import url(//fonts.googleapis.com/css?family=Droid+Sans+Mono);
+*/
+
+/* символьный шрифт от гитхаба*/
+@font-face {
+ font-family: "GeneralFoundicons";
+ src: url('/font/general_foundicons.woff') format('woff');
+ font-weight: normal;
+ font-style: normal;
+}
+
+/* http://fontello.com/ */
+@font-face {
+ font-family: 'Fontello';
+ src: url("/font/fontello.eot");
+ src: url("/font/fontello.eot?#iefix") format('embedded-opentype'), url("/font/fontello.woff") format('woff'), url("/font/fontello.ttf") format('truetype'), url("/font/fontello.svg#cloudcmd") format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'Droid Sans Mono';
+ font-style: normal;
+ font-weight: normal;
+ src: local('Droid Sans Mono'), local('DroidSansMono'), url('//themes.googleusercontent.com/static/fonts/droidsansmono/v4/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff') format('woff');
+}
+
+body{
+ font:16px "Droid Sans Mono";
+ background-color:white;
+}
+
+.path-icon{
+ position: relative;
+ top: 3px;
+ left: -4px;
+ display: inline-block;
+ /* размер иконки и позиция на png-файле*/
+ width: 15px;
+ height: 15px;
+ font-family:'FoundationIconsGeneralEnclosed';
+ font-size:30px;
+ color: #46A4C3;/*#55BF3F; green*/
+ text-shadow:black 0 2px 1px;
+}
+.path-icon:hover{
+ cursor:pointer;
+}
+.path-icon:active{
+ position: relative;
+ top: 4px;
+ text-shadow:black 0 0 1px;
+}
+.icon{
+ display:inline-block;
+ width:16px;
+ height:16px;
+ margin-left:0.5%;
+ /* font-family: 'GeneralFoundicons'; */
+ font-family: 'Fontello';
+}
+.error::before{
+ position: relative;
+ font-size: 14px;
+ color: rgb(222, 41, 41);
+ cursor :default;
+ content: '\2757';
+}
+.loading{
+ position:relative;
+ top:1px;
+ background:url(/img/spinner.gif);
+}
+.error:hover{
+ color:rgb(222, 41, 41);
+ color:rgba(222, 41, 41, 0.81);
+}
+.refresh-icon{
+ background:url(/img/panel_refresh.png) no-repeat;
+}
+.refresh-icon:active{
+ /*background-position-y: -15px;*/
+ background:url(/img/panel_refresh.png) 0 -15px no-repeat;
+}
+
+.cmd-button{
+ width: 10%;
+ margin: 20px 2px 0 2px;
+ overflow: hidden;
+ color: rgb(49,123,249);
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ background-color: white;
+ border: 1.5px solid rgba(49,123,249,.40);
+}
+
+.cmd-button:hover{
+ border: 1.5px solid rgb(0,0,0);
+}
+
+.cmd-button:active{
+ color: white;
+ background-color: rgb(49,123,249);
+}
+
+.clear-cache{
+ margin-right: 6px;
+ margin-left: 7px;
+ background:url(/img/console_clear.png) -4px -4px no-repeat;
+}
+.clear-cache:active{
+ top:5px;
+}
+
+.links{
+ color:red;
+}
+
+.mini-icon {
+ position: relative;
+ top: 2px;
+ left: -5px;
+ float: left;
+ width: 16px;
+ height: 16px;
+ margin-left: 6px;
+ /* отступ перед картинкой
+ * для нормального отображения
+ * рамки
+ */
+}
+/* уменьшаем отступ
+ * между между иконкой и
+ * именем файла во время
+ * установления курсора
+ */
+.current-file > .mini-icon{
+ left: -6px;
+}
+/* freeupex */
+.directory{
+ /*list-style-image*/
+ background-image:url('/img/dir.png');
+ background-position: 0 0;
+ background-repeat: no-repeat;
+}
+.text-file{
+ /*list-style-image*/
+ background-image:url('/img/txt.png');
+ background-position: 0 0;
+ background-repeat: no-repeat;
+}
+#fm{
+ height: 90%;
+ margin: 26px 26px 0 26px;
+}
+.fm-header{
+ font-weight: bold;
+}
+#path{
+ margin-left:1.5%;
+}
+.left, #left{
+ float:left;
+}
+
+/* фон файла, на котором курсор*/
+.current-file{
+ border: 1.5px solid rgba(49, 123, 249, .40);
+}
+
+.selected-file, .selected-file .name > a{
+ color: rgb(254,159,224);
+}
+
+.right, #right{
+ float:right;
+}
+.panel{
+ width: 46%;
+ overflow-y: auto;
+ border: 1.5px solid rgba(49, 123, 249, .40);
+}
+#keyspanel{
+ text-align: center;
+}
+
+/* информация о файлах и папках*/
+.name{
+ float: left;
+ width: 37%;
+ /* если длина имени файла больше 16 символов
+ * отрезаем лишнее, оставляя лишь 16,
+ * и добавляем две точки и тайтл
+ */
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.size{
+ float:left;
+ width:16%;
+ /* Ставим отступ, что бы
+ * size не налазил на uid
+ * (owner)
+ */
+ margin-right: 27px;
+ /* Ставим выравнивание,
+ * что бы размер был в
+ * одной ровной колонке
+ */
+ text-align: right;
+}
+.mode{
+ float: right;
+ width: 25%;
+}
+
+/* changin ul to panel for high speed parsing*/
+.panel, li{
+ list-style-type:none;
+ /* making cursor just arrow,
+ * not text editing cursor
+ */
+ cursor:default;
+}
+button{
+ width:10%;
+}
+a{
+ text-decoration:none;
+}
+a:hover, a:active {
+ color: #06e;
+ cursor:pointer;
+}
+
+/* Если размер окна очень маленький
+ * располагаем имя и атрибуты файла
+ * друг-под-другом
+*/
+/* responsive design */
+@media only screen and (max-width: 600px){
+ .panel{
+ width:94% !important;
+ }
+ /* если правая панель не помещаеться - прячем её */
+ #right{
+ display:none;
+ }
+ /* текущий файл под курсором */
+ .current-file{
+ background-color: rgb(49, 123, 249);
+ background-color: rgba(49, 123, 249, .40);
+ color:white;
+ }
+ /* делаем иконки под курсом белыми*/
+ .current-file > .mini-icon{
+ color:white;
+ }
+ .current-file > .text-file::before{
+ color:white;
+ }
+
+ .fm-header{
+ display:none;
+ }
+
+ /* меняем иконки на шрифтовые*/
+ .mini-icon {
+ color: rgb(246, 224, 124);
+ color: rgba(246, 224, 124, 0.56);
+ font: 60px 'Fontello';
+ width: 40%;
+ height: 0;
+ margin-left: 0;
+ float: right;
+ position: relative;
+ top: 10px
+ }
+ .directory::before{
+ content: '\1f4c1';
+ }
+ .text-file::before{
+ color: rgb(26, 224, 124);
+ color: rgba(26, 224, 124, 0.56);
+ content: '\1f4c4';
+ }
+ .text-file{
+ background-image:none;
+ }
+
+ /* убираем заголовок*/
+ .fm_header{
+ display:none;
+ }
+ .mode,.size,.owner{
+ /* располагаем элементы
+ * один под другим
+ */
+ display: table;
+ float: none;
+ width: 0;
+
+ text-align: left;
+ }
+ /* выводим заголовки рядом с полями */
+ .name::before{
+ content: 'name:';
+ font-weight: bold;
+ font-size: 13px;
+ }
+ .mode::before{
+ content: 'mode:';
+ font-weight: bold;
+ font-size: 13px;
+ }
+ .size::before{
+ content: 'size:';
+ font-weight: bold;
+ font-size: 13px;
+ }
+ .owner::before{
+ content: 'owner:';
+ font-weight: bold;
+ font-size: 13px;
+ }
+
+ .name{
+ float: none;
+ width:100%;
+ font-size: 18px;
+ }
+}
+@media only screen and (min-width: 601px) and (max-width: 785px){
+ .panel{
+ width:94% !important;
+ }
+ #right{
+ display:none;
+ }
+}
+
+@media only screen and (min-width:786px) and (max-width: 1155px){
+ .panel{
+ width:94% !important;
+ }
+ /* если правая панель не помещаеться - прячем её */
+ #right{
+ display:none;
+ }
}
\ No newline at end of file
diff --git a/html/auth/dropbox.html b/html/auth/dropbox.html
index cc702b56..51478866 100644
--- a/html/auth/dropbox.html
+++ b/html/auth/dropbox.html
@@ -1,7 +1,7 @@
-
+
-```
-
-The snippet is not a typo. [cdnjs](https://cdnjs.com) recommends using
-[protocol-relative URLs](http://paulirish.com/2010/the-protocol-relative-url/).
-
-To get the latest development build of dropbox.js, follow the steps in the
-[development guide](https://github.com/dropbox/dropbox-js/blob/master/doc/development.md).
-
-
-#### "Powered by Dropbox" Static Web Apps
-
-Before writing any source code, use the
-[console app](https://dl-web.dropbox.com/spa/pjlfdak1tmznswp/powered_by.js/public/index.html)
-to set up your Dropbox. After adding an application, place the source code at
-`/Apps/Static Web Apps/my_awesome_app/public`. You should find a pre-generated
-`index.html` file in there.
-
-### node.js Applications
-
-First, install the `dropbox` [npm](https://npmjs.org/) package.
-
-```bash
-npm install dropbox
-```
-
-Once the npm package is installed, the following `require` statement lets you
-access the same API as browser applications
-
-```javascript
-var Dropbox = require("dropbox");
-```
-
-
-## Initialization
-
-[Register your application](https://www.dropbox.com/developers/apps) to obtain
-an API key. Read the brief
-[API core concepts intro](https://www.dropbox.com/developers/start/core).
-
-Once you have an API key, use it to create a `Dropbox.Client`.
-
-```javascript
-var client = new Dropbox.Client({
- key: "your-key-here", secret: "your-secret-here", sandbox: true
-});
-```
-
-If your application requires full Dropbox access, leave out the `sandbox: true`
-parameter.
-
-
-### Browser and Open-Source Applications
-
-The Dropbox API guidelines ask that the API key and secret is never exposed in
-cleartext. This is an issue for browser-side and open-source applications.
-
-To meet this requirement,
-[encode your API key](https://dl-web.dropbox.com/spa/pjlfdak1tmznswp/api_keys.js/public/index.html)
-and pass the encoded key string to the `Dropbox.Client` constructor.
-
-```javascript
-var client = new Dropbox.Client({
- key: "encoded-key-string|it-is-really-really-long", sandbox: true
-});
-```
-
-
-## Authentication
-
-Before you can make any API calls, you need to authenticate your application's
-user with Dropbox, and have them authorize your app's to access their Dropbox.
-
-This process follows the [OAuth 1.0](http://tools.ietf.org/html/rfc5849)
-protocol, which entails sending the user to a Web page on `www.dropbox.com`,
-and then having them redirected back to your application. Each Web application
-has its requirements, so `dropbox.js` lets you customize the authentication
-process by implementing an
-[OAuth driver](https://github.com/dropbox/dropbox-js/blob/master/src/drivers.coffee).
-
-At the same time, dropbox.js ships with a couple of OAuth drivers, and you
-should take advantage of them as you prototype your application.
-
-Read the
-[authentication doc](https://github.com/dropbox/dropbox-js/blob/master/doc/auth_drivers.md)
-for further information about writing an OAuth driver, and to learn about all
-the drivers that ship with `dropbox.js`.
-
-### Browser Setup
-
-The following snippet will set up the recommended driver.
-
-```javascript
-client.authDriver(new Dropbox.Drivers.Redirect());
-```
-
-The
-[authentication doc](https://github.com/dropbox/dropbox-js/blob/master/doc/auth_drivers.md)
-describes some useful options that you can pass to the
-`Dropbox.Drivers.Redirect` constructor.
-
-### node.js Setup
-
-Single-process node.js applications should create one driver to authenticate
-all the clients.
-
-```javascript
-client.authDriver(new Dropbox.Drivers.NodeServer(8191));
-```
-
-The
-[authentication doc](https://github.com/dropbox/dropbox-js/blob/master/doc/auth_drivers.md)
-has useful tips on using the `NodeServer` driver.
-
-### Shared Code
-
-After setting up an OAuth driver, authenticating the user is one method call
-away.
-
-```javascript
-client.authenticate(function(error, client) {
- if (error) {
- // Replace with a call to your own error-handling code.
- //
- // Don't forget to return from the callback, so you don't execute the code
- // that assumes everything went well.
- return showError(error);
- }
-
- // Replace with a call to your own application code.
- //
- // The user authorized your app, and everything went well.
- // client is a Dropbox.Client instance that you can use to make API calls.
- doSomethingCool(client);
-});
-```
-
-## Error Handlng
-
-When Dropbox API calls fail, dropbox.js methods pass a `Dropbox.ApiError`
-instance as the first parameter in their callbacks. This parameter is named
-`error` in all the code snippets on this page.
-
-If `error` is a truthy value, you should either recover from the error, or
-notify the user that an error occurred. The `status` field in the
-`Dropbox.ApiError` instance contains the HTTP error code, which should be one
-of the
-[error codes in the REST API](https://www.dropbox.com/developers/reference/api#error-handling).
-
-The snippet below is a template for an extensive error handler.
-
-```javascript
-var showError = function(error) {
- switch (error.status) {
- case 401:
- // If you're using dropbox.js, the only cause behind this error is that
- // the user token expired.
- // Get the user through the authentication flow again.
- break;
-
- case 404:
- // The file or folder you tried to access is not in the user's Dropbox.
- // Handling this error is specific to your application.
- break;
-
- case 507:
- // The user is over their Dropbox quota.
- // Tell them their Dropbox is full. Refreshing the page won't help.
- break;
-
- case 503:
- // Too many API requests. Tell the user to try again later.
- // Long-term, optimize your code to use fewer API calls.
- break;
-
- case 400: // Bad input parameter
- case 403: // Bad OAuth request.
- case 405: // Request method not expected
- default:
- // Caused by a bug in dropbox.js, in your application, or in Dropbox.
- // Tell the user an error occurred, ask them to refresh the page.
- }
-};
-```
-
-`Dropbox.Client` also supports a DOM event-like API for receiving all errors.
-This can be used to log API errors, or to upload them to your server for
-further analysis.
-
-```javascript
-client.onError.addListener(function(error) {
- if (window.console) { // Skip the "if" in node.js code.
- console.error(error);
- }
-});
-```
-
-
-## The Fun Part
-
-Authentication was the hard part of the API integration, and error handling was
-the most boring part. Now that these are both behind us, you can interact
-with the user's Dropbox and focus on coding up your application!
-
-The following sections have some commonly used code snippets. The
-[Dropbox.Client API reference](http://coffeedoc.info/github/dropbox/dropbox-js/master/classes/Dropbox/Client.html)
-will help you navigate less common scenarios, and the
-[Dropbox REST API reference](https://www.dropbox.com/developers/reference/api)
-describes the underlying HTTP protocol, and can come in handy when debugging
-your application, or if you want to extend dropbox.js.
-
-### User Info
-
-```javascript
-client.getUserInfo(function(error, userInfo) {
- if (error) {
- return showError(error); // Something went wrong.
- }
-
- alert("Hello, " + userInfo.name + "!");
-});
-```
-
-### Write a File
-
-```javascript
-client.writeFile("hello_world.txt", "Hello, world!\n", function(error, stat) {
- if (error) {
- return showError(error); // Something went wrong.
- }
-
- alert("File saved as revision " + stat.revisionTag);
-});
-```
-
-### Read a File
-
-```javascript
-client.readFile("hello_world.txt", function(error, data) {
- if (error) {
- return showError(error); // Something went wrong.
- }
-
- alert(data); // data has the file's contents
-});
-```
-
-### List a Directory's Contents
-
-```javascript
-client.readdir("/", function(error, entries) {
- if (error) {
- return showError(error); // Something went wrong.
- }
-
- alert("Your Dropbox contains " + entries.join(", "));
-});
-```
-
-### Sample Applications
-
-Check out the
-[sample apps](https://github.com/dropbox/dropbox-js/tree/master/samples)
-to see how all these concepts play out together.
-
diff --git a/lib/client/storage/dropbox/lib/README.md b/lib/client/storage/dropbox/lib/README.md
deleted file mode 100644
index 6a273731..00000000
--- a/lib/client/storage/dropbox/lib/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# dropbox.js Build Directory
-
-dropbox.js is written in [CoffeeScript](http://coffeescript.org/), and its
-source code is in the `src/` directory. The `lib/` directory contains the
-compiled JavaScript produced by the build process.
-
-The
-[development guide](https://github.com/dropbox/dropbox-js/blob/master/doc/development.md)
-contains a step-by-step guide to the library's build process, and will help you
-populate this directory.
diff --git a/lib/client/storage/dropbox/lib/dropbox.js b/lib/client/storage/dropbox/lib/dropbox.js
deleted file mode 100644
index 05a073aa..00000000
--- a/lib/client/storage/dropbox/lib/dropbox.js
+++ /dev/null
@@ -1,2925 +0,0 @@
-// Generated by CoffeeScript 1.4.0
-(function() {
- var Dropbox, DropboxChromeOnMessage, DropboxChromeSendMessage, DropboxClient, DropboxXhrArrayBufferView, DropboxXhrCanSendForms, DropboxXhrDoesPreflight, DropboxXhrIeMode, DropboxXhrRequest, DropboxXhrSendArrayBufferView, add32, arrayToBase64, atob, atobNibble, base64Digits, base64HmacSha1, base64Sha1, btoa, btoaNibble, crypto, dropboxEncodeKey, hmacSha1, rotateLeft32, sha1, stringToArray, _base64Digits,
- __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
- __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
-
- Dropbox = (function() {
-
- function Dropbox(options) {
- this.client = new DropboxClient(options);
- }
-
- return Dropbox;
-
- })();
-
- Dropbox.ApiError = (function() {
-
- ApiError.prototype.status = void 0;
-
- ApiError.prototype.method = void 0;
-
- ApiError.prototype.url = void 0;
-
- ApiError.prototype.responseText = void 0;
-
- ApiError.prototype.response = void 0;
-
- function ApiError(xhr, method, url) {
- var text;
- this.method = method;
- this.url = url;
- this.status = xhr.status;
- if (xhr.responseType) {
- try {
- text = xhr.response || xhr.responseText;
- } catch (e) {
- try {
- text = xhr.responseText;
- } catch (e) {
- text = null;
- }
- }
- } else {
- try {
- text = xhr.responseText;
- } catch (e) {
- text = null;
- }
- }
- if (text) {
- try {
- this.responseText = text.toString();
- this.response = JSON.parse(text);
- } catch (e) {
- this.response = null;
- }
- } else {
- this.responseText = '(no response)';
- this.response = null;
- }
- }
-
- ApiError.prototype.toString = function() {
- return "Dropbox API error " + this.status + " from " + this.method + " " + this.url + " :: " + this.responseText;
- };
-
- ApiError.prototype.inspect = function() {
- return this.toString();
- };
-
- return ApiError;
-
- })();
-
- if (typeof window !== "undefined" && window !== null) {
- if (window.atob && window.btoa) {
- atob = function(string) {
- return window.atob(string);
- };
- btoa = function(base64) {
- return window.btoa(base64);
- };
- } else {
- base64Digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
- btoaNibble = function(accumulator, bytes, result) {
- var i, limit;
- limit = 3 - bytes;
- accumulator <<= limit * 8;
- i = 3;
- while (i >= limit) {
- result.push(base64Digits.charAt((accumulator >> (i * 6)) & 0x3F));
- i -= 1;
- }
- i = bytes;
- while (i < 3) {
- result.push('=');
- i += 1;
- }
- return null;
- };
- atobNibble = function(accumulator, digits, result) {
- var i, limit;
- limit = 4 - digits;
- accumulator <<= limit * 6;
- i = 2;
- while (i >= limit) {
- result.push(String.fromCharCode((accumulator >> (8 * i)) & 0xFF));
- i -= 1;
- }
- return null;
- };
- btoa = function(string) {
- var accumulator, bytes, i, result, _i, _ref;
- result = [];
- accumulator = 0;
- bytes = 0;
- for (i = _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- accumulator = (accumulator << 8) | string.charCodeAt(i);
- bytes += 1;
- if (bytes === 3) {
- btoaNibble(accumulator, bytes, result);
- accumulator = bytes = 0;
- }
- }
- if (bytes > 0) {
- btoaNibble(accumulator, bytes, result);
- }
- return result.join('');
- };
- atob = function(base64) {
- var accumulator, digit, digits, i, result, _i, _ref;
- result = [];
- accumulator = 0;
- digits = 0;
- for (i = _i = 0, _ref = base64.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- digit = base64.charAt(i);
- if (digit === '=') {
- break;
- }
- accumulator = (accumulator << 6) | base64Digits.indexOf(digit);
- digits += 1;
- if (digits === 4) {
- atobNibble(accumulator, digits, result);
- accumulator = digits = 0;
- }
- }
- if (digits > 0) {
- atobNibble(accumulator, digits, result);
- }
- return result.join('');
- };
- }
- } else {
- atob = function(arg) {
- var buffer, i;
- buffer = new Buffer(arg, 'base64');
- return ((function() {
- var _i, _ref, _results;
- _results = [];
- for (i = _i = 0, _ref = buffer.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- _results.push(String.fromCharCode(buffer[i]));
- }
- return _results;
- })()).join('');
- };
- btoa = function(arg) {
- var buffer, i;
- buffer = new Buffer((function() {
- var _i, _ref, _results;
- _results = [];
- for (i = _i = 0, _ref = arg.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- _results.push(arg.charCodeAt(i));
- }
- return _results;
- })());
- return buffer.toString('base64');
- };
- }
-
- Dropbox.Client = (function() {
-
- function Client(options) {
- this.sandbox = options.sandbox || false;
- this.apiServer = options.server || this.defaultApiServer();
- this.authServer = options.authServer || this.defaultAuthServer();
- this.fileServer = options.fileServer || this.defaultFileServer();
- this.downloadServer = options.downloadServer || this.defaultDownloadServer();
- this.onXhr = new Dropbox.EventSource({
- cancelable: true
- });
- this.onError = new Dropbox.EventSource;
- this.onAuthStateChange = new Dropbox.EventSource;
- this.oauth = new Dropbox.Oauth(options);
- this.driver = null;
- this.filter = null;
- this.uid = null;
- this.authState = null;
- this.authError = null;
- this._credentials = null;
- this.setCredentials(options);
- this.setupUrls();
- }
-
- Client.prototype.authDriver = function(driver) {
- this.driver = driver;
- return this;
- };
-
- Client.prototype.onXhr = null;
-
- Client.prototype.onError = null;
-
- Client.prototype.onAuthStateChange = null;
-
- Client.prototype.dropboxUid = function() {
- return this.uid;
- };
-
- Client.prototype.credentials = function() {
- if (!this._credentials) {
- this.computeCredentials();
- }
- return this._credentials;
- };
-
- Client.prototype.authenticate = function(callback) {
- var oldAuthState, _fsmStep,
- _this = this;
- oldAuthState = null;
- if (!(this.driver || this.authState === DropboxClient.DONE)) {
- throw new Error("Call authDriver to set an authentication driver");
- }
- _fsmStep = function() {
- var authUrl;
- if (oldAuthState !== _this.authState) {
- if (oldAuthState !== null) {
- _this.onAuthStateChange.dispatch(_this);
- }
- oldAuthState = _this.authState;
- if (_this.driver && _this.driver.onAuthStateChange) {
- return _this.driver.onAuthStateChange(_this, _fsmStep);
- }
- }
- switch (_this.authState) {
- case DropboxClient.RESET:
- return _this.requestToken(function(error, data) {
- var token, tokenSecret;
- if (error) {
- _this.authError = error;
- _this.authState = DropboxClient.ERROR;
- } else {
- token = data.oauth_token;
- tokenSecret = data.oauth_token_secret;
- _this.oauth.setToken(token, tokenSecret);
- _this.authState = DropboxClient.REQUEST;
- }
- _this._credentials = null;
- return _fsmStep();
- });
- case DropboxClient.REQUEST:
- authUrl = _this.authorizeUrl(_this.oauth.token);
- return _this.driver.doAuthorize(authUrl, _this.oauth.token, _this.oauth.tokenSecret, function() {
- _this.authState = DropboxClient.AUTHORIZED;
- _this._credentials = null;
- return _fsmStep();
- });
- case DropboxClient.AUTHORIZED:
- return _this.getAccessToken(function(error, data) {
- if (error) {
- _this.authError = error;
- _this.authState = DropboxClient.ERROR;
- } else {
- _this.oauth.setToken(data.oauth_token, data.oauth_token_secret);
- _this.uid = data.uid;
- _this.authState = DropboxClient.DONE;
- }
- _this._credentials = null;
- return _fsmStep();
- });
- case DropboxClient.DONE:
- return callback(null, _this);
- case DropboxClient.SIGNED_OFF:
- _this.authState = DropboxClient.RESET;
- _this.reset();
- return _fsmStep();
- case DropboxClient.ERROR:
- return callback(_this.authError);
- }
- };
- _fsmStep();
- return this;
- };
-
- Client.prototype.isAuthenticated = function() {
- return this.authState === DropboxClient.DONE;
- };
-
- Client.prototype.signOut = function(callback) {
- var xhr,
- _this = this;
- xhr = new Dropbox.Xhr('POST', this.urls.signOut);
- xhr.signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error) {
- if (error) {
- return callback(error);
- }
- _this.authState = DropboxClient.RESET;
- _this.reset();
- _this.authState = DropboxClient.SIGNED_OFF;
- _this.onAuthStateChange.dispatch(_this);
- if (_this.driver.onAuthStateChange) {
- return _this.driver.onAuthStateChange(_this, function() {
- return callback(error);
- });
- } else {
- return callback(error);
- }
- });
- };
-
- Client.prototype.signOff = function(callback) {
- return this.signOut(callback);
- };
-
- Client.prototype.getUserInfo = function(options, callback) {
- var httpCache, xhr;
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- httpCache = false;
- if (options && options.httpCache) {
- httpCache = true;
- }
- xhr = new Dropbox.Xhr('GET', this.urls.accountInfo);
- xhr.signWithOauth(this.oauth, httpCache);
- return this.dispatchXhr(xhr, function(error, userData) {
- return callback(error, Dropbox.UserInfo.parse(userData), userData);
- });
- };
-
- Client.prototype.readFile = function(path, options, callback) {
- var httpCache, params, rangeEnd, rangeHeader, rangeStart, responseType, xhr;
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- params = {};
- responseType = null;
- rangeHeader = null;
- httpCache = false;
- if (options) {
- if (options.versionTag) {
- params.rev = options.versionTag;
- } else if (options.rev) {
- params.rev = options.rev;
- }
- if (options.arrayBuffer) {
- responseType = 'arraybuffer';
- } else if (options.blob) {
- responseType = 'blob';
- } else if (options.binary) {
- responseType = 'b';
- }
- if (options.length) {
- if (options.start != null) {
- rangeStart = options.start;
- rangeEnd = options.start + options.length - 1;
- } else {
- rangeStart = '';
- rangeEnd = options.length;
- }
- rangeHeader = "bytes=" + rangeStart + "-" + rangeEnd;
- } else if (options.start != null) {
- rangeHeader = "bytes=" + options.start + "-";
- }
- if (options.httpCache) {
- httpCache = true;
- }
- }
- xhr = new Dropbox.Xhr('GET', "" + this.urls.getFile + "/" + (this.urlEncodePath(path)));
- xhr.setParams(params).signWithOauth(this.oauth, httpCache);
- xhr.setResponseType(responseType);
- if (rangeHeader) {
- xhr.setHeader('Range', rangeHeader);
- }
- return this.dispatchXhr(xhr, function(error, data, metadata) {
- return callback(error, data, Dropbox.Stat.parse(metadata));
- });
- };
-
- Client.prototype.writeFile = function(path, data, options, callback) {
- var useForm;
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- useForm = Dropbox.Xhr.canSendForms && typeof data === 'object';
- if (useForm) {
- return this.writeFileUsingForm(path, data, options, callback);
- } else {
- return this.writeFileUsingPut(path, data, options, callback);
- }
- };
-
- Client.prototype.writeFileUsingForm = function(path, data, options, callback) {
- var fileName, params, slashIndex, xhr;
- slashIndex = path.lastIndexOf('/');
- if (slashIndex === -1) {
- fileName = path;
- path = '';
- } else {
- fileName = path.substring(slashIndex);
- path = path.substring(0, slashIndex);
- }
- params = {
- file: fileName
- };
- if (options) {
- if (options.noOverwrite) {
- params.overwrite = 'false';
- }
- if (options.lastVersionTag) {
- params.parent_rev = options.lastVersionTag;
- } else if (options.parentRev || options.parent_rev) {
- params.parent_rev = options.parentRev || options.parent_rev;
- }
- }
- xhr = new Dropbox.Xhr('POST', "" + this.urls.postFile + "/" + (this.urlEncodePath(path)));
- xhr.setParams(params).signWithOauth(this.oauth).setFileField('file', fileName, data, 'application/octet-stream');
- delete params.file;
- return this.dispatchXhr(xhr, function(error, metadata) {
- return callback(error, Dropbox.Stat.parse(metadata));
- });
- };
-
- Client.prototype.writeFileUsingPut = function(path, data, options, callback) {
- var params, xhr;
- params = {};
- if (options) {
- if (options.noOverwrite) {
- params.overwrite = 'false';
- }
- if (options.lastVersionTag) {
- params.parent_rev = options.lastVersionTag;
- } else if (options.parentRev || options.parent_rev) {
- params.parent_rev = options.parentRev || options.parent_rev;
- }
- }
- xhr = new Dropbox.Xhr('POST', "" + this.urls.putFile + "/" + (this.urlEncodePath(path)));
- xhr.setBody(data).setParams(params).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- return callback(error, Dropbox.Stat.parse(metadata));
- });
- };
-
- Client.prototype.resumableUploadStep = function(data, cursor, callback) {
- var params, xhr;
- if (cursor) {
- params = {
- offset: cursor.offset
- };
- if (cursor.tag) {
- params.upload_id = cursor.tag;
- }
- } else {
- params = {
- offset: 0
- };
- }
- xhr = new Dropbox.Xhr('POST', this.urls.chunkedUpload);
- xhr.setBody(data).setParams(params).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, cursor) {
- if (error && error.status === 400 && error.response.upload_id && error.response.offset) {
- return callback(null, Dropbox.UploadCursor.parse(error.response));
- } else {
- return callback(error, Dropbox.UploadCursor.parse(cursor));
- }
- });
- };
-
- Client.prototype.resumableUploadFinish = function(path, cursor, options, callback) {
- var params, xhr;
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- params = {
- upload_id: cursor.tag
- };
- if (options) {
- if (options.lastVersionTag) {
- params.parent_rev = options.lastVersionTag;
- } else if (options.parentRev || options.parent_rev) {
- params.parent_rev = options.parentRev || options.parent_rev;
- }
- if (options.noOverwrite) {
- params.autorename = true;
- }
- }
- xhr = new Dropbox.Xhr('POST', "" + this.urls.commitChunkedUpload + "/" + (this.urlEncodePath(path)));
- xhr.setParams(params).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- return callback(error, Dropbox.Stat.parse(metadata));
- });
- };
-
- Client.prototype.stat = function(path, options, callback) {
- var httpCache, params, xhr;
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- params = {};
- httpCache = false;
- if (options) {
- if (options.version != null) {
- params.rev = options.version;
- }
- if (options.removed || options.deleted) {
- params.include_deleted = 'true';
- }
- if (options.readDir) {
- params.list = 'true';
- if (options.readDir !== true) {
- params.file_limit = options.readDir.toString();
- }
- }
- if (options.cacheHash) {
- params.hash = options.cacheHash;
- }
- if (options.httpCache) {
- httpCache = true;
- }
- }
- params.include_deleted || (params.include_deleted = 'false');
- params.list || (params.list = 'false');
- xhr = new Dropbox.Xhr('GET', "" + this.urls.metadata + "/" + (this.urlEncodePath(path)));
- xhr.setParams(params).signWithOauth(this.oauth, httpCache);
- return this.dispatchXhr(xhr, function(error, metadata) {
- var entries, entry, stat;
- stat = Dropbox.Stat.parse(metadata);
- if (metadata != null ? metadata.contents : void 0) {
- entries = (function() {
- var _i, _len, _ref, _results;
- _ref = metadata.contents;
- _results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- entry = _ref[_i];
- _results.push(Dropbox.Stat.parse(entry));
- }
- return _results;
- })();
- } else {
- entries = void 0;
- }
- return callback(error, stat, entries);
- });
- };
-
- Client.prototype.readdir = function(path, options, callback) {
- var statOptions;
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- statOptions = {
- readDir: true
- };
- if (options) {
- if (options.limit != null) {
- statOptions.readDir = options.limit;
- }
- if (options.versionTag) {
- statOptions.versionTag = options.versionTag;
- }
- if (options.removed || options.deleted) {
- statOptions.removed = options.removed || options.deleted;
- }
- if (options.httpCache) {
- statOptions.httpCache = options.httpCache;
- }
- }
- return this.stat(path, statOptions, function(error, stat, entry_stats) {
- var entries, entry_stat;
- if (entry_stats) {
- entries = (function() {
- var _i, _len, _results;
- _results = [];
- for (_i = 0, _len = entry_stats.length; _i < _len; _i++) {
- entry_stat = entry_stats[_i];
- _results.push(entry_stat.name);
- }
- return _results;
- })();
- } else {
- entries = null;
- }
- return callback(error, entries, stat, entry_stats);
- });
- };
-
- Client.prototype.metadata = function(path, options, callback) {
- return this.stat(path, options, callback);
- };
-
- Client.prototype.makeUrl = function(path, options, callback) {
- var isDirect, params, url, useDownloadHack, xhr;
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- if (options && (options['long'] || options.longUrl || options.downloadHack)) {
- params = {
- short_url: 'false'
- };
- } else {
- params = {};
- }
- path = this.urlEncodePath(path);
- url = "" + this.urls.shares + "/" + path;
- isDirect = false;
- useDownloadHack = false;
- if (options) {
- if (options.downloadHack) {
- isDirect = true;
- useDownloadHack = true;
- } else if (options.download) {
- isDirect = true;
- url = "" + this.urls.media + "/" + path;
- }
- }
- xhr = new Dropbox.Xhr('POST', url).setParams(params).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, urlData) {
- if (useDownloadHack && urlData && urlData.url) {
- urlData.url = urlData.url.replace(this.authServer, this.downloadServer);
- }
- return callback(error, Dropbox.PublicUrl.parse(urlData, isDirect));
- });
- };
-
- Client.prototype.history = function(path, options, callback) {
- var httpCache, params, xhr;
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- params = {};
- httpCache = false;
- if (options) {
- if (options.limit != null) {
- params.rev_limit = options.limit;
- }
- if (options.httpCache) {
- httpCache = true;
- }
- }
- xhr = new Dropbox.Xhr('GET', "" + this.urls.revisions + "/" + (this.urlEncodePath(path)));
- xhr.setParams(params).signWithOauth(this.oauth, httpCache);
- return this.dispatchXhr(xhr, function(error, versions) {
- var metadata, stats;
- if (versions) {
- stats = (function() {
- var _i, _len, _results;
- _results = [];
- for (_i = 0, _len = versions.length; _i < _len; _i++) {
- metadata = versions[_i];
- _results.push(Dropbox.Stat.parse(metadata));
- }
- return _results;
- })();
- } else {
- stats = void 0;
- }
- return callback(error, stats);
- });
- };
-
- Client.prototype.revisions = function(path, options, callback) {
- return this.history(path, options, callback);
- };
-
- Client.prototype.thumbnailUrl = function(path, options) {
- var xhr;
- xhr = this.thumbnailXhr(path, options);
- return xhr.paramsToUrl().url;
- };
-
- Client.prototype.readThumbnail = function(path, options, callback) {
- var responseType, xhr;
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- responseType = 'b';
- if (options) {
- if (options.blob) {
- responseType = 'blob';
- }
- }
- xhr = this.thumbnailXhr(path, options);
- xhr.setResponseType(responseType);
- return this.dispatchXhr(xhr, function(error, data, metadata) {
- return callback(error, data, Dropbox.Stat.parse(metadata));
- });
- };
-
- Client.prototype.thumbnailXhr = function(path, options) {
- var params, xhr;
- params = {};
- if (options) {
- if (options.format) {
- params.format = options.format;
- } else if (options.png) {
- params.format = 'png';
- }
- if (options.size) {
- params.size = options.size;
- }
- }
- xhr = new Dropbox.Xhr('GET', "" + this.urls.thumbnails + "/" + (this.urlEncodePath(path)));
- return xhr.setParams(params).signWithOauth(this.oauth);
- };
-
- Client.prototype.revertFile = function(path, versionTag, callback) {
- var xhr;
- xhr = new Dropbox.Xhr('POST', "" + this.urls.restore + "/" + (this.urlEncodePath(path)));
- xhr.setParams({
- rev: versionTag
- }).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- return callback(error, Dropbox.Stat.parse(metadata));
- });
- };
-
- Client.prototype.restore = function(path, versionTag, callback) {
- return this.revertFile(path, versionTag, callback);
- };
-
- Client.prototype.findByName = function(path, namePattern, options, callback) {
- var httpCache, params, xhr;
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- params = {
- query: namePattern
- };
- httpCache = false;
- if (options) {
- if (options.limit != null) {
- params.file_limit = options.limit;
- }
- if (options.removed || options.deleted) {
- params.include_deleted = true;
- }
- if (options.httpCache) {
- httpCache = true;
- }
- }
- xhr = new Dropbox.Xhr('GET', "" + this.urls.search + "/" + (this.urlEncodePath(path)));
- xhr.setParams(params).signWithOauth(this.oauth, httpCache);
- return this.dispatchXhr(xhr, function(error, results) {
- var metadata, stats;
- if (results) {
- stats = (function() {
- var _i, _len, _results;
- _results = [];
- for (_i = 0, _len = results.length; _i < _len; _i++) {
- metadata = results[_i];
- _results.push(Dropbox.Stat.parse(metadata));
- }
- return _results;
- })();
- } else {
- stats = void 0;
- }
- return callback(error, stats);
- });
- };
-
- Client.prototype.search = function(path, namePattern, options, callback) {
- return this.findByName(path, namePattern, options, callback);
- };
-
- Client.prototype.makeCopyReference = function(path, callback) {
- var xhr;
- xhr = new Dropbox.Xhr('GET', "" + this.urls.copyRef + "/" + (this.urlEncodePath(path)));
- xhr.signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, refData) {
- return callback(error, Dropbox.CopyReference.parse(refData));
- });
- };
-
- Client.prototype.copyRef = function(path, callback) {
- return this.makeCopyReference(path, callback);
- };
-
- Client.prototype.pullChanges = function(cursor, callback) {
- var params, xhr;
- if ((!callback) && (typeof cursor === 'function')) {
- callback = cursor;
- cursor = null;
- }
- if (cursor) {
- if (cursor.cursorTag) {
- params = {
- cursor: cursor.cursorTag
- };
- } else {
- params = {
- cursor: cursor
- };
- }
- } else {
- params = {};
- }
- xhr = new Dropbox.Xhr('POST', this.urls.delta);
- xhr.setParams(params).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, deltaInfo) {
- return callback(error, Dropbox.PulledChanges.parse(deltaInfo));
- });
- };
-
- Client.prototype.delta = function(cursor, callback) {
- return this.pullChanges(cursor, callback);
- };
-
- Client.prototype.mkdir = function(path, callback) {
- var xhr;
- xhr = new Dropbox.Xhr('POST', this.urls.fileopsCreateFolder);
- xhr.setParams({
- root: this.fileRoot,
- path: this.normalizePath(path)
- }).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- return callback(error, Dropbox.Stat.parse(metadata));
- });
- };
-
- Client.prototype.remove = function(path, callback) {
- var xhr;
- xhr = new Dropbox.Xhr('POST', this.urls.fileopsDelete);
- xhr.setParams({
- root: this.fileRoot,
- path: this.normalizePath(path)
- }).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- return callback(error, Dropbox.Stat.parse(metadata));
- });
- };
-
- Client.prototype.unlink = function(path, callback) {
- return this.remove(path, callback);
- };
-
- Client.prototype["delete"] = function(path, callback) {
- return this.remove(path, callback);
- };
-
- Client.prototype.copy = function(from, toPath, callback) {
- var options, params, xhr;
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- params = {
- root: this.fileRoot,
- to_path: this.normalizePath(toPath)
- };
- if (from instanceof Dropbox.CopyReference) {
- params.from_copy_ref = from.tag;
- } else {
- params.from_path = this.normalizePath(from);
- }
- xhr = new Dropbox.Xhr('POST', this.urls.fileopsCopy);
- xhr.setParams(params).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- return callback(error, Dropbox.Stat.parse(metadata));
- });
- };
-
- Client.prototype.move = function(fromPath, toPath, callback) {
- var options, xhr;
- if ((!callback) && (typeof options === 'function')) {
- callback = options;
- options = null;
- }
- xhr = new Dropbox.Xhr('POST', this.urls.fileopsMove);
- xhr.setParams({
- root: this.fileRoot,
- from_path: this.normalizePath(fromPath),
- to_path: this.normalizePath(toPath)
- }).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, function(error, metadata) {
- return callback(error, Dropbox.Stat.parse(metadata));
- });
- };
-
- Client.prototype.reset = function() {
- var oldAuthState;
- this.uid = null;
- this.oauth.setToken(null, '');
- oldAuthState = this.authState;
- this.authState = DropboxClient.RESET;
- if (oldAuthState !== this.authState) {
- this.onAuthStateChange.dispatch(this);
- }
- this.authError = null;
- this._credentials = null;
- return this;
- };
-
- Client.prototype.setCredentials = function(credentials) {
- var oldAuthState;
- oldAuthState = this.authState;
- this.oauth.reset(credentials);
- this.uid = credentials.uid || null;
- if (credentials.authState) {
- this.authState = credentials.authState;
- } else {
- if (credentials.token) {
- this.authState = DropboxClient.DONE;
- } else {
- this.authState = DropboxClient.RESET;
- }
- }
- this.authError = null;
- this._credentials = null;
- if (oldAuthState !== this.authState) {
- this.onAuthStateChange.dispatch(this);
- }
- return this;
- };
-
- Client.prototype.appHash = function() {
- return this.oauth.appHash();
- };
-
- Client.prototype.setupUrls = function() {
- this.fileRoot = this.sandbox ? 'sandbox' : 'dropbox';
- return this.urls = {
- requestToken: "" + this.apiServer + "/1/oauth/request_token",
- authorize: "" + this.authServer + "/1/oauth/authorize",
- accessToken: "" + this.apiServer + "/1/oauth/access_token",
- signOut: "" + this.apiServer + "/1/unlink_access_token",
- accountInfo: "" + this.apiServer + "/1/account/info",
- getFile: "" + this.fileServer + "/1/files/" + this.fileRoot,
- postFile: "" + this.fileServer + "/1/files/" + this.fileRoot,
- putFile: "" + this.fileServer + "/1/files_put/" + this.fileRoot,
- metadata: "" + this.apiServer + "/1/metadata/" + this.fileRoot,
- delta: "" + this.apiServer + "/1/delta",
- revisions: "" + this.apiServer + "/1/revisions/" + this.fileRoot,
- restore: "" + this.apiServer + "/1/restore/" + this.fileRoot,
- search: "" + this.apiServer + "/1/search/" + this.fileRoot,
- shares: "" + this.apiServer + "/1/shares/" + this.fileRoot,
- media: "" + this.apiServer + "/1/media/" + this.fileRoot,
- copyRef: "" + this.apiServer + "/1/copy_ref/" + this.fileRoot,
- thumbnails: "" + this.fileServer + "/1/thumbnails/" + this.fileRoot,
- chunkedUpload: "" + this.fileServer + "/1/chunked_upload",
- commitChunkedUpload: "" + this.fileServer + "/1/commit_chunked_upload/" + this.fileRoot,
- fileopsCopy: "" + this.apiServer + "/1/fileops/copy",
- fileopsCreateFolder: "" + this.apiServer + "/1/fileops/create_folder",
- fileopsDelete: "" + this.apiServer + "/1/fileops/delete",
- fileopsMove: "" + this.apiServer + "/1/fileops/move"
- };
- };
-
- Client.prototype.authState = null;
-
- Client.ERROR = 0;
-
- Client.RESET = 1;
-
- Client.REQUEST = 2;
-
- Client.AUTHORIZED = 3;
-
- Client.DONE = 4;
-
- Client.SIGNED_OFF = 5;
-
- Client.prototype.urlEncodePath = function(path) {
- return Dropbox.Xhr.urlEncodeValue(this.normalizePath(path)).replace(/%2F/gi, '/');
- };
-
- Client.prototype.normalizePath = function(path) {
- var i;
- if (path.substring(0, 1) === '/') {
- i = 1;
- while (path.substring(i, i + 1) === '/') {
- i += 1;
- }
- return path.substring(i);
- } else {
- return path;
- }
- };
-
- Client.prototype.requestToken = function(callback) {
- var xhr;
- xhr = new Dropbox.Xhr('POST', this.urls.requestToken).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, callback);
- };
-
- Client.prototype.authorizeUrl = function(token) {
- var params;
- params = {
- oauth_token: token,
- oauth_callback: this.driver.url()
- };
- return ("" + this.urls.authorize + "?") + Dropbox.Xhr.urlEncode(params);
- };
-
- Client.prototype.getAccessToken = function(callback) {
- var xhr;
- xhr = new Dropbox.Xhr('POST', this.urls.accessToken).signWithOauth(this.oauth);
- return this.dispatchXhr(xhr, callback);
- };
-
- Client.prototype.dispatchXhr = function(xhr, callback) {
- var nativeXhr;
- xhr.setCallback(callback);
- xhr.onError = this.onError;
- xhr.prepare();
- nativeXhr = xhr.xhr;
- if (this.onXhr.dispatch(xhr)) {
- xhr.send();
- }
- return nativeXhr;
- };
-
- Client.prototype.defaultApiServer = function() {
- return 'https://api.dropbox.com';
- };
-
- Client.prototype.defaultAuthServer = function() {
- return this.apiServer.replace('api.', 'www.');
- };
-
- Client.prototype.defaultFileServer = function() {
- return this.apiServer.replace('api.', 'api-content.');
- };
-
- Client.prototype.defaultDownloadServer = function() {
- return this.apiServer.replace('api.', 'dl.');
- };
-
- Client.prototype.computeCredentials = function() {
- var value;
- value = {
- key: this.oauth.key,
- sandbox: this.sandbox
- };
- if (this.oauth.secret) {
- value.secret = this.oauth.secret;
- }
- if (this.oauth.token) {
- value.token = this.oauth.token;
- value.tokenSecret = this.oauth.tokenSecret;
- }
- if (this.uid) {
- value.uid = this.uid;
- }
- if (this.authState !== DropboxClient.ERROR && this.authState !== DropboxClient.RESET && this.authState !== DropboxClient.DONE && this.authState !== DropboxClient.SIGNED_OFF) {
- value.authState = this.authState;
- }
- if (this.apiServer !== this.defaultApiServer()) {
- value.server = this.apiServer;
- }
- if (this.authServer !== this.defaultAuthServer()) {
- value.authServer = this.authServer;
- }
- if (this.fileServer !== this.defaultFileServer()) {
- value.fileServer = this.fileServer;
- }
- if (this.downloadServer !== this.defaultDownloadServer()) {
- value.downloadServer = this.downloadServer;
- }
- return this._credentials = value;
- };
-
- return Client;
-
- })();
-
- DropboxClient = Dropbox.Client;
-
- Dropbox.AuthDriver = (function() {
-
- function AuthDriver() {}
-
- AuthDriver.prototype.url = function() {
- return 'https://some.url';
- };
-
- AuthDriver.prototype.doAuthorize = function(authUrl, token, tokenSecret, callback) {
- return callback('oauth-token');
- };
-
- AuthDriver.prototype.onAuthStateChange = function(client, callback) {
- return callback();
- };
-
- return AuthDriver;
-
- })();
-
- Dropbox.Drivers = {};
-
- Dropbox.Drivers.BrowserBase = (function() {
-
- function BrowserBase(options) {
- this.rememberUser = (options != null ? options.rememberUser : void 0) || false;
- this.scope = (options != null ? options.scope : void 0) || 'default';
- this.storageKey = null;
- }
-
- BrowserBase.prototype.onAuthStateChange = function(client, callback) {
- var _this = this;
- this.setStorageKey(client);
- switch (client.authState) {
- case DropboxClient.RESET:
- return this.loadCredentials(function(credentials) {
- if (!credentials) {
- return callback();
- }
- if (credentials.authState) {
- client.setCredentials(credentials);
- return callback();
- }
- if (!_this.rememberUser) {
- _this.forgetCredentials();
- return callback();
- }
- client.setCredentials(credentials);
- return client.getUserInfo(function(error) {
- if (error) {
- client.reset();
- return _this.forgetCredentials(callback);
- } else {
- return callback();
- }
- });
- });
- case DropboxClient.REQUEST:
- return this.storeCredentials(client.credentials(), callback);
- case DropboxClient.DONE:
- if (this.rememberUser) {
- return this.storeCredentials(client.credentials(), callback);
- }
- return this.forgetCredentials(callback);
- case DropboxClient.SIGNED_OFF:
- return this.forgetCredentials(callback);
- case DropboxClient.ERROR:
- return this.forgetCredentials(callback);
- default:
- callback();
- return this;
- }
- };
-
- BrowserBase.prototype.setStorageKey = function(client) {
- this.storageKey = "dropbox-auth:" + this.scope + ":" + (client.appHash());
- return this;
- };
-
- BrowserBase.prototype.storeCredentials = function(credentials, callback) {
- localStorage.setItem(this.storageKey, JSON.stringify(credentials));
- callback();
- return this;
- };
-
- BrowserBase.prototype.loadCredentials = function(callback) {
- var jsonString;
- jsonString = localStorage.getItem(this.storageKey);
- if (!jsonString) {
- callback(null);
- return this;
- }
- try {
- callback(JSON.parse(jsonString));
- } catch (e) {
- callback(null);
- }
- return this;
- };
-
- BrowserBase.prototype.forgetCredentials = function(callback) {
- localStorage.removeItem(this.storageKey);
- callback();
- return this;
- };
-
- BrowserBase.currentLocation = function() {
- return window.location.href;
- };
-
- return BrowserBase;
-
- })();
-
- Dropbox.Drivers.Redirect = (function(_super) {
-
- __extends(Redirect, _super);
-
- function Redirect(options) {
- Redirect.__super__.constructor.call(this, options);
- this.useQuery = (options != null ? options.useQuery : void 0) || false;
- this.receiverUrl = this.computeUrl(options);
- this.tokenRe = new RegExp("(#|\\?|&)oauth_token=([^]+)(&|#|$)");
- }
-
- Redirect.prototype.onAuthStateChange = function(client, callback) {
- var superCall,
- _this = this;
- superCall = (function() {
- return function() {
- return Redirect.__super__.onAuthStateChange.call(_this, client, callback);
- };
- })();
- this.setStorageKey(client);
- if (client.authState === DropboxClient.RESET) {
- return this.loadCredentials(function(credentials) {
- if (credentials && credentials.authState) {
- if (credentials.token === _this.locationToken() && credentials.authState === DropboxClient.REQUEST) {
- credentials.authState = DropboxClient.AUTHORIZED;
- return _this.storeCredentials(credentials, superCall);
- } else {
- return _this.forgetCredentials(superCall);
- }
- }
- return superCall();
- });
- } else {
- return superCall();
- }
- };
-
- Redirect.prototype.url = function() {
- return this.receiverUrl;
- };
-
- Redirect.prototype.doAuthorize = function(authUrl) {
- return window.location.assign(authUrl);
- };
-
- Redirect.prototype.computeUrl = function() {
- var fragment, location, locationPair, querySuffix;
- querySuffix = "_dropboxjs_scope=" + (encodeURIComponent(this.scope));
- location = Dropbox.Drivers.BrowserBase.currentLocation();
- if (location.indexOf('#') === -1) {
- fragment = null;
- } else {
- locationPair = location.split('#', 2);
- location = locationPair[0];
- fragment = locationPair[1];
- }
- if (this.useQuery) {
- if (location.indexOf('?') === -1) {
- location += "?" + querySuffix;
- } else {
- location += "&" + querySuffix;
- }
- } else {
- fragment = "?" + querySuffix;
- }
- if (fragment) {
- return location + '#' + fragment;
- } else {
- return location;
- }
- };
-
- Redirect.prototype.locationToken = function() {
- var location, match, scopePattern;
- location = Dropbox.Drivers.BrowserBase.currentLocation();
- scopePattern = "_dropboxjs_scope=" + (encodeURIComponent(this.scope)) + "&";
- if ((typeof location.indexOf === "function" ? location.indexOf(scopePattern) : void 0) === -1) {
- return null;
- }
- match = this.tokenRe.exec(location);
- if (match) {
- return decodeURIComponent(match[2]);
- } else {
- return null;
- }
- };
-
- return Redirect;
-
- })(Dropbox.Drivers.BrowserBase);
-
- Dropbox.Drivers.Popup = (function(_super) {
-
- __extends(Popup, _super);
-
- function Popup(options) {
- Popup.__super__.constructor.call(this, options);
- this.receiverUrl = this.computeUrl(options);
- this.tokenRe = new RegExp("(#|\\?|&)oauth_token=([^]+)(&|#|$)");
- }
-
- Popup.prototype.onAuthStateChange = function(client, callback) {
- var superCall,
- _this = this;
- superCall = (function() {
- return function() {
- return Popup.__super__.onAuthStateChange.call(_this, client, callback);
- };
- })();
- this.setStorageKey(client);
- if (client.authState === DropboxClient.RESET) {
- return this.loadCredentials(function(credentials) {
- if (credentials && credentials.authState) {
- return _this.forgetCredentials(superCall);
- }
- return superCall();
- });
- } else {
- return superCall();
- }
- };
-
- Popup.prototype.doAuthorize = function(authUrl, token, tokenSecret, callback) {
- this.listenForMessage(token, callback);
- return this.openWindow(authUrl);
- };
-
- Popup.prototype.url = function() {
- return this.receiverUrl;
- };
-
- Popup.prototype.computeUrl = function(options) {
- var fragments;
- if (options) {
- if (options.receiverUrl) {
- if (options.noFragment || options.receiverUrl.indexOf('#') !== -1) {
- return options.receiverUrl;
- } else {
- return options.receiverUrl + '#';
- }
- } else if (options.receiverFile) {
- fragments = Dropbox.Drivers.BrowserBase.currentLocation().split('/');
- fragments[fragments.length - 1] = options.receiverFile;
- if (options.noFragment) {
- return fragments.join('/');
- } else {
- return fragments.join('/') + '#';
- }
- }
- }
- return Dropbox.Drivers.BrowserBase.currentLocation();
- };
-
- Popup.prototype.openWindow = function(url) {
- return window.open(url, '_dropboxOauthSigninWindow', this.popupWindowSpec(980, 700));
- };
-
- Popup.prototype.popupWindowSpec = function(popupWidth, popupHeight) {
- var height, popupLeft, popupTop, width, x0, y0, _ref, _ref1, _ref2, _ref3;
- x0 = (_ref = window.screenX) != null ? _ref : window.screenLeft;
- y0 = (_ref1 = window.screenY) != null ? _ref1 : window.screenTop;
- width = (_ref2 = window.outerWidth) != null ? _ref2 : document.documentElement.clientWidth;
- height = (_ref3 = window.outerHeight) != null ? _ref3 : document.documentElement.clientHeight;
- popupLeft = Math.round(x0 + (width - popupWidth) / 2);
- popupTop = Math.round(y0 + (height - popupHeight) / 2.5);
- if (popupLeft < x0) {
- popupLeft = x0;
- }
- if (popupTop < y0) {
- popupTop = y0;
- }
- return ("width=" + popupWidth + ",height=" + popupHeight + ",") + ("left=" + popupLeft + ",top=" + popupTop) + 'dialog=yes,dependent=yes,scrollbars=yes,location=yes';
- };
-
- Popup.prototype.listenForMessage = function(token, callback) {
- var listener,
- _this = this;
- listener = function(event) {
- var match;
- match = _this.tokenRe.exec(event.data.toString());
- if (match && decodeURIComponent(match[2]) === token) {
- window.removeEventListener('message', listener);
- return callback();
- }
- };
- return window.addEventListener('message', listener, false);
- };
-
- Popup.oauthReceiver = function() {
- return window.addEventListener('load', function() {
- var opener;
- opener = window.opener;
- if (window.parent !== window.top) {
- opener || (opener = window.parent);
- }
- if (opener) {
- try {
- opener.postMessage(window.location.href, '*');
- } catch (e) {
-
- }
- return window.close();
- }
- });
- };
-
- return Popup;
-
- })(Dropbox.Drivers.BrowserBase);
-
- DropboxChromeOnMessage = null;
-
- DropboxChromeSendMessage = null;
-
- if (typeof chrome !== "undefined" && chrome !== null) {
- if (chrome.runtime) {
- if (chrome.runtime.onMessage) {
- DropboxChromeOnMessage = chrome.runtime.onMessage;
- }
- if (chrome.runtime.sendMessage) {
- DropboxChromeSendMessage = function(m) {
- return chrome.runtime.sendMessage(m);
- };
- }
- }
- if (chrome.extension) {
- if (chrome.extension.onMessage) {
- DropboxChromeOnMessage || (DropboxChromeOnMessage = chrome.extension.onMessage);
- }
- if (chrome.extension.sendMessage) {
- DropboxChromeSendMessage || (DropboxChromeSendMessage = function(m) {
- return chrome.extension.sendMessage(m);
- });
- }
- }
- if (!DropboxChromeOnMessage) {
- (function() {
- var page, pageHack;
- pageHack = function(page) {
- if (page.Dropbox) {
- Dropbox.Drivers.Chrome.prototype.onMessage = page.Dropbox.Drivers.Chrome.onMessage;
- return Dropbox.Drivers.Chrome.prototype.sendMessage = page.Dropbox.Drivers.Chrome.sendMessage;
- } else {
- page.Dropbox = Dropbox;
- Dropbox.Drivers.Chrome.prototype.onMessage = new Dropbox.EventSource;
- return Dropbox.Drivers.Chrome.prototype.sendMessage = function(m) {
- return Dropbox.Drivers.Chrome.prototype.onMessage.dispatch(m);
- };
- }
- };
- if (chrome.extension && chrome.extension.getBackgroundPage) {
- if (page = chrome.extension.getBackgroundPage()) {
- return pageHack(page);
- }
- }
- if (chrome.runtime && chrome.runtime.getBackgroundPage) {
- return chrome.runtime.getBackgroundPage(function(page) {
- return pageHack(page);
- });
- }
- })();
- }
- }
-
- Dropbox.Drivers.Chrome = (function() {
-
- Chrome.prototype.onMessage = DropboxChromeOnMessage;
-
- Chrome.prototype.sendMessage = DropboxChromeSendMessage;
-
- Chrome.prototype.expandUrl = function(url) {
- if (chrome.runtime && chrome.runtime.getURL) {
- return chrome.runtime.getURL(url);
- }
- if (chrome.extension && chrome.extension.getURL) {
- return chrome.extension.getURL(url);
- }
- return url;
- };
-
- function Chrome(options) {
- var receiverPath, scope;
- receiverPath = (options && options.receiverPath) || 'chrome_oauth_receiver.html';
- this.receiverUrl = this.expandUrl(receiverPath);
- this.tokenRe = new RegExp("(#|\\?|&)oauth_token=([^]+)(&|#|$)");
- scope = (options && options.scope) || 'default';
- this.storageKey = "dropbox_js_" + scope + "_credentials";
- }
-
- Chrome.prototype.onAuthStateChange = function(client, callback) {
- var _this = this;
- switch (client.authState) {
- case Dropbox.Client.RESET:
- return this.loadCredentials(function(credentials) {
- if (credentials) {
- if (credentials.authState) {
- return _this.forgetCredentials(callback);
- }
- client.setCredentials(credentials);
- }
- return callback();
- });
- case Dropbox.Client.DONE:
- return this.storeCredentials(client.credentials(), callback);
- case Dropbox.Client.SIGNED_OFF:
- return this.forgetCredentials(callback);
- case Dropbox.Client.ERROR:
- return this.forgetCredentials(callback);
- default:
- return callback();
- }
- };
-
- Chrome.prototype.doAuthorize = function(authUrl, token, tokenSecret, callback) {
- var window;
- window = {
- handle: null
- };
- this.listenForMessage(token, window, callback);
- return this.openWindow(authUrl, function(handle) {
- return window.handle = handle;
- });
- };
-
- Chrome.prototype.openWindow = function(url, callback) {
- if (chrome.tabs && chrome.tabs.create) {
- chrome.tabs.create({
- url: url,
- active: true,
- pinned: false
- }, function(tab) {
- return callback(tab);
- });
- return this;
- }
- if (chrome.app && chrome.app.window && chrome.app.window.create) {
- chrome.app.window.create(url, {
- frame: 'none',
- id: 'dropbox-auth'
- }, function(window) {
- return callback(window);
- });
- return this;
- }
- return this;
- };
-
- Chrome.prototype.closeWindow = function(handle) {
- if (chrome.tabs && chrome.tabs.remove && handle.id) {
- chrome.tabs.remove(handle.id);
- return this;
- }
- if (chrome.app && chrome.app.window && handle.close) {
- handle.close();
- return this;
- }
- return this;
- };
-
- Chrome.prototype.url = function() {
- return this.receiverUrl;
- };
-
- Chrome.prototype.listenForMessage = function(token, window, callback) {
- var listener,
- _this = this;
- listener = function(message, sender) {
- var match;
- if (sender && sender.tab) {
- if (sender.tab.url.substring(0, _this.receiverUrl.length) !== _this.receiverUrl) {
- return;
- }
- }
- match = _this.tokenRe.exec(message.dropbox_oauth_receiver_href || '');
- if (match && decodeURIComponent(match[2]) === token) {
- if (window.handle) {
- _this.closeWindow(window.handle);
- }
- _this.onMessage.removeListener(listener);
- return callback();
- }
- };
- return this.onMessage.addListener(listener);
- };
-
- Chrome.prototype.storeCredentials = function(credentials, callback) {
- var items;
- items = {};
- items[this.storageKey] = credentials;
- chrome.storage.local.set(items, callback);
- return this;
- };
-
- Chrome.prototype.loadCredentials = function(callback) {
- var _this = this;
- chrome.storage.local.get(this.storageKey, function(items) {
- return callback(items[_this.storageKey] || null);
- });
- return this;
- };
-
- Chrome.prototype.forgetCredentials = function(callback) {
- chrome.storage.local.remove(this.storageKey, callback);
- return this;
- };
-
- Chrome.oauthReceiver = function() {
- return window.addEventListener('load', function() {
- var driver;
- driver = new Dropbox.Drivers.Chrome();
- driver.sendMessage({
- dropbox_oauth_receiver_href: window.location.href
- });
- if (window.close) {
- return window.close();
- }
- });
- };
-
- return Chrome;
-
- })();
-
- Dropbox.Drivers.NodeServer = (function() {
-
- function NodeServer(options) {
- this.port = (options != null ? options.port : void 0) || 8912;
- this.faviconFile = (options != null ? options.favicon : void 0) || null;
- this.fs = require('fs');
- this.http = require('http');
- this.open = require('open');
- this.callbacks = {};
- this.urlRe = new RegExp("^/oauth_callback\\?");
- this.tokenRe = new RegExp("(\\?|&)oauth_token=([^&]+)(&|$)");
- this.createApp();
- }
-
- NodeServer.prototype.url = function() {
- return "http://localhost:" + this.port + "/oauth_callback";
- };
-
- NodeServer.prototype.doAuthorize = function(authUrl, token, tokenSecret, callback) {
- this.callbacks[token] = callback;
- return this.openBrowser(authUrl);
- };
-
- NodeServer.prototype.openBrowser = function(url) {
- if (!url.match(/^https?:\/\//)) {
- throw new Error("Not a http/https URL: " + url);
- }
- return this.open(url);
- };
-
- NodeServer.prototype.createApp = function() {
- var _this = this;
- this.app = this.http.createServer(function(request, response) {
- return _this.doRequest(request, response);
- });
- return this.app.listen(this.port);
- };
-
- NodeServer.prototype.closeServer = function() {
- return this.app.close();
- };
-
- NodeServer.prototype.doRequest = function(request, response) {
- var data, match, token,
- _this = this;
- if (this.urlRe.exec(request.url)) {
- match = this.tokenRe.exec(request.url);
- if (match) {
- token = decodeURIComponent(match[2]);
- if (this.callbacks[token]) {
- this.callbacks[token]();
- delete this.callbacks[token];
- }
- }
- }
- data = '';
- request.on('data', function(dataFragment) {
- return data += dataFragment;
- });
- return request.on('end', function() {
- if (_this.faviconFile && (request.url === '/favicon.ico')) {
- return _this.sendFavicon(response);
- } else {
- return _this.closeBrowser(response);
- }
- });
- };
-
- NodeServer.prototype.closeBrowser = function(response) {
- var closeHtml;
- closeHtml = "\n\nPlease close this window.
";
- response.writeHead(200, {
- 'Content-Length': closeHtml.length,
- 'Content-Type': 'text/html'
- });
- response.write(closeHtml);
- return response.end;
- };
-
- NodeServer.prototype.sendFavicon = function(response) {
- return this.fs.readFile(this.faviconFile, function(error, data) {
- response.writeHead(200, {
- 'Content-Length': data.length,
- 'Content-Type': 'image/x-icon'
- });
- response.write(data);
- return response.end;
- });
- };
-
- return NodeServer;
-
- })();
-
- Dropbox.EventSource = (function() {
-
- function EventSource(options) {
- this._cancelable = options && options.cancelable;
- this._listeners = [];
- }
-
- EventSource.prototype.addListener = function(listener) {
- if (typeof listener !== 'function') {
- throw new TypeError('Invalid listener type; expected function');
- }
- if (__indexOf.call(this._listeners, listener) < 0) {
- this._listeners.push(listener);
- }
- return this;
- };
-
- EventSource.prototype.removeListener = function(listener) {
- var i, index, subscriber, _i, _len, _ref;
- if (this._listeners.indexOf) {
- index = this._listeners.indexOf(listener);
- if (index !== -1) {
- this._listeners.splice(index, 1);
- }
- } else {
- _ref = this._listeners;
- for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
- subscriber = _ref[i];
- if (subscriber === listener) {
- this._listeners.splice(i, 1);
- break;
- }
- }
- }
- return this;
- };
-
- EventSource.prototype.dispatch = function(event) {
- var listener, returnValue, _i, _len, _ref;
- _ref = this._listeners;
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- listener = _ref[_i];
- returnValue = listener(event);
- if (this._cancelable && returnValue === false) {
- return false;
- }
- }
- return true;
- };
-
- return EventSource;
-
- })();
-
- base64HmacSha1 = function(string, key) {
- return arrayToBase64(hmacSha1(stringToArray(string), stringToArray(key), string.length, key.length));
- };
-
- base64Sha1 = function(string) {
- return arrayToBase64(sha1(stringToArray(string), string.length));
- };
-
- if (typeof window === "undefined" || window === null) {
- crypto = require('crypto');
- base64HmacSha1 = function(string, key) {
- var hmac;
- hmac = crypto.createHmac('sha1', key);
- hmac.update(string);
- return hmac.digest('base64');
- };
- base64Sha1 = function(string) {
- var hash;
- hash = crypto.createHash('sha1');
- hash.update(string);
- return hash.digest('base64');
- };
- }
-
- hmacSha1 = function(string, key, length, keyLength) {
- var hash1, i, ipad, opad;
- if (key.length > 16) {
- key = sha1(key, keyLength);
- }
- ipad = (function() {
- var _i, _results;
- _results = [];
- for (i = _i = 0; _i < 16; i = ++_i) {
- _results.push(key[i] ^ 0x36363636);
- }
- return _results;
- })();
- opad = (function() {
- var _i, _results;
- _results = [];
- for (i = _i = 0; _i < 16; i = ++_i) {
- _results.push(key[i] ^ 0x5C5C5C5C);
- }
- return _results;
- })();
- hash1 = sha1(ipad.concat(string), 64 + length);
- return sha1(opad.concat(hash1), 64 + 20);
- };
-
- sha1 = function(string, length) {
- var a, a0, b, b0, c, c0, d, d0, e, e0, ft, i, j, kt, limit, state, t, _i;
- string[length >> 2] |= 1 << (31 - ((length & 0x03) << 3));
- string[(((length + 8) >> 6) << 4) + 15] = length << 3;
- state = Array(80);
- a = 1732584193;
- b = -271733879;
- c = -1732584194;
- d = 271733878;
- e = -1009589776;
- i = 0;
- limit = string.length;
- while (i < limit) {
- a0 = a;
- b0 = b;
- c0 = c;
- d0 = d;
- e0 = e;
- for (j = _i = 0; _i < 80; j = ++_i) {
- if (j < 16) {
- state[j] = string[i + j];
- } else {
- state[j] = rotateLeft32(state[j - 3] ^ state[j - 8] ^ state[j - 14] ^ state[j - 16], 1);
- }
- if (j < 20) {
- ft = (b & c) | ((~b) & d);
- kt = 1518500249;
- } else if (j < 40) {
- ft = b ^ c ^ d;
- kt = 1859775393;
- } else if (j < 60) {
- ft = (b & c) | (b & d) | (c & d);
- kt = -1894007588;
- } else {
- ft = b ^ c ^ d;
- kt = -899497514;
- }
- t = add32(add32(rotateLeft32(a, 5), ft), add32(add32(e, state[j]), kt));
- e = d;
- d = c;
- c = rotateLeft32(b, 30);
- b = a;
- a = t;
- }
- a = add32(a, a0);
- b = add32(b, b0);
- c = add32(c, c0);
- d = add32(d, d0);
- e = add32(e, e0);
- i += 16;
- }
- return [a, b, c, d, e];
- };
-
- /*
- # Uncomment the definition below for debugging.
- #
- # Returns the hexadecimal representation of a 32-bit number.
- xxx = (n) ->
- if n < 0
- n = (1 << 30) * 4 + n
- n.toString 16
- */
-
-
- rotateLeft32 = function(value, count) {
- return (value << count) | (value >>> (32 - count));
- };
-
- add32 = function(a, b) {
- var high, low;
- low = (a & 0xFFFF) + (b & 0xFFFF);
- high = (a >> 16) + (b >> 16) + (low >> 16);
- return (high << 16) | (low & 0xFFFF);
- };
-
- arrayToBase64 = function(array) {
- var i, i2, limit, string, trit;
- string = "";
- i = 0;
- limit = array.length * 4;
- while (i < limit) {
- i2 = i;
- trit = ((array[i2 >> 2] >> ((3 - (i2 & 3)) << 3)) & 0xFF) << 16;
- i2 += 1;
- trit |= ((array[i2 >> 2] >> ((3 - (i2 & 3)) << 3)) & 0xFF) << 8;
- i2 += 1;
- trit |= (array[i2 >> 2] >> ((3 - (i2 & 3)) << 3)) & 0xFF;
- string += _base64Digits[(trit >> 18) & 0x3F];
- string += _base64Digits[(trit >> 12) & 0x3F];
- i += 1;
- if (i >= limit) {
- string += '=';
- } else {
- string += _base64Digits[(trit >> 6) & 0x3F];
- }
- i += 1;
- if (i >= limit) {
- string += '=';
- } else {
- string += _base64Digits[trit & 0x3F];
- }
- i += 1;
- }
- return string;
- };
-
- _base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- stringToArray = function(string) {
- var array, i, mask, _i, _ref;
- array = [];
- mask = 0xFF;
- for (i = _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- array[i >> 2] |= (string.charCodeAt(i) & mask) << ((3 - (i & 3)) << 3);
- }
- return array;
- };
-
- Dropbox.Oauth = (function() {
-
- function Oauth(options) {
- this.key = this.k = null;
- this.secret = this.s = null;
- this.token = null;
- this.tokenSecret = null;
- this._appHash = null;
- this.reset(options);
- }
-
- Oauth.prototype.reset = function(options) {
- var k, s, secret, _ref;
- if (options.secret) {
- this.k = this.key = options.key;
- this.s = this.secret = options.secret;
- this._appHash = null;
- } else if (options.key) {
- this.key = options.key;
- this.secret = null;
- secret = atob(dropboxEncodeKey(this.key).split('|', 2)[1]);
- _ref = secret.split('?', 2), k = _ref[0], s = _ref[1];
- this.k = decodeURIComponent(k);
- this.s = decodeURIComponent(s);
- this._appHash = null;
- } else {
- if (!this.k) {
- throw new Error('No API key supplied');
- }
- }
- if (options.token) {
- return this.setToken(options.token, options.tokenSecret);
- } else {
- return this.setToken(null, '');
- }
- };
-
- Oauth.prototype.setToken = function(token, tokenSecret) {
- if (token && (!tokenSecret)) {
- throw new Error('No secret supplied with the user token');
- }
- this.token = token;
- this.tokenSecret = tokenSecret || '';
- this.hmacKey = Dropbox.Xhr.urlEncodeValue(this.s) + '&' + Dropbox.Xhr.urlEncodeValue(tokenSecret);
- return null;
- };
-
- Oauth.prototype.authHeader = function(method, url, params) {
- var header, oauth_params, param, value, _i, _len;
- this.addAuthParams(method, url, params);
- oauth_params = [];
- for (param in params) {
- value = params[param];
- if (param.substring(0, 6) === 'oauth_') {
- oauth_params.push(param);
- }
- }
- oauth_params.sort();
- header = [];
- for (_i = 0, _len = oauth_params.length; _i < _len; _i++) {
- param = oauth_params[_i];
- header.push(Dropbox.Xhr.urlEncodeValue(param) + '="' + Dropbox.Xhr.urlEncodeValue(params[param]) + '"');
- delete params[param];
- }
- return 'OAuth ' + header.join(',');
- };
-
- Oauth.prototype.addAuthParams = function(method, url, params) {
- this.boilerplateParams(params);
- params.oauth_signature = this.signature(method, url, params);
- return params;
- };
-
- Oauth.prototype.boilerplateParams = function(params) {
- params.oauth_consumer_key = this.k;
- params.oauth_nonce = this.nonce();
- params.oauth_signature_method = 'HMAC-SHA1';
- if (this.token) {
- params.oauth_token = this.token;
- }
- params.oauth_timestamp = Math.floor(Date.now() / 1000);
- params.oauth_version = '1.0';
- return params;
- };
-
- Oauth.prototype.nonce = function() {
- return Date.now().toString(36) + Math.random().toString(36);
- };
-
- Oauth.prototype.signature = function(method, url, params) {
- var string;
- string = method.toUpperCase() + '&' + Dropbox.Xhr.urlEncodeValue(url) + '&' + Dropbox.Xhr.urlEncodeValue(Dropbox.Xhr.urlEncode(params));
- return base64HmacSha1(string, this.hmacKey);
- };
-
- Oauth.prototype.appHash = function() {
- if (this._appHash) {
- return this._appHash;
- }
- return this._appHash = base64Sha1(this.k).replace(/\=/g, '');
- };
-
- return Oauth;
-
- })();
-
- if (Date.now == null) {
- Date.now = function() {
- return (new Date()).getTime();
- };
- }
-
- dropboxEncodeKey = function(key, secret) {
- var i, k, result, s, x, y, z, _i, _j, _ref, _ref1, _results;
- if (secret) {
- secret = [encodeURIComponent(key), encodeURIComponent(secret)].join('?');
- key = (function() {
- var _i, _ref, _results;
- _results = [];
- for (i = _i = 0, _ref = key.length / 2; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- _results.push(((key.charCodeAt(i * 2) & 15) * 16) + (key.charCodeAt(i * 2 + 1) & 15));
- }
- return _results;
- })();
- } else {
- _ref = key.split('|', 2), key = _ref[0], secret = _ref[1];
- key = atob(key);
- key = (function() {
- var _i, _ref1, _results;
- _results = [];
- for (i = _i = 0, _ref1 = key.length; 0 <= _ref1 ? _i < _ref1 : _i > _ref1; i = 0 <= _ref1 ? ++_i : --_i) {
- _results.push(key.charCodeAt(i));
- }
- return _results;
- })();
- secret = atob(secret);
- }
- s = (function() {
- _results = [];
- for (_i = 0; _i < 256; _i++){ _results.push(_i); }
- return _results;
- }).apply(this);
- y = 0;
- for (x = _j = 0; _j < 256; x = ++_j) {
- y = (y + s[i] + key[x % key.length]) % 256;
- _ref1 = [s[y], s[x]], s[x] = _ref1[0], s[y] = _ref1[1];
- }
- x = y = 0;
- result = (function() {
- var _k, _ref2, _ref3, _results1;
- _results1 = [];
- for (z = _k = 0, _ref2 = secret.length; 0 <= _ref2 ? _k < _ref2 : _k > _ref2; z = 0 <= _ref2 ? ++_k : --_k) {
- x = (x + 1) % 256;
- y = (y + s[x]) % 256;
- _ref3 = [s[y], s[x]], s[x] = _ref3[0], s[y] = _ref3[1];
- k = s[(s[x] + s[y]) % 256];
- _results1.push(String.fromCharCode((k ^ secret.charCodeAt(z)) % 256));
- }
- return _results1;
- })();
- key = (function() {
- var _k, _ref2, _results1;
- _results1 = [];
- for (i = _k = 0, _ref2 = key.length; 0 <= _ref2 ? _k < _ref2 : _k > _ref2; i = 0 <= _ref2 ? ++_k : --_k) {
- _results1.push(String.fromCharCode(key[i]));
- }
- return _results1;
- })();
- return [btoa(key.join('')), btoa(result.join(''))].join('|');
- };
-
- Dropbox.PulledChanges = (function() {
-
- PulledChanges.parse = function(deltaInfo) {
- if (deltaInfo && typeof deltaInfo === 'object') {
- return new Dropbox.PulledChanges(deltaInfo);
- } else {
- return deltaInfo;
- }
- };
-
- PulledChanges.prototype.blankSlate = void 0;
-
- PulledChanges.prototype.cursorTag = void 0;
-
- PulledChanges.prototype.changes = void 0;
-
- PulledChanges.prototype.shouldPullAgain = void 0;
-
- PulledChanges.prototype.shouldBackOff = void 0;
-
- PulledChanges.prototype.cursor = function() {
- return this.cursorTag;
- };
-
- function PulledChanges(deltaInfo) {
- var entry;
- this.blankSlate = deltaInfo.reset || false;
- this.cursorTag = deltaInfo.cursor;
- this.shouldPullAgain = deltaInfo.has_more;
- this.shouldBackOff = !this.shouldPullAgain;
- if (deltaInfo.cursor && deltaInfo.cursor.length) {
- this.changes = (function() {
- var _i, _len, _ref, _results;
- _ref = deltaInfo.entries;
- _results = [];
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- entry = _ref[_i];
- _results.push(Dropbox.PullChange.parse(entry));
- }
- return _results;
- })();
- } else {
- this.changes = [];
- }
- }
-
- return PulledChanges;
-
- })();
-
- Dropbox.PullChange = (function() {
-
- PullChange.parse = function(entry) {
- if (entry && typeof entry === 'object') {
- return new Dropbox.PullChange(entry);
- } else {
- return entry;
- }
- };
-
- PullChange.prototype.path = void 0;
-
- PullChange.prototype.wasRemoved = void 0;
-
- PullChange.prototype.stat = void 0;
-
- function PullChange(entry) {
- this.path = entry[0];
- this.stat = Dropbox.Stat.parse(entry[1]);
- if (this.stat) {
- this.wasRemoved = false;
- } else {
- this.stat = null;
- this.wasRemoved = true;
- }
- }
-
- return PullChange;
-
- })();
-
- Dropbox.PublicUrl = (function() {
-
- PublicUrl.parse = function(urlData, isDirect) {
- if (urlData && typeof urlData === 'object') {
- return new Dropbox.PublicUrl(urlData, isDirect);
- } else {
- return urlData;
- }
- };
-
- PublicUrl.prototype.url = null;
-
- PublicUrl.prototype.expiresAt = null;
-
- PublicUrl.prototype.isDirect = null;
-
- PublicUrl.prototype.isPreview = null;
-
- PublicUrl.prototype.json = function() {
- return this._json || (this._json = {
- url: this.url,
- expires: this.expiresAt.toString(),
- direct: this.isDirect
- });
- };
-
- function PublicUrl(urlData, isDirect) {
- this.url = urlData.url;
- this.expiresAt = new Date(Date.parse(urlData.expires));
- if (isDirect === true) {
- this.isDirect = true;
- } else if (isDirect === false) {
- this.isDirect = false;
- } else {
- if ('direct' in urlData) {
- this.isDirect = urlData.direct;
- } else {
- this.isDirect = Date.now() - this.expiresAt <= 86400000;
- }
- }
- this.isPreview = !this.isDirect;
- this._json = null;
- }
-
- return PublicUrl;
-
- })();
-
- Dropbox.CopyReference = (function() {
-
- CopyReference.parse = function(refData) {
- if (refData && (typeof refData === 'object' || typeof refData === 'string')) {
- return new Dropbox.CopyReference(refData);
- } else {
- return refData;
- }
- };
-
- CopyReference.prototype.tag = null;
-
- CopyReference.prototype.expiresAt = null;
-
- CopyReference.prototype.json = function() {
- return this._json || (this._json = {
- copy_ref: this.tag,
- expires: this.expiresAt.toString()
- });
- };
-
- function CopyReference(refData) {
- if (typeof refData === 'object') {
- this.tag = refData.copy_ref;
- this.expiresAt = new Date(Date.parse(refData.expires));
- this._json = refData;
- } else {
- this.tag = refData;
- this.expiresAt = new Date(Math.ceil(Date.now() / 1000) * 1000);
- this._json = null;
- }
- }
-
- return CopyReference;
-
- })();
-
- Dropbox.Stat = (function() {
-
- Stat.parse = function(metadata) {
- if (metadata && typeof metadata === 'object') {
- return new Dropbox.Stat(metadata);
- } else {
- return metadata;
- }
- };
-
- Stat.prototype.path = null;
-
- Stat.prototype.name = null;
-
- Stat.prototype.inAppFolder = null;
-
- Stat.prototype.isFolder = null;
-
- Stat.prototype.isFile = null;
-
- Stat.prototype.isRemoved = null;
-
- Stat.prototype.typeIcon = null;
-
- Stat.prototype.versionTag = null;
-
- Stat.prototype.mimeType = null;
-
- Stat.prototype.size = null;
-
- Stat.prototype.humanSize = null;
-
- Stat.prototype.hasThumbnail = null;
-
- Stat.prototype.modifiedAt = null;
-
- Stat.prototype.clientModifiedAt = null;
-
- Stat.prototype.json = function() {
- return this._json;
- };
-
- function Stat(metadata) {
- var lastIndex, nameSlash, _ref, _ref1;
- this._json = metadata;
- this.path = metadata.path;
- if (this.path.substring(0, 1) !== '/') {
- this.path = '/' + this.path;
- }
- lastIndex = this.path.length - 1;
- if (lastIndex >= 0 && this.path.substring(lastIndex) === '/') {
- this.path = this.path.substring(0, lastIndex);
- }
- nameSlash = this.path.lastIndexOf('/');
- this.name = this.path.substring(nameSlash + 1);
- this.isFolder = metadata.is_dir || false;
- this.isFile = !this.isFolder;
- this.isRemoved = metadata.is_deleted || false;
- this.typeIcon = metadata.icon;
- if ((_ref = metadata.modified) != null ? _ref.length : void 0) {
- this.modifiedAt = new Date(Date.parse(metadata.modified));
- } else {
- this.modifiedAt = null;
- }
- if ((_ref1 = metadata.client_mtime) != null ? _ref1.length : void 0) {
- this.clientModifiedAt = new Date(Date.parse(metadata.client_mtime));
- } else {
- this.clientModifiedAt = null;
- }
- switch (metadata.root) {
- case 'dropbox':
- this.inAppFolder = false;
- break;
- case 'app_folder':
- this.inAppFolder = true;
- break;
- default:
- this.inAppFolder = null;
- }
- this.size = metadata.bytes || 0;
- this.humanSize = metadata.size || '';
- this.hasThumbnail = metadata.thumb_exists || false;
- if (this.isFolder) {
- this.versionTag = metadata.hash;
- this.mimeType = metadata.mime_type || 'inode/directory';
- } else {
- this.versionTag = metadata.rev;
- this.mimeType = metadata.mime_type || 'application/octet-stream';
- }
- }
-
- return Stat;
-
- })();
-
- Dropbox.UploadCursor = (function() {
-
- UploadCursor.parse = function(cursorData) {
- if (cursorData && (typeof cursorData === 'object' || typeof cursorData === 'string')) {
- return new Dropbox.UploadCursor(cursorData);
- } else {
- return cursorData;
- }
- };
-
- UploadCursor.prototype.tag = null;
-
- UploadCursor.prototype.offset = null;
-
- UploadCursor.prototype.expiresAt = null;
-
- UploadCursor.prototype.json = function() {
- return this._json || (this._json = {
- upload_id: this.tag,
- offset: this.offset,
- expires: this.expiresAt.toString()
- });
- };
-
- function UploadCursor(cursorData) {
- this.replace(cursorData);
- }
-
- UploadCursor.prototype.replace = function(cursorData) {
- if (typeof cursorData === 'object') {
- this.tag = cursorData.upload_id || null;
- this.offset = cursorData.offset || 0;
- this.expiresAt = new Date(Date.parse(cursorData.expires) || Date.now());
- this._json = cursorData;
- } else {
- this.tag = cursorData || null;
- this.offset = 0;
- this.expiresAt = new Date(Math.floor(Date.now() / 1000) * 1000);
- this._json = null;
- }
- return this;
- };
-
- return UploadCursor;
-
- })();
-
- Dropbox.UserInfo = (function() {
-
- UserInfo.parse = function(userInfo) {
- if (userInfo && typeof userInfo === 'object') {
- return new Dropbox.UserInfo(userInfo);
- } else {
- return userInfo;
- }
- };
-
- UserInfo.prototype.name = null;
-
- UserInfo.prototype.email = null;
-
- UserInfo.prototype.countryCode = null;
-
- UserInfo.prototype.uid = null;
-
- UserInfo.prototype.referralUrl = null;
-
- UserInfo.prototype.publicAppUrl = null;
-
- UserInfo.prototype.quota = null;
-
- UserInfo.prototype.usedQuota = null;
-
- UserInfo.prototype.privateBytes = null;
-
- UserInfo.prototype.sharedBytes = null;
-
- UserInfo.prototype.json = function() {
- return this._json;
- };
-
- function UserInfo(userInfo) {
- var lastIndex;
- this._json = userInfo;
- this.name = userInfo.display_name;
- this.email = userInfo.email;
- this.countryCode = userInfo.country || null;
- this.uid = userInfo.uid.toString();
- if (userInfo.public_app_url) {
- this.publicAppUrl = userInfo.public_app_url;
- lastIndex = this.publicAppUrl.length - 1;
- if (lastIndex >= 0 && this.publicAppUrl.substring(lastIndex) === '/') {
- this.publicAppUrl = this.publicAppUrl.substring(0, lastIndex);
- }
- } else {
- this.publicAppUrl = null;
- }
- this.referralUrl = userInfo.referral_link;
- this.quota = userInfo.quota_info.quota;
- this.privateBytes = userInfo.quota_info.normal || 0;
- this.sharedBytes = userInfo.quota_info.shared || 0;
- this.usedQuota = this.privateBytes + this.sharedBytes;
- }
-
- return UserInfo;
-
- })();
-
- if (typeof window !== "undefined" && window !== null) {
- if (window.XDomainRequest && !('withCredentials' in new XMLHttpRequest())) {
- DropboxXhrRequest = window.XDomainRequest;
- DropboxXhrIeMode = true;
- DropboxXhrCanSendForms = false;
- } else {
- DropboxXhrRequest = window.XMLHttpRequest;
- DropboxXhrIeMode = false;
- DropboxXhrCanSendForms = window.navigator.userAgent.indexOf('Firefox') === -1;
- }
- DropboxXhrDoesPreflight = true;
- } else {
- DropboxXhrRequest = require('xmlhttprequest').XMLHttpRequest;
- DropboxXhrIeMode = false;
- DropboxXhrCanSendForms = false;
- DropboxXhrDoesPreflight = false;
- }
-
- if (typeof Uint8Array === 'undefined') {
- DropboxXhrArrayBufferView = null;
- DropboxXhrSendArrayBufferView = false;
- } else {
- if (Object.getPrototypeOf) {
- DropboxXhrArrayBufferView = Object.getPrototypeOf(Object.getPrototypeOf(new Uint8Array(0))).constructor;
- } else if (Object.__proto__) {
- DropboxXhrArrayBufferView = (new Uint8Array(0)).__proto__.__proto__.constructor;
- }
- DropboxXhrSendArrayBufferView = DropboxXhrArrayBufferView !== Object;
- }
-
- Dropbox.Xhr = (function() {
-
- Xhr.Request = DropboxXhrRequest;
-
- Xhr.ieXdr = DropboxXhrIeMode;
-
- Xhr.canSendForms = DropboxXhrCanSendForms;
-
- Xhr.doesPreflight = DropboxXhrDoesPreflight;
-
- Xhr.ArrayBufferView = DropboxXhrArrayBufferView;
-
- Xhr.sendArrayBufferView = DropboxXhrSendArrayBufferView;
-
- function Xhr(method, baseUrl) {
- this.method = method;
- this.isGet = this.method === 'GET';
- this.url = baseUrl;
- this.headers = {};
- this.params = null;
- this.body = null;
- this.preflight = !(this.isGet || (this.method === 'POST'));
- this.signed = false;
- this.responseType = null;
- this.callback = null;
- this.xhr = null;
- this.onError = null;
- }
-
- Xhr.prototype.xhr = null;
-
- Xhr.prototype.onError = null;
-
- Xhr.prototype.setParams = function(params) {
- if (this.signed) {
- throw new Error('setParams called after addOauthParams or addOauthHeader');
- }
- if (this.params) {
- throw new Error('setParams cannot be called twice');
- }
- this.params = params;
- return this;
- };
-
- Xhr.prototype.setCallback = function(callback) {
- this.callback = callback;
- return this;
- };
-
- Xhr.prototype.signWithOauth = function(oauth, cacheFriendly) {
- if (Dropbox.Xhr.ieXdr) {
- return this.addOauthParams(oauth);
- } else if (this.preflight || !Dropbox.Xhr.doesPreflight) {
- return this.addOauthHeader(oauth);
- } else {
- if (this.isGet && cacheFriendly) {
- return this.addOauthHeader(oauth);
- } else {
- return this.addOauthParams(oauth);
- }
- }
- };
-
- Xhr.prototype.addOauthParams = function(oauth) {
- if (this.signed) {
- throw new Error('Request already has an OAuth signature');
- }
- this.params || (this.params = {});
- oauth.addAuthParams(this.method, this.url, this.params);
- this.signed = true;
- return this;
- };
-
- Xhr.prototype.addOauthHeader = function(oauth) {
- if (this.signed) {
- throw new Error('Request already has an OAuth signature');
- }
- this.params || (this.params = {});
- this.signed = true;
- return this.setHeader('Authorization', oauth.authHeader(this.method, this.url, this.params));
- };
-
- Xhr.prototype.setBody = function(body) {
- if (this.isGet) {
- throw new Error('setBody cannot be called on GET requests');
- }
- if (this.body !== null) {
- throw new Error('Request already has a body');
- }
- if (typeof body === 'string') {
-
- } else if ((typeof FormData !== 'undefined') && (body instanceof FormData)) {
-
- } else {
- this.headers['Content-Type'] = 'application/octet-stream';
- this.preflight = true;
- }
- this.body = body;
- return this;
- };
-
- Xhr.prototype.setResponseType = function(responseType) {
- this.responseType = responseType;
- return this;
- };
-
- Xhr.prototype.setHeader = function(headerName, value) {
- var oldValue;
- if (this.headers[headerName]) {
- oldValue = this.headers[headerName];
- throw new Error("HTTP header " + headerName + " already set to " + oldValue);
- }
- if (headerName === 'Content-Type') {
- throw new Error('Content-Type is automatically computed based on setBody');
- }
- this.preflight = true;
- this.headers[headerName] = value;
- return this;
- };
-
- Xhr.prototype.setFileField = function(fieldName, fileName, fileData, contentType) {
- var boundary, useFormData;
- if (this.body !== null) {
- throw new Error('Request already has a body');
- }
- if (this.isGet) {
- throw new Error('setFileField cannot be called on GET requests');
- }
- if (typeof fileData === 'object' && typeof Blob !== 'undefined') {
- if (typeof ArrayBuffer !== 'undefined') {
- if (fileData instanceof ArrayBuffer) {
- if (Dropbox.Xhr.sendArrayBufferView) {
- fileData = new Uint8Array(fileData);
- }
- } else {
- if (!Dropbox.Xhr.sendArrayBufferView && fileData.byteOffset === 0 && fileData.buffer instanceof ArrayBuffer) {
- fileData = fileData.buffer;
- }
- }
- }
- contentType || (contentType = 'application/octet-stream');
- fileData = new Blob([fileData], {
- type: contentType
- });
- if (typeof File !== 'undefined' && fileData instanceof File) {
- fileData = new Blob([fileData], {
- type: fileData.type
- });
- }
- useFormData = fileData instanceof Blob;
- } else {
- useFormData = false;
- }
- if (useFormData) {
- this.body = new FormData();
- return this.body.append(fieldName, fileData, fileName);
- } else {
- contentType || (contentType = 'application/octet-stream');
- boundary = this.multipartBoundary();
- this.headers['Content-Type'] = "multipart/form-data; boundary=" + boundary;
- return this.body = ['--', boundary, "\r\n", 'Content-Disposition: form-data; name="', fieldName, '"; filename="', fileName, "\"\r\n", 'Content-Type: ', contentType, "\r\n", "Content-Transfer-Encoding: binary\r\n\r\n", fileData, "\r\n", '--', boundary, '--', "\r\n"].join('');
- }
- };
-
- Xhr.prototype.multipartBoundary = function() {
- return [Date.now().toString(36), Math.random().toString(36)].join('----');
- };
-
- Xhr.prototype.paramsToUrl = function() {
- var queryString;
- if (this.params) {
- queryString = Dropbox.Xhr.urlEncode(this.params);
- if (queryString.length !== 0) {
- this.url = [this.url, '?', queryString].join('');
- }
- this.params = null;
- }
- return this;
- };
-
- Xhr.prototype.paramsToBody = function() {
- if (this.params) {
- if (this.body !== null) {
- throw new Error('Request already has a body');
- }
- if (this.isGet) {
- throw new Error('paramsToBody cannot be called on GET requests');
- }
- this.headers['Content-Type'] = 'application/x-www-form-urlencoded';
- this.body = Dropbox.Xhr.urlEncode(this.params);
- this.params = null;
- }
- return this;
- };
-
- Xhr.prototype.prepare = function() {
- var header, ieXdr, value, _ref,
- _this = this;
- ieXdr = Dropbox.Xhr.ieXdr;
- if (this.isGet || this.body !== null || ieXdr) {
- this.paramsToUrl();
- if (this.body !== null && typeof this.body === 'string') {
- this.headers['Content-Type'] = 'text/plain; charset=utf8';
- }
- } else {
- this.paramsToBody();
- }
- this.xhr = new Dropbox.Xhr.Request();
- if (ieXdr) {
- this.xhr.onload = function() {
- return _this.onXdrLoad();
- };
- this.xhr.onerror = function() {
- return _this.onXdrError();
- };
- this.xhr.ontimeout = function() {
- return _this.onXdrError();
- };
- this.xhr.onprogress = function() {};
- } else {
- this.xhr.onreadystatechange = function() {
- return _this.onReadyStateChange();
- };
- }
- this.xhr.open(this.method, this.url, true);
- if (!ieXdr) {
- _ref = this.headers;
- for (header in _ref) {
- if (!__hasProp.call(_ref, header)) continue;
- value = _ref[header];
- this.xhr.setRequestHeader(header, value);
- }
- }
- if (this.responseType) {
- if (this.responseType === 'b') {
- if (this.xhr.overrideMimeType) {
- this.xhr.overrideMimeType('text/plain; charset=x-user-defined');
- }
- } else {
- this.xhr.responseType = this.responseType;
- }
- }
- return this;
- };
-
- Xhr.prototype.send = function(callback) {
- var body;
- this.callback = callback || this.callback;
- if (this.body !== null) {
- body = this.body;
- if (Dropbox.Xhr.sendArrayBufferView && body instanceof ArrayBuffer) {
- body = new Uint8Array(body);
- }
- try {
- this.xhr.send(body);
- } catch (e) {
- if (!Dropbox.Xhr.sendArrayBufferView && typeof Blob !== 'undefined') {
- body = new Blob([body], {
- type: 'application/octet-stream'
- });
- this.xhr.send(body);
- } else {
- throw e;
- }
- }
- } else {
- this.xhr.send();
- }
- return this;
- };
-
- Xhr.urlEncode = function(object) {
- var chunks, key, value;
- chunks = [];
- for (key in object) {
- value = object[key];
- chunks.push(this.urlEncodeValue(key) + '=' + this.urlEncodeValue(value));
- }
- return chunks.sort().join('&');
- };
-
- Xhr.urlEncodeValue = function(object) {
- return encodeURIComponent(object.toString()).replace(/\!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A');
- };
-
- Xhr.urlDecode = function(string) {
- var kvp, result, token, _i, _len, _ref;
- result = {};
- _ref = string.split('&');
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- token = _ref[_i];
- kvp = token.split('=');
- result[decodeURIComponent(kvp[0])] = decodeURIComponent(kvp[1]);
- }
- return result;
- };
-
- Xhr.prototype.onReadyStateChange = function() {
- var apiError, bytes, dirtyText, i, metadata, metadataJson, text, _i, _ref;
- if (this.xhr.readyState !== 4) {
- return true;
- }
- if (this.xhr.status < 200 || this.xhr.status >= 300) {
- apiError = new Dropbox.ApiError(this.xhr, this.method, this.url);
- if (this.onError) {
- this.onError.dispatch(apiError);
- }
- this.callback(apiError);
- return true;
- }
- metadataJson = this.xhr.getResponseHeader('x-dropbox-metadata');
- if (metadataJson != null ? metadataJson.length : void 0) {
- try {
- metadata = JSON.parse(metadataJson);
- } catch (e) {
- metadata = void 0;
- }
- } else {
- metadata = void 0;
- }
- if (this.responseType) {
- if (this.responseType === 'b') {
- dirtyText = this.xhr.responseText != null ? this.xhr.responseText : this.xhr.response;
- /*
- jsString = ['["']
- for i in [0...dirtyText.length]
- hexByte = (dirtyText.charCodeAt(i) & 0xFF).toString(16)
- if hexByte.length is 2
- jsString.push "\\u00#{hexByte}"
- else
- jsString.push "\\u000#{hexByte}"
- jsString.push '"]'
- console.log jsString
- text = JSON.parse(jsString.join(''))[0]
- */
-
- bytes = [];
- for (i = _i = 0, _ref = dirtyText.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
- bytes.push(String.fromCharCode(dirtyText.charCodeAt(i) & 0xFF));
- }
- text = bytes.join('');
- this.callback(null, text, metadata);
- } else {
- this.callback(null, this.xhr.response, metadata);
- }
- return true;
- }
- text = this.xhr.responseText != null ? this.xhr.responseText : this.xhr.response;
- switch (this.xhr.getResponseHeader('Content-Type')) {
- case 'application/x-www-form-urlencoded':
- this.callback(null, Dropbox.Xhr.urlDecode(text), metadata);
- break;
- case 'application/json':
- case 'text/javascript':
- this.callback(null, JSON.parse(text), metadata);
- break;
- default:
- this.callback(null, text, metadata);
- }
- return true;
- };
-
- Xhr.prototype.onXdrLoad = function() {
- var text;
- text = this.xhr.responseText;
- switch (this.xhr.contentType) {
- case 'application/x-www-form-urlencoded':
- this.callback(null, Dropbox.Xhr.urlDecode(text), void 0);
- break;
- case 'application/json':
- case 'text/javascript':
- this.callback(null, JSON.parse(text), void 0);
- break;
- default:
- this.callback(null, text, void 0);
- }
- return true;
- };
-
- Xhr.prototype.onXdrError = function() {
- var apiError;
- apiError = new Dropbox.ApiError(this.xhr, this.method, this.url);
- if (this.onError) {
- this.onError.dispatch(apiError);
- }
- this.callback(apiError);
- return true;
- };
-
- return Xhr;
-
- })();
-
- if ((typeof module !== "undefined" && module !== null ? module.exports : void 0) != null) {
- module.exports = Dropbox;
- } else if (typeof window !== "undefined" && window !== null) {
- window.Dropbox = Dropbox;
- } else {
- throw new Error('This library only supports node.js and modern browsers.');
- }
-
- Dropbox.atob = atob;
-
- Dropbox.btoa = btoa;
-
- Dropbox.hmac = base64HmacSha1;
-
- Dropbox.sha1 = base64Sha1;
-
- Dropbox.encodeKey = dropboxEncodeKey;
-
-}).call(this);
diff --git a/lib/client/storage/dropbox/lib/dropbox.min.js b/lib/client/storage/dropbox/lib/dropbox.min.js
deleted file mode 100644
index f14c0b0b..00000000
--- a/lib/client/storage/dropbox/lib/dropbox.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-(function(){var t,e,r,n,o,i,s,a,h,u,l,p,c,d,f,y,v,m,g,w,S,b,_,E,C,x,R={}.hasOwnProperty,T=function(t,e){function r(){this.constructor=t}for(var n in e)R.call(e,n)&&(t[n]=e[n]);return r.prototype=e.prototype,t.prototype=new r,t.__super__=e.prototype,t},k=[].indexOf||function(t){for(var e=0,r=this.length;r>e;e++)if(e in this&&this[e]===t)return e;return-1};if(t=function(){function t(t){this.client=new n(t)}return t}(),t.ApiError=function(){function t(t,e,r){var n;if(this.method=e,this.url=r,this.status=t.status,t.responseType)try{n=t.response||t.responseText}catch(o){try{n=t.responseText}catch(o){n=null}}else try{n=t.responseText}catch(o){n=null}if(n)try{this.responseText=""+n,this.response=JSON.parse(n)}catch(o){this.response=null}else this.responseText="(no response)",this.response=null}return t.prototype.status=void 0,t.prototype.method=void 0,t.prototype.url=void 0,t.prototype.responseText=void 0,t.prototype.response=void 0,t.prototype.toString=function(){return"Dropbox API error "+this.status+" from "+this.method+" "+this.url+" :: "+this.responseText},t.prototype.inspect=function(){return""+this},t}(),"undefined"!=typeof window&&null!==window?window.atob&&window.btoa?(c=function(t){return window.atob(t)},m=function(t){return window.btoa(t)}):(f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",g=function(t,e,r){var n,o;for(o=3-e,t<<=8*o,n=3;n>=o;)r.push(f.charAt(63&t>>6*n)),n-=1;for(n=e;3>n;)r.push("="),n+=1;return null},d=function(t,e,r){var n,o;for(o=4-e,t<<=6*o,n=2;n>=o;)r.push(String.fromCharCode(255&t>>8*n)),n-=1;return null},m=function(t){var e,r,n,o,i,s;for(o=[],e=0,r=0,n=i=0,s=t.length;s>=0?s>i:i>s;n=s>=0?++i:--i)e=e<<8|t.charCodeAt(n),r+=1,3===r&&(g(e,r,o),e=r=0);return r>0&&g(e,r,o),o.join("")},c=function(t){var e,r,n,o,i,s,a;for(i=[],e=0,n=0,o=s=0,a=t.length;(a>=0?a>s:s>a)&&(r=t.charAt(o),"="!==r);o=a>=0?++s:--s)e=e<<6|f.indexOf(r),n+=1,4===n&&(d(e,n,i),e=n=0);return n>0&&d(e,n,i),i.join("")}):(c=function(t){var e,r;return e=new Buffer(t,"base64"),function(){var t,n,o;for(o=[],r=t=0,n=e.length;n>=0?n>t:t>n;r=n>=0?++t:--t)o.push(String.fromCharCode(e[r]));return o}().join("")},m=function(t){var e,r;return e=new Buffer(function(){var e,n,o;for(o=[],r=e=0,n=t.length;n>=0?n>e:e>n;r=n>=0?++e:--e)o.push(t.charCodeAt(r));return o}()),e.toString("base64")}),t.Client=function(){function e(e){this.sandbox=e.sandbox||!1,this.apiServer=e.server||this.defaultApiServer(),this.authServer=e.authServer||this.defaultAuthServer(),this.fileServer=e.fileServer||this.defaultFileServer(),this.downloadServer=e.downloadServer||this.defaultDownloadServer(),this.onXhr=new t.EventSource({cancelable:!0}),this.onError=new t.EventSource,this.onAuthStateChange=new t.EventSource,this.oauth=new t.Oauth(e),this.driver=null,this.filter=null,this.uid=null,this.authState=null,this.authError=null,this._credentials=null,this.setCredentials(e),this.setupUrls()}return e.prototype.authDriver=function(t){return this.driver=t,this},e.prototype.onXhr=null,e.prototype.onError=null,e.prototype.onAuthStateChange=null,e.prototype.dropboxUid=function(){return this.uid},e.prototype.credentials=function(){return this._credentials||this.computeCredentials(),this._credentials},e.prototype.authenticate=function(t){var e,r,o=this;if(e=null,!this.driver&&this.authState!==n.DONE)throw Error("Call authDriver to set an authentication driver");return r=function(){var i;if(e!==o.authState&&(null!==e&&o.onAuthStateChange.dispatch(o),e=o.authState,o.driver&&o.driver.onAuthStateChange))return o.driver.onAuthStateChange(o,r);switch(o.authState){case n.RESET:return o.requestToken(function(t,e){var i,s;return t?(o.authError=t,o.authState=n.ERROR):(i=e.oauth_token,s=e.oauth_token_secret,o.oauth.setToken(i,s),o.authState=n.REQUEST),o._credentials=null,r()});case n.REQUEST:return i=o.authorizeUrl(o.oauth.token),o.driver.doAuthorize(i,o.oauth.token,o.oauth.tokenSecret,function(){return o.authState=n.AUTHORIZED,o._credentials=null,r()});case n.AUTHORIZED:return o.getAccessToken(function(t,e){return t?(o.authError=t,o.authState=n.ERROR):(o.oauth.setToken(e.oauth_token,e.oauth_token_secret),o.uid=e.uid,o.authState=n.DONE),o._credentials=null,r()});case n.DONE:return t(null,o);case n.SIGNED_OFF:return o.authState=n.RESET,o.reset(),r();case n.ERROR:return t(o.authError)}},r(),this},e.prototype.isAuthenticated=function(){return this.authState===n.DONE},e.prototype.signOut=function(e){var r,o=this;return r=new t.Xhr("POST",this.urls.signOut),r.signWithOauth(this.oauth),this.dispatchXhr(r,function(t){return t?e(t):(o.authState=n.RESET,o.reset(),o.authState=n.SIGNED_OFF,o.onAuthStateChange.dispatch(o),o.driver.onAuthStateChange?o.driver.onAuthStateChange(o,function(){return e(t)}):e(t))})},e.prototype.signOff=function(t){return this.signOut(t)},e.prototype.getUserInfo=function(e,r){var n,o;return r||"function"!=typeof e||(r=e,e=null),n=!1,e&&e.httpCache&&(n=!0),o=new t.Xhr("GET",this.urls.accountInfo),o.signWithOauth(this.oauth,n),this.dispatchXhr(o,function(e,n){return r(e,t.UserInfo.parse(n),n)})},e.prototype.readFile=function(e,r,n){var o,i,s,a,h,u,l;return n||"function"!=typeof r||(n=r,r=null),i={},u=null,a=null,o=!1,r&&(r.versionTag?i.rev=r.versionTag:r.rev&&(i.rev=r.rev),r.arrayBuffer?u="arraybuffer":r.blob?u="blob":r.binary&&(u="b"),r.length?(null!=r.start?(h=r.start,s=r.start+r.length-1):(h="",s=r.length),a="bytes="+h+"-"+s):null!=r.start&&(a="bytes="+r.start+"-"),r.httpCache&&(o=!0)),l=new t.Xhr("GET",""+this.urls.getFile+"/"+this.urlEncodePath(e)),l.setParams(i).signWithOauth(this.oauth,o),l.setResponseType(u),a&&l.setHeader("Range",a),this.dispatchXhr(l,function(e,r,o){return n(e,r,t.Stat.parse(o))})},e.prototype.writeFile=function(e,r,n,o){var i;return o||"function"!=typeof n||(o=n,n=null),i=t.Xhr.canSendForms&&"object"==typeof r,i?this.writeFileUsingForm(e,r,n,o):this.writeFileUsingPut(e,r,n,o)},e.prototype.writeFileUsingForm=function(e,r,n,o){var i,s,a,h;return a=e.lastIndexOf("/"),-1===a?(i=e,e=""):(i=e.substring(a),e=e.substring(0,a)),s={file:i},n&&(n.noOverwrite&&(s.overwrite="false"),n.lastVersionTag?s.parent_rev=n.lastVersionTag:(n.parentRev||n.parent_rev)&&(s.parent_rev=n.parentRev||n.parent_rev)),h=new t.Xhr("POST",""+this.urls.postFile+"/"+this.urlEncodePath(e)),h.setParams(s).signWithOauth(this.oauth).setFileField("file",i,r,"application/octet-stream"),delete s.file,this.dispatchXhr(h,function(e,r){return o(e,t.Stat.parse(r))})},e.prototype.writeFileUsingPut=function(e,r,n,o){var i,s;return i={},n&&(n.noOverwrite&&(i.overwrite="false"),n.lastVersionTag?i.parent_rev=n.lastVersionTag:(n.parentRev||n.parent_rev)&&(i.parent_rev=n.parentRev||n.parent_rev)),s=new t.Xhr("POST",""+this.urls.putFile+"/"+this.urlEncodePath(e)),s.setBody(r).setParams(i).signWithOauth(this.oauth),this.dispatchXhr(s,function(e,r){return o(e,t.Stat.parse(r))})},e.prototype.resumableUploadStep=function(e,r,n){var o,i;return r?(o={offset:r.offset},r.tag&&(o.upload_id=r.tag)):o={offset:0},i=new t.Xhr("POST",this.urls.chunkedUpload),i.setBody(e).setParams(o).signWithOauth(this.oauth),this.dispatchXhr(i,function(e,r){return e&&400===e.status&&e.response.upload_id&&e.response.offset?n(null,t.UploadCursor.parse(e.response)):n(e,t.UploadCursor.parse(r))})},e.prototype.resumableUploadFinish=function(e,r,n,o){var i,s;return o||"function"!=typeof n||(o=n,n=null),i={upload_id:r.tag},n&&(n.lastVersionTag?i.parent_rev=n.lastVersionTag:(n.parentRev||n.parent_rev)&&(i.parent_rev=n.parentRev||n.parent_rev),n.noOverwrite&&(i.autorename=!0)),s=new t.Xhr("POST",""+this.urls.commitChunkedUpload+"/"+this.urlEncodePath(e)),s.setParams(i).signWithOauth(this.oauth),this.dispatchXhr(s,function(e,r){return o(e,t.Stat.parse(r))})},e.prototype.stat=function(e,r,n){var o,i,s;return n||"function"!=typeof r||(n=r,r=null),i={},o=!1,r&&(null!=r.version&&(i.rev=r.version),(r.removed||r.deleted)&&(i.include_deleted="true"),r.readDir&&(i.list="true",r.readDir!==!0&&(i.file_limit=""+r.readDir)),r.cacheHash&&(i.hash=r.cacheHash),r.httpCache&&(o=!0)),i.include_deleted||(i.include_deleted="false"),i.list||(i.list="false"),s=new t.Xhr("GET",""+this.urls.metadata+"/"+this.urlEncodePath(e)),s.setParams(i).signWithOauth(this.oauth,o),this.dispatchXhr(s,function(e,r){var o,i,s;return s=t.Stat.parse(r),o=(null!=r?r.contents:void 0)?function(){var e,n,o,s;for(o=r.contents,s=[],e=0,n=o.length;n>e;e++)i=o[e],s.push(t.Stat.parse(i));return s}():void 0,n(e,s,o)})},e.prototype.readdir=function(t,e,r){var n;return r||"function"!=typeof e||(r=e,e=null),n={readDir:!0},e&&(null!=e.limit&&(n.readDir=e.limit),e.versionTag&&(n.versionTag=e.versionTag),(e.removed||e.deleted)&&(n.removed=e.removed||e.deleted),e.httpCache&&(n.httpCache=e.httpCache)),this.stat(t,n,function(t,e,n){var o,i;return o=n?function(){var t,e,r;for(r=[],t=0,e=n.length;e>t;t++)i=n[t],r.push(i.name);return r}():null,r(t,o,e,n)})},e.prototype.metadata=function(t,e,r){return this.stat(t,e,r)},e.prototype.makeUrl=function(e,r,n){var o,i,s,a,h;return n||"function"!=typeof r||(n=r,r=null),i=r&&(r["long"]||r.longUrl||r.downloadHack)?{short_url:"false"}:{},e=this.urlEncodePath(e),s=""+this.urls.shares+"/"+e,o=!1,a=!1,r&&(r.downloadHack?(o=!0,a=!0):r.download&&(o=!0,s=""+this.urls.media+"/"+e)),h=new t.Xhr("POST",s).setParams(i).signWithOauth(this.oauth),this.dispatchXhr(h,function(e,r){return a&&r&&r.url&&(r.url=r.url.replace(this.authServer,this.downloadServer)),n(e,t.PublicUrl.parse(r,o))})},e.prototype.history=function(e,r,n){var o,i,s;return n||"function"!=typeof r||(n=r,r=null),i={},o=!1,r&&(null!=r.limit&&(i.rev_limit=r.limit),r.httpCache&&(o=!0)),s=new t.Xhr("GET",""+this.urls.revisions+"/"+this.urlEncodePath(e)),s.setParams(i).signWithOauth(this.oauth,o),this.dispatchXhr(s,function(e,r){var o,i;return i=r?function(){var e,n,i;for(i=[],e=0,n=r.length;n>e;e++)o=r[e],i.push(t.Stat.parse(o));return i}():void 0,n(e,i)})},e.prototype.revisions=function(t,e,r){return this.history(t,e,r)},e.prototype.thumbnailUrl=function(t,e){var r;return r=this.thumbnailXhr(t,e),r.paramsToUrl().url},e.prototype.readThumbnail=function(e,r,n){var o,i;return n||"function"!=typeof r||(n=r,r=null),o="b",r&&r.blob&&(o="blob"),i=this.thumbnailXhr(e,r),i.setResponseType(o),this.dispatchXhr(i,function(e,r,o){return n(e,r,t.Stat.parse(o))})},e.prototype.thumbnailXhr=function(e,r){var n,o;return n={},r&&(r.format?n.format=r.format:r.png&&(n.format="png"),r.size&&(n.size=r.size)),o=new t.Xhr("GET",""+this.urls.thumbnails+"/"+this.urlEncodePath(e)),o.setParams(n).signWithOauth(this.oauth)},e.prototype.revertFile=function(e,r,n){var o;return o=new t.Xhr("POST",""+this.urls.restore+"/"+this.urlEncodePath(e)),o.setParams({rev:r}).signWithOauth(this.oauth),this.dispatchXhr(o,function(e,r){return n(e,t.Stat.parse(r))})},e.prototype.restore=function(t,e,r){return this.revertFile(t,e,r)},e.prototype.findByName=function(e,r,n,o){var i,s,a;return o||"function"!=typeof n||(o=n,n=null),s={query:r},i=!1,n&&(null!=n.limit&&(s.file_limit=n.limit),(n.removed||n.deleted)&&(s.include_deleted=!0),n.httpCache&&(i=!0)),a=new t.Xhr("GET",""+this.urls.search+"/"+this.urlEncodePath(e)),a.setParams(s).signWithOauth(this.oauth,i),this.dispatchXhr(a,function(e,r){var n,i;return i=r?function(){var e,o,i;for(i=[],e=0,o=r.length;o>e;e++)n=r[e],i.push(t.Stat.parse(n));return i}():void 0,o(e,i)})},e.prototype.search=function(t,e,r,n){return this.findByName(t,e,r,n)},e.prototype.makeCopyReference=function(e,r){var n;return n=new t.Xhr("GET",""+this.urls.copyRef+"/"+this.urlEncodePath(e)),n.signWithOauth(this.oauth),this.dispatchXhr(n,function(e,n){return r(e,t.CopyReference.parse(n))})},e.prototype.copyRef=function(t,e){return this.makeCopyReference(t,e)},e.prototype.pullChanges=function(e,r){var n,o;return r||"function"!=typeof e||(r=e,e=null),n=e?e.cursorTag?{cursor:e.cursorTag}:{cursor:e}:{},o=new t.Xhr("POST",this.urls.delta),o.setParams(n).signWithOauth(this.oauth),this.dispatchXhr(o,function(e,n){return r(e,t.PulledChanges.parse(n))})},e.prototype.delta=function(t,e){return this.pullChanges(t,e)},e.prototype.mkdir=function(e,r){var n;return n=new t.Xhr("POST",this.urls.fileopsCreateFolder),n.setParams({root:this.fileRoot,path:this.normalizePath(e)}).signWithOauth(this.oauth),this.dispatchXhr(n,function(e,n){return r(e,t.Stat.parse(n))})},e.prototype.remove=function(e,r){var n;return n=new t.Xhr("POST",this.urls.fileopsDelete),n.setParams({root:this.fileRoot,path:this.normalizePath(e)}).signWithOauth(this.oauth),this.dispatchXhr(n,function(e,n){return r(e,t.Stat.parse(n))})},e.prototype.unlink=function(t,e){return this.remove(t,e)},e.prototype["delete"]=function(t,e){return this.remove(t,e)},e.prototype.copy=function(e,r,n){var o,i,s;return n||"function"!=typeof o||(n=o,o=null),i={root:this.fileRoot,to_path:this.normalizePath(r)},e instanceof t.CopyReference?i.from_copy_ref=e.tag:i.from_path=this.normalizePath(e),s=new t.Xhr("POST",this.urls.fileopsCopy),s.setParams(i).signWithOauth(this.oauth),this.dispatchXhr(s,function(e,r){return n(e,t.Stat.parse(r))})},e.prototype.move=function(e,r,n){var o,i;return n||"function"!=typeof o||(n=o,o=null),i=new t.Xhr("POST",this.urls.fileopsMove),i.setParams({root:this.fileRoot,from_path:this.normalizePath(e),to_path:this.normalizePath(r)}).signWithOauth(this.oauth),this.dispatchXhr(i,function(e,r){return n(e,t.Stat.parse(r))})},e.prototype.reset=function(){var t;return this.uid=null,this.oauth.setToken(null,""),t=this.authState,this.authState=n.RESET,t!==this.authState&&this.onAuthStateChange.dispatch(this),this.authError=null,this._credentials=null,this},e.prototype.setCredentials=function(t){var e;return e=this.authState,this.oauth.reset(t),this.uid=t.uid||null,this.authState=t.authState?t.authState:t.token?n.DONE:n.RESET,this.authError=null,this._credentials=null,e!==this.authState&&this.onAuthStateChange.dispatch(this),this},e.prototype.appHash=function(){return this.oauth.appHash()},e.prototype.setupUrls=function(){return this.fileRoot=this.sandbox?"sandbox":"dropbox",this.urls={requestToken:""+this.apiServer+"/1/oauth/request_token",authorize:""+this.authServer+"/1/oauth/authorize",accessToken:""+this.apiServer+"/1/oauth/access_token",signOut:""+this.apiServer+"/1/unlink_access_token",accountInfo:""+this.apiServer+"/1/account/info",getFile:""+this.fileServer+"/1/files/"+this.fileRoot,postFile:""+this.fileServer+"/1/files/"+this.fileRoot,putFile:""+this.fileServer+"/1/files_put/"+this.fileRoot,metadata:""+this.apiServer+"/1/metadata/"+this.fileRoot,delta:""+this.apiServer+"/1/delta",revisions:""+this.apiServer+"/1/revisions/"+this.fileRoot,restore:""+this.apiServer+"/1/restore/"+this.fileRoot,search:""+this.apiServer+"/1/search/"+this.fileRoot,shares:""+this.apiServer+"/1/shares/"+this.fileRoot,media:""+this.apiServer+"/1/media/"+this.fileRoot,copyRef:""+this.apiServer+"/1/copy_ref/"+this.fileRoot,thumbnails:""+this.fileServer+"/1/thumbnails/"+this.fileRoot,chunkedUpload:""+this.fileServer+"/1/chunked_upload",commitChunkedUpload:""+this.fileServer+"/1/commit_chunked_upload/"+this.fileRoot,fileopsCopy:""+this.apiServer+"/1/fileops/copy",fileopsCreateFolder:""+this.apiServer+"/1/fileops/create_folder",fileopsDelete:""+this.apiServer+"/1/fileops/delete",fileopsMove:""+this.apiServer+"/1/fileops/move"}},e.prototype.authState=null,e.ERROR=0,e.RESET=1,e.REQUEST=2,e.AUTHORIZED=3,e.DONE=4,e.SIGNED_OFF=5,e.prototype.urlEncodePath=function(e){return t.Xhr.urlEncodeValue(this.normalizePath(e)).replace(/%2F/gi,"/")},e.prototype.normalizePath=function(t){var e;if("/"===t.substring(0,1)){for(e=1;"/"===t.substring(e,e+1);)e+=1;return t.substring(e)}return t},e.prototype.requestToken=function(e){var r;return r=new t.Xhr("POST",this.urls.requestToken).signWithOauth(this.oauth),this.dispatchXhr(r,e)},e.prototype.authorizeUrl=function(e){var r;return r={oauth_token:e,oauth_callback:this.driver.url()},""+this.urls.authorize+"?"+t.Xhr.urlEncode(r)},e.prototype.getAccessToken=function(e){var r;return r=new t.Xhr("POST",this.urls.accessToken).signWithOauth(this.oauth),this.dispatchXhr(r,e)},e.prototype.dispatchXhr=function(t,e){var r;return t.setCallback(e),t.onError=this.onError,t.prepare(),r=t.xhr,this.onXhr.dispatch(t)&&t.send(),r},e.prototype.defaultApiServer=function(){return"https://api.dropbox.com"},e.prototype.defaultAuthServer=function(){return this.apiServer.replace("api.","www.")},e.prototype.defaultFileServer=function(){return this.apiServer.replace("api.","api-content.")},e.prototype.defaultDownloadServer=function(){return this.apiServer.replace("api.","dl.")},e.prototype.computeCredentials=function(){var t;return t={key:this.oauth.key,sandbox:this.sandbox},this.oauth.secret&&(t.secret=this.oauth.secret),this.oauth.token&&(t.token=this.oauth.token,t.tokenSecret=this.oauth.tokenSecret),this.uid&&(t.uid=this.uid),this.authState!==n.ERROR&&this.authState!==n.RESET&&this.authState!==n.DONE&&this.authState!==n.SIGNED_OFF&&(t.authState=this.authState),this.apiServer!==this.defaultApiServer()&&(t.server=this.apiServer),this.authServer!==this.defaultAuthServer()&&(t.authServer=this.authServer),this.fileServer!==this.defaultFileServer()&&(t.fileServer=this.fileServer),this.downloadServer!==this.defaultDownloadServer()&&(t.downloadServer=this.downloadServer),this._credentials=t},e}(),n=t.Client,t.AuthDriver=function(){function t(){}return t.prototype.url=function(){return"https://some.url"},t.prototype.doAuthorize=function(t,e,r,n){return n("oauth-token")},t.prototype.onAuthStateChange=function(t,e){return e()},t}(),t.Drivers={},t.Drivers.BrowserBase=function(){function t(t){this.rememberUser=(null!=t?t.rememberUser:void 0)||!1,this.scope=(null!=t?t.scope:void 0)||"default",this.storageKey=null}return t.prototype.onAuthStateChange=function(t,e){var r=this;switch(this.setStorageKey(t),t.authState){case n.RESET:return this.loadCredentials(function(n){return n?n.authState?(t.setCredentials(n),e()):r.rememberUser?(t.setCredentials(n),t.getUserInfo(function(n){return n?(t.reset(),r.forgetCredentials(e)):e()})):(r.forgetCredentials(),e()):e()});case n.REQUEST:return this.storeCredentials(t.credentials(),e);case n.DONE:return this.rememberUser?this.storeCredentials(t.credentials(),e):this.forgetCredentials(e);case n.SIGNED_OFF:return this.forgetCredentials(e);case n.ERROR:return this.forgetCredentials(e);default:return e(),this}},t.prototype.setStorageKey=function(t){return this.storageKey="dropbox-auth:"+this.scope+":"+t.appHash(),this},t.prototype.storeCredentials=function(t,e){return localStorage.setItem(this.storageKey,JSON.stringify(t)),e(),this},t.prototype.loadCredentials=function(t){var e;if(e=localStorage.getItem(this.storageKey),!e)return t(null),this;try{t(JSON.parse(e))}catch(r){t(null)}return this},t.prototype.forgetCredentials=function(t){return localStorage.removeItem(this.storageKey),t(),this},t.currentLocation=function(){return window.location.href},t}(),t.Drivers.Redirect=function(e){function r(t){r.__super__.constructor.call(this,t),this.useQuery=(null!=t?t.useQuery:void 0)||!1,this.receiverUrl=this.computeUrl(t),this.tokenRe=RegExp("(#|\\?|&)oauth_token=([^]+)(&|#|$)")}return T(r,e),r.prototype.onAuthStateChange=function(t,e){var o,i=this;return o=function(){return function(){return r.__super__.onAuthStateChange.call(i,t,e)}}(),this.setStorageKey(t),t.authState===n.RESET?this.loadCredentials(function(t){return t&&t.authState?t.token===i.locationToken()&&t.authState===n.REQUEST?(t.authState=n.AUTHORIZED,i.storeCredentials(t,o)):i.forgetCredentials(o):o()}):o()},r.prototype.url=function(){return this.receiverUrl},r.prototype.doAuthorize=function(t){return window.location.assign(t)},r.prototype.computeUrl=function(){var e,r,n,o;return o="_dropboxjs_scope="+encodeURIComponent(this.scope),r=t.Drivers.BrowserBase.currentLocation(),-1===r.indexOf("#")?e=null:(n=r.split("#",2),r=n[0],e=n[1]),this.useQuery?r+=-1===r.indexOf("?")?"?"+o:"&"+o:e="?"+o,e?r+"#"+e:r},r.prototype.locationToken=function(){var e,r,n;return e=t.Drivers.BrowserBase.currentLocation(),n="_dropboxjs_scope="+encodeURIComponent(this.scope)+"&",-1===("function"==typeof e.indexOf?e.indexOf(n):void 0)?null:(r=this.tokenRe.exec(e),r?decodeURIComponent(r[2]):null)},r}(t.Drivers.BrowserBase),t.Drivers.Popup=function(e){function r(t){r.__super__.constructor.call(this,t),this.receiverUrl=this.computeUrl(t),this.tokenRe=RegExp("(#|\\?|&)oauth_token=([^]+)(&|#|$)")}return T(r,e),r.prototype.onAuthStateChange=function(t,e){var o,i=this;return o=function(){return function(){return r.__super__.onAuthStateChange.call(i,t,e)}}(),this.setStorageKey(t),t.authState===n.RESET?this.loadCredentials(function(t){return t&&t.authState?i.forgetCredentials(o):o()}):o()},r.prototype.doAuthorize=function(t,e,r,n){return this.listenForMessage(e,n),this.openWindow(t)},r.prototype.url=function(){return this.receiverUrl},r.prototype.computeUrl=function(e){var r;if(e){if(e.receiverUrl)return e.noFragment||-1!==e.receiverUrl.indexOf("#")?e.receiverUrl:e.receiverUrl+"#";if(e.receiverFile)return r=t.Drivers.BrowserBase.currentLocation().split("/"),r[r.length-1]=e.receiverFile,e.noFragment?r.join("/"):r.join("/")+"#"}return t.Drivers.BrowserBase.currentLocation()},r.prototype.openWindow=function(t){return window.open(t,"_dropboxOauthSigninWindow",this.popupWindowSpec(980,700))},r.prototype.popupWindowSpec=function(t,e){var r,n,o,i,s,a,h,u,l,p;return s=null!=(h=window.screenX)?h:window.screenLeft,a=null!=(u=window.screenY)?u:window.screenTop,i=null!=(l=window.outerWidth)?l:document.documentElement.clientWidth,r=null!=(p=window.outerHeight)?p:document.documentElement.clientHeight,n=Math.round(s+(i-t)/2),o=Math.round(a+(r-e)/2.5),s>n&&(n=s),a>o&&(o=a),"width="+t+",height="+e+","+("left="+n+",top="+o)+"dialog=yes,dependent=yes,scrollbars=yes,location=yes"},r.prototype.listenForMessage=function(t,e){var r,n=this;return r=function(o){var i;return i=n.tokenRe.exec(""+o.data),i&&decodeURIComponent(i[2])===t?(window.removeEventListener("message",r),e()):void 0},window.addEventListener("message",r,!1)},r.oauthReceiver=function(){return window.addEventListener("load",function(){var t;if(t=window.opener,window.parent!==window.top&&(t||(t=window.parent)),t){try{t.postMessage(window.location.href,"*")}catch(e){}return window.close()}})},r}(t.Drivers.BrowserBase),e=null,r=null,"undefined"!=typeof chrome&&null!==chrome&&(chrome.runtime&&(chrome.runtime.onMessage&&(e=chrome.runtime.onMessage),chrome.runtime.sendMessage&&(r=function(t){return chrome.runtime.sendMessage(t)})),chrome.extension&&(chrome.extension.onMessage&&(e||(e=chrome.extension.onMessage)),chrome.extension.sendMessage&&(r||(r=function(t){return chrome.extension.sendMessage(t)}))),e||function(){var e,r;return r=function(e){return e.Dropbox?(t.Drivers.Chrome.prototype.onMessage=e.Dropbox.Drivers.Chrome.onMessage,t.Drivers.Chrome.prototype.sendMessage=e.Dropbox.Drivers.Chrome.sendMessage):(e.Dropbox=t,t.Drivers.Chrome.prototype.onMessage=new t.EventSource,t.Drivers.Chrome.prototype.sendMessage=function(e){return t.Drivers.Chrome.prototype.onMessage.dispatch(e)})},chrome.extension&&chrome.extension.getBackgroundPage&&(e=chrome.extension.getBackgroundPage())?r(e):chrome.runtime&&chrome.runtime.getBackgroundPage?chrome.runtime.getBackgroundPage(function(t){return r(t)}):void 0}()),t.Drivers.Chrome=function(){function n(t){var e,r;e=t&&t.receiverPath||"chrome_oauth_receiver.html",this.receiverUrl=this.expandUrl(e),this.tokenRe=RegExp("(#|\\?|&)oauth_token=([^]+)(&|#|$)"),r=t&&t.scope||"default",this.storageKey="dropbox_js_"+r+"_credentials"}return n.prototype.onMessage=e,n.prototype.sendMessage=r,n.prototype.expandUrl=function(t){return chrome.runtime&&chrome.runtime.getURL?chrome.runtime.getURL(t):chrome.extension&&chrome.extension.getURL?chrome.extension.getURL(t):t},n.prototype.onAuthStateChange=function(e,r){var n=this;switch(e.authState){case t.Client.RESET:return this.loadCredentials(function(t){if(t){if(t.authState)return n.forgetCredentials(r);e.setCredentials(t)}return r()});case t.Client.DONE:return this.storeCredentials(e.credentials(),r);case t.Client.SIGNED_OFF:return this.forgetCredentials(r);case t.Client.ERROR:return this.forgetCredentials(r);default:return r()}},n.prototype.doAuthorize=function(t,e,r,n){var o;return o={handle:null},this.listenForMessage(e,o,n),this.openWindow(t,function(t){return o.handle=t})},n.prototype.openWindow=function(t,e){return chrome.tabs&&chrome.tabs.create?(chrome.tabs.create({url:t,active:!0,pinned:!1},function(t){return e(t)}),this):chrome.app&&chrome.app.window&&chrome.app.window.create?(chrome.app.window.create(t,{frame:"none",id:"dropbox-auth"},function(t){return e(t)}),this):this},n.prototype.closeWindow=function(t){return chrome.tabs&&chrome.tabs.remove&&t.id?(chrome.tabs.remove(t.id),this):chrome.app&&chrome.app.window&&t.close?(t.close(),this):this},n.prototype.url=function(){return this.receiverUrl},n.prototype.listenForMessage=function(t,e,r){var n,o=this;return n=function(i,s){var a;if(!s||!s.tab||s.tab.url.substring(0,o.receiverUrl.length)===o.receiverUrl)return a=o.tokenRe.exec(i.dropbox_oauth_receiver_href||""),a&&decodeURIComponent(a[2])===t?(e.handle&&o.closeWindow(e.handle),o.onMessage.removeListener(n),r()):void 0},this.onMessage.addListener(n)},n.prototype.storeCredentials=function(t,e){var r;return r={},r[this.storageKey]=t,chrome.storage.local.set(r,e),this},n.prototype.loadCredentials=function(t){var e=this;return chrome.storage.local.get(this.storageKey,function(r){return t(r[e.storageKey]||null)}),this},n.prototype.forgetCredentials=function(t){return chrome.storage.local.remove(this.storageKey,t),this},n.oauthReceiver=function(){return window.addEventListener("load",function(){var e;return e=new t.Drivers.Chrome,e.sendMessage({dropbox_oauth_receiver_href:window.location.href}),window.close?window.close():void 0})},n}(),t.Drivers.NodeServer=function(){function t(t){this.port=(null!=t?t.port:void 0)||8912,this.faviconFile=(null!=t?t.favicon:void 0)||null,this.fs=require("fs"),this.http=require("http"),this.open=require("open"),this.callbacks={},this.urlRe=RegExp("^/oauth_callback\\?"),this.tokenRe=RegExp("(\\?|&)oauth_token=([^&]+)(&|$)"),this.createApp()}return t.prototype.url=function(){return"http://localhost:"+this.port+"/oauth_callback"},t.prototype.doAuthorize=function(t,e,r,n){return this.callbacks[e]=n,this.openBrowser(t)},t.prototype.openBrowser=function(t){if(!t.match(/^https?:\/\//))throw Error("Not a http/https URL: "+t);return this.open(t)},t.prototype.createApp=function(){var t=this;return this.app=this.http.createServer(function(e,r){return t.doRequest(e,r)}),this.app.listen(this.port)},t.prototype.closeServer=function(){return this.app.close()},t.prototype.doRequest=function(t,e){var r,n,o,i=this;return this.urlRe.exec(t.url)&&(n=this.tokenRe.exec(t.url),n&&(o=decodeURIComponent(n[2]),this.callbacks[o]&&(this.callbacks[o](),delete this.callbacks[o]))),r="",t.on("data",function(t){return r+=t}),t.on("end",function(){return i.faviconFile&&"/favicon.ico"===t.url?i.sendFavicon(e):i.closeBrowser(e)})},t.prototype.closeBrowser=function(t){var e;return e='\n\nPlease close this window.
',t.writeHead(200,{"Content-Length":e.length,"Content-Type":"text/html"}),t.write(e),t.end},t.prototype.sendFavicon=function(t){return this.fs.readFile(this.faviconFile,function(e,r){return t.writeHead(200,{"Content-Length":r.length,"Content-Type":"image/x-icon"}),t.write(r),t.end})},t}(),t.EventSource=function(){function t(t){this._cancelable=t&&t.cancelable,this._listeners=[]}return t.prototype.addListener=function(t){if("function"!=typeof t)throw new TypeError("Invalid listener type; expected function");return 0>k.call(this._listeners,t)&&this._listeners.push(t),this},t.prototype.removeListener=function(t){var e,r,n,o,i,s;if(this._listeners.indexOf)r=this._listeners.indexOf(t),-1!==r&&this._listeners.splice(r,1);else for(s=this._listeners,e=o=0,i=s.length;i>o;e=++o)if(n=s[e],n===t){this._listeners.splice(e,1);break}return this},t.prototype.dispatch=function(t){var e,r,n,o,i;for(i=this._listeners,n=0,o=i.length;o>n;n++)if(e=i[n],r=e(t),this._cancelable&&r===!1)return!1;return!0},t}(),y=function(t,e){return p(b(C(t),C(e),t.length,e.length))},v=function(t){return p(E(C(t),t.length))},("undefined"==typeof window||null===window)&&(w=require("crypto"),y=function(t,e){var r;return r=w.createHmac("sha1",e),r.update(t),r.digest("base64")},v=function(t){var e;return e=w.createHash("sha1"),e.update(t),e.digest("base64")}),b=function(t,e,r,n){var o,i,s,a;return e.length>16&&(e=E(e,n)),s=function(){var t,r;for(r=[],i=t=0;16>t;i=++t)r.push(909522486^e[i]);return r}(),a=function(){var t,r;for(r=[],i=t=0;16>t;i=++t)r.push(1549556828^e[i]);return r}(),o=E(s.concat(t),64+r),E(a.concat(o),84)},E=function(t,e){var r,n,o,i,s,a,h,u,p,c,d,f,y,v,m,g,w,S;for(t[e>>2]|=1<<31-((3&e)<<3),t[(e+8>>6<<4)+15]=e<<3,g=Array(80),r=1732584193,o=-271733879,s=-1732584194,h=271733878,p=-1009589776,f=0,m=t.length;m>f;){for(n=r,i=o,a=s,u=h,c=p,y=S=0;80>S;y=++S)g[y]=16>y?t[f+y]:_(g[y-3]^g[y-8]^g[y-14]^g[y-16],1),20>y?(d=o&s|~o&h,v=1518500249):40>y?(d=o^s^h,v=1859775393):60>y?(d=o&s|o&h|s&h,v=-1894007588):(d=o^s^h,v=-899497514),w=l(l(_(r,5),d),l(l(p,g[y]),v)),p=h,h=s,s=_(o,30),o=r,r=w;r=l(r,n),o=l(o,i),s=l(s,a),h=l(h,u),p=l(p,c),f+=16}return[r,o,s,h,p]},_=function(t,e){return t<>>32-e},l=function(t,e){var r,n;return n=(65535&t)+(65535&e),r=(t>>16)+(e>>16)+(n>>16),r<<16|65535&n},p=function(t){var e,r,n,o,i;for(o="",e=0,n=4*t.length;n>e;)r=e,i=(255&t[r>>2]>>(3-(3&r)<<3))<<16,r+=1,i|=(255&t[r>>2]>>(3-(3&r)<<3))<<8,r+=1,i|=255&t[r>>2]>>(3-(3&r)<<3),o+=x[63&i>>18],o+=x[63&i>>12],e+=1,o+=e>=n?"=":x[63&i>>6],e+=1,o+=e>=n?"=":x[63&i],e+=1;return o},x="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",C=function(t){var e,r,n,o,i;for(e=[],n=255,r=o=0,i=t.length;i>=0?i>o:o>i;r=i>=0?++o:--o)e[r>>2]|=(t.charCodeAt(r)&n)<<(3-(3&r)<<3);return e},t.Oauth=function(){function e(t){this.key=this.k=null,this.secret=this.s=null,this.token=null,this.tokenSecret=null,this._appHash=null,this.reset(t)}return e.prototype.reset=function(t){var e,r,n,o;if(t.secret)this.k=this.key=t.key,this.s=this.secret=t.secret,this._appHash=null;else if(t.key)this.key=t.key,this.secret=null,n=c(S(this.key).split("|",2)[1]),o=n.split("?",2),e=o[0],r=o[1],this.k=decodeURIComponent(e),this.s=decodeURIComponent(r),this._appHash=null;else if(!this.k)throw Error("No API key supplied");return t.token?this.setToken(t.token,t.tokenSecret):this.setToken(null,"")},e.prototype.setToken=function(e,r){if(e&&!r)throw Error("No secret supplied with the user token");return this.token=e,this.tokenSecret=r||"",this.hmacKey=t.Xhr.urlEncodeValue(this.s)+"&"+t.Xhr.urlEncodeValue(r),null},e.prototype.authHeader=function(e,r,n){var o,i,s,a,h,u;this.addAuthParams(e,r,n),i=[];for(s in n)a=n[s],"oauth_"===s.substring(0,6)&&i.push(s);for(i.sort(),o=[],h=0,u=i.length;u>h;h++)s=i[h],o.push(t.Xhr.urlEncodeValue(s)+'="'+t.Xhr.urlEncodeValue(n[s])+'"'),delete n[s];return"OAuth "+o.join(",")},e.prototype.addAuthParams=function(t,e,r){return this.boilerplateParams(r),r.oauth_signature=this.signature(t,e,r),r},e.prototype.boilerplateParams=function(t){return t.oauth_consumer_key=this.k,t.oauth_nonce=this.nonce(),t.oauth_signature_method="HMAC-SHA1",this.token&&(t.oauth_token=this.token),t.oauth_timestamp=Math.floor(Date.now()/1e3),t.oauth_version="1.0",t},e.prototype.nonce=function(){return Date.now().toString(36)+Math.random().toString(36)},e.prototype.signature=function(e,r,n){var o;return o=e.toUpperCase()+"&"+t.Xhr.urlEncodeValue(r)+"&"+t.Xhr.urlEncodeValue(t.Xhr.urlEncode(n)),y(o,this.hmacKey)},e.prototype.appHash=function(){return this._appHash?this._appHash:this._appHash=v(this.k).replace(/\=/g,"")},e}(),null==Date.now&&(Date.now=function(){return(new Date).getTime()}),S=function(t,e){var r,n,o,i,s,a,h,u,l,p,d,f;for(e?(e=[encodeURIComponent(t),encodeURIComponent(e)].join("?"),t=function(){var e,n,o;for(o=[],r=e=0,n=t.length/2;n>=0?n>e:e>n;r=n>=0?++e:--e)o.push(16*(15&t.charCodeAt(2*r))+(15&t.charCodeAt(2*r+1)));
-return o}()):(p=t.split("|",2),t=p[0],e=p[1],t=c(t),t=function(){var e,n,o;for(o=[],r=e=0,n=t.length;n>=0?n>e:e>n;r=n>=0?++e:--e)o.push(t.charCodeAt(r));return o}(),e=c(e)),i=function(){for(f=[],u=0;256>u;u++)f.push(u);return f}.apply(this),a=0,s=l=0;256>l;s=++l)a=(a+i[r]+t[s%t.length])%256,d=[i[a],i[s]],i[s]=d[0],i[a]=d[1];return s=a=0,o=function(){var t,r,o,u;for(u=[],h=t=0,r=e.length;r>=0?r>t:t>r;h=r>=0?++t:--t)s=(s+1)%256,a=(a+i[s])%256,o=[i[a],i[s]],i[s]=o[0],i[a]=o[1],n=i[(i[s]+i[a])%256],u.push(String.fromCharCode((n^e.charCodeAt(h))%256));return u}(),t=function(){var e,n,o;for(o=[],r=e=0,n=t.length;n>=0?n>e:e>n;r=n>=0?++e:--e)o.push(String.fromCharCode(t[r]));return o}(),[m(t.join("")),m(o.join(""))].join("|")},t.PulledChanges=function(){function e(e){var r;this.blankSlate=e.reset||!1,this.cursorTag=e.cursor,this.shouldPullAgain=e.has_more,this.shouldBackOff=!this.shouldPullAgain,this.changes=e.cursor&&e.cursor.length?function(){var n,o,i,s;for(i=e.entries,s=[],n=0,o=i.length;o>n;n++)r=i[n],s.push(t.PullChange.parse(r));return s}():[]}return e.parse=function(e){return e&&"object"==typeof e?new t.PulledChanges(e):e},e.prototype.blankSlate=void 0,e.prototype.cursorTag=void 0,e.prototype.changes=void 0,e.prototype.shouldPullAgain=void 0,e.prototype.shouldBackOff=void 0,e.prototype.cursor=function(){return this.cursorTag},e}(),t.PullChange=function(){function e(e){this.path=e[0],this.stat=t.Stat.parse(e[1]),this.stat?this.wasRemoved=!1:(this.stat=null,this.wasRemoved=!0)}return e.parse=function(e){return e&&"object"==typeof e?new t.PullChange(e):e},e.prototype.path=void 0,e.prototype.wasRemoved=void 0,e.prototype.stat=void 0,e}(),t.PublicUrl=function(){function e(t,e){this.url=t.url,this.expiresAt=new Date(Date.parse(t.expires)),this.isDirect=e===!0?!0:e===!1?!1:"direct"in t?t.direct:864e5>=Date.now()-this.expiresAt,this.isPreview=!this.isDirect,this._json=null}return e.parse=function(e,r){return e&&"object"==typeof e?new t.PublicUrl(e,r):e},e.prototype.url=null,e.prototype.expiresAt=null,e.prototype.isDirect=null,e.prototype.isPreview=null,e.prototype.json=function(){return this._json||(this._json={url:this.url,expires:""+this.expiresAt,direct:this.isDirect})},e}(),t.CopyReference=function(){function e(t){"object"==typeof t?(this.tag=t.copy_ref,this.expiresAt=new Date(Date.parse(t.expires)),this._json=t):(this.tag=t,this.expiresAt=new Date(1e3*Math.ceil(Date.now()/1e3)),this._json=null)}return e.parse=function(e){return!e||"object"!=typeof e&&"string"!=typeof e?e:new t.CopyReference(e)},e.prototype.tag=null,e.prototype.expiresAt=null,e.prototype.json=function(){return this._json||(this._json={copy_ref:this.tag,expires:""+this.expiresAt})},e}(),t.Stat=function(){function e(t){var e,r,n,o;switch(this._json=t,this.path=t.path,"/"!==this.path.substring(0,1)&&(this.path="/"+this.path),e=this.path.length-1,e>=0&&"/"===this.path.substring(e)&&(this.path=this.path.substring(0,e)),r=this.path.lastIndexOf("/"),this.name=this.path.substring(r+1),this.isFolder=t.is_dir||!1,this.isFile=!this.isFolder,this.isRemoved=t.is_deleted||!1,this.typeIcon=t.icon,this.modifiedAt=(null!=(n=t.modified)?n.length:void 0)?new Date(Date.parse(t.modified)):null,this.clientModifiedAt=(null!=(o=t.client_mtime)?o.length:void 0)?new Date(Date.parse(t.client_mtime)):null,t.root){case"dropbox":this.inAppFolder=!1;break;case"app_folder":this.inAppFolder=!0;break;default:this.inAppFolder=null}this.size=t.bytes||0,this.humanSize=t.size||"",this.hasThumbnail=t.thumb_exists||!1,this.isFolder?(this.versionTag=t.hash,this.mimeType=t.mime_type||"inode/directory"):(this.versionTag=t.rev,this.mimeType=t.mime_type||"application/octet-stream")}return e.parse=function(e){return e&&"object"==typeof e?new t.Stat(e):e},e.prototype.path=null,e.prototype.name=null,e.prototype.inAppFolder=null,e.prototype.isFolder=null,e.prototype.isFile=null,e.prototype.isRemoved=null,e.prototype.typeIcon=null,e.prototype.versionTag=null,e.prototype.mimeType=null,e.prototype.size=null,e.prototype.humanSize=null,e.prototype.hasThumbnail=null,e.prototype.modifiedAt=null,e.prototype.clientModifiedAt=null,e.prototype.json=function(){return this._json},e}(),t.UploadCursor=function(){function e(t){this.replace(t)}return e.parse=function(e){return!e||"object"!=typeof e&&"string"!=typeof e?e:new t.UploadCursor(e)},e.prototype.tag=null,e.prototype.offset=null,e.prototype.expiresAt=null,e.prototype.json=function(){return this._json||(this._json={upload_id:this.tag,offset:this.offset,expires:""+this.expiresAt})},e.prototype.replace=function(t){return"object"==typeof t?(this.tag=t.upload_id||null,this.offset=t.offset||0,this.expiresAt=new Date(Date.parse(t.expires)||Date.now()),this._json=t):(this.tag=t||null,this.offset=0,this.expiresAt=new Date(1e3*Math.floor(Date.now()/1e3)),this._json=null),this},e}(),t.UserInfo=function(){function e(t){var e;this._json=t,this.name=t.display_name,this.email=t.email,this.countryCode=t.country||null,this.uid=""+t.uid,t.public_app_url?(this.publicAppUrl=t.public_app_url,e=this.publicAppUrl.length-1,e>=0&&"/"===this.publicAppUrl.substring(e)&&(this.publicAppUrl=this.publicAppUrl.substring(0,e))):this.publicAppUrl=null,this.referralUrl=t.referral_link,this.quota=t.quota_info.quota,this.privateBytes=t.quota_info.normal||0,this.sharedBytes=t.quota_info.shared||0,this.usedQuota=this.privateBytes+this.sharedBytes}return e.parse=function(e){return e&&"object"==typeof e?new t.UserInfo(e):e},e.prototype.name=null,e.prototype.email=null,e.prototype.countryCode=null,e.prototype.uid=null,e.prototype.referralUrl=null,e.prototype.publicAppUrl=null,e.prototype.quota=null,e.prototype.usedQuota=null,e.prototype.privateBytes=null,e.prototype.sharedBytes=null,e.prototype.json=function(){return this._json},e}(),"undefined"!=typeof window&&null!==window?(!window.XDomainRequest||"withCredentials"in new XMLHttpRequest?(h=window.XMLHttpRequest,a=!1,i=-1===window.navigator.userAgent.indexOf("Firefox")):(h=window.XDomainRequest,a=!0,i=!1),s=!0):(h=require("xmlhttprequest").XMLHttpRequest,a=!1,i=!1,s=!1),"undefined"==typeof Uint8Array?(o=null,u=!1):(Object.getPrototypeOf?o=Object.getPrototypeOf(Object.getPrototypeOf(new Uint8Array(0))).constructor:Object.__proto__&&(o=new Uint8Array(0).__proto__.__proto__.constructor),u=o!==Object),t.Xhr=function(){function e(t,e){this.method=t,this.isGet="GET"===this.method,this.url=e,this.headers={},this.params=null,this.body=null,this.preflight=!(this.isGet||"POST"===this.method),this.signed=!1,this.responseType=null,this.callback=null,this.xhr=null,this.onError=null}return e.Request=h,e.ieXdr=a,e.canSendForms=i,e.doesPreflight=s,e.ArrayBufferView=o,e.sendArrayBufferView=u,e.prototype.xhr=null,e.prototype.onError=null,e.prototype.setParams=function(t){if(this.signed)throw Error("setParams called after addOauthParams or addOauthHeader");if(this.params)throw Error("setParams cannot be called twice");return this.params=t,this},e.prototype.setCallback=function(t){return this.callback=t,this},e.prototype.signWithOauth=function(e,r){return t.Xhr.ieXdr?this.addOauthParams(e):this.preflight||!t.Xhr.doesPreflight?this.addOauthHeader(e):this.isGet&&r?this.addOauthHeader(e):this.addOauthParams(e)},e.prototype.addOauthParams=function(t){if(this.signed)throw Error("Request already has an OAuth signature");return this.params||(this.params={}),t.addAuthParams(this.method,this.url,this.params),this.signed=!0,this},e.prototype.addOauthHeader=function(t){if(this.signed)throw Error("Request already has an OAuth signature");return this.params||(this.params={}),this.signed=!0,this.setHeader("Authorization",t.authHeader(this.method,this.url,this.params))},e.prototype.setBody=function(t){if(this.isGet)throw Error("setBody cannot be called on GET requests");if(null!==this.body)throw Error("Request already has a body");return"string"==typeof t||"undefined"!=typeof FormData&&t instanceof FormData||(this.headers["Content-Type"]="application/octet-stream",this.preflight=!0),this.body=t,this},e.prototype.setResponseType=function(t){return this.responseType=t,this},e.prototype.setHeader=function(t,e){var r;if(this.headers[t])throw r=this.headers[t],Error("HTTP header "+t+" already set to "+r);if("Content-Type"===t)throw Error("Content-Type is automatically computed based on setBody");return this.preflight=!0,this.headers[t]=e,this},e.prototype.setFileField=function(e,r,n,o){var i,s;if(null!==this.body)throw Error("Request already has a body");if(this.isGet)throw Error("setFileField cannot be called on GET requests");return"object"==typeof n&&"undefined"!=typeof Blob?("undefined"!=typeof ArrayBuffer&&(n instanceof ArrayBuffer?t.Xhr.sendArrayBufferView&&(n=new Uint8Array(n)):!t.Xhr.sendArrayBufferView&&0===n.byteOffset&&n.buffer instanceof ArrayBuffer&&(n=n.buffer)),o||(o="application/octet-stream"),n=new Blob([n],{type:o}),"undefined"!=typeof File&&n instanceof File&&(n=new Blob([n],{type:n.type})),s=n instanceof Blob):s=!1,s?(this.body=new FormData,this.body.append(e,n,r)):(o||(o="application/octet-stream"),i=this.multipartBoundary(),this.headers["Content-Type"]="multipart/form-data; boundary="+i,this.body=["--",i,"\r\n",'Content-Disposition: form-data; name="',e,'"; filename="',r,'"\r\n',"Content-Type: ",o,"\r\n","Content-Transfer-Encoding: binary\r\n\r\n",n,"\r\n","--",i,"--","\r\n"].join(""))},e.prototype.multipartBoundary=function(){return[Date.now().toString(36),Math.random().toString(36)].join("----")},e.prototype.paramsToUrl=function(){var e;return this.params&&(e=t.Xhr.urlEncode(this.params),0!==e.length&&(this.url=[this.url,"?",e].join("")),this.params=null),this},e.prototype.paramsToBody=function(){if(this.params){if(null!==this.body)throw Error("Request already has a body");if(this.isGet)throw Error("paramsToBody cannot be called on GET requests");this.headers["Content-Type"]="application/x-www-form-urlencoded",this.body=t.Xhr.urlEncode(this.params),this.params=null}return this},e.prototype.prepare=function(){var e,r,n,o,i=this;if(r=t.Xhr.ieXdr,this.isGet||null!==this.body||r?(this.paramsToUrl(),null!==this.body&&"string"==typeof this.body&&(this.headers["Content-Type"]="text/plain; charset=utf8")):this.paramsToBody(),this.xhr=new t.Xhr.Request,r?(this.xhr.onload=function(){return i.onXdrLoad()},this.xhr.onerror=function(){return i.onXdrError()},this.xhr.ontimeout=function(){return i.onXdrError()},this.xhr.onprogress=function(){}):this.xhr.onreadystatechange=function(){return i.onReadyStateChange()},this.xhr.open(this.method,this.url,!0),!r){o=this.headers;for(e in o)R.call(o,e)&&(n=o[e],this.xhr.setRequestHeader(e,n))}return this.responseType&&("b"===this.responseType?this.xhr.overrideMimeType&&this.xhr.overrideMimeType("text/plain; charset=x-user-defined"):this.xhr.responseType=this.responseType),this},e.prototype.send=function(e){var r;if(this.callback=e||this.callback,null!==this.body){r=this.body,t.Xhr.sendArrayBufferView&&r instanceof ArrayBuffer&&(r=new Uint8Array(r));try{this.xhr.send(r)}catch(n){if(t.Xhr.sendArrayBufferView||"undefined"==typeof Blob)throw n;r=new Blob([r],{type:"application/octet-stream"}),this.xhr.send(r)}}else this.xhr.send();return this},e.urlEncode=function(t){var e,r,n;e=[];for(r in t)n=t[r],e.push(this.urlEncodeValue(r)+"="+this.urlEncodeValue(n));return e.sort().join("&")},e.urlEncodeValue=function(t){return encodeURIComponent(""+t).replace(/\!/g,"%21").replace(/'/g,"%27").replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/\*/g,"%2A")},e.urlDecode=function(t){var e,r,n,o,i,s;for(r={},s=t.split("&"),o=0,i=s.length;i>o;o++)n=s[o],e=n.split("="),r[decodeURIComponent(e[0])]=decodeURIComponent(e[1]);return r},e.prototype.onReadyStateChange=function(){var e,r,n,o,i,s,a,h,u;if(4!==this.xhr.readyState)return!0;if(200>this.xhr.status||this.xhr.status>=300)return e=new t.ApiError(this.xhr,this.method,this.url),this.onError&&this.onError.dispatch(e),this.callback(e),!0;if(s=this.xhr.getResponseHeader("x-dropbox-metadata"),null!=s?s.length:void 0)try{i=JSON.parse(s)}catch(l){i=void 0}else i=void 0;if(this.responseType){if("b"===this.responseType){for(n=null!=this.xhr.responseText?this.xhr.responseText:this.xhr.response,r=[],o=h=0,u=n.length;u>=0?u>h:h>u;o=u>=0?++h:--h)r.push(String.fromCharCode(255&n.charCodeAt(o)));a=r.join(""),this.callback(null,a,i)}else this.callback(null,this.xhr.response,i);return!0}switch(a=null!=this.xhr.responseText?this.xhr.responseText:this.xhr.response,this.xhr.getResponseHeader("Content-Type")){case"application/x-www-form-urlencoded":this.callback(null,t.Xhr.urlDecode(a),i);break;case"application/json":case"text/javascript":this.callback(null,JSON.parse(a),i);break;default:this.callback(null,a,i)}return!0},e.prototype.onXdrLoad=function(){var e;switch(e=this.xhr.responseText,this.xhr.contentType){case"application/x-www-form-urlencoded":this.callback(null,t.Xhr.urlDecode(e),void 0);break;case"application/json":case"text/javascript":this.callback(null,JSON.parse(e),void 0);break;default:this.callback(null,e,void 0)}return!0},e.prototype.onXdrError=function(){var e;return e=new t.ApiError(this.xhr,this.method,this.url),this.onError&&this.onError.dispatch(e),this.callback(e),!0},e}(),null!=("undefined"!=typeof module&&null!==module?module.exports:void 0))module.exports=t;else{if("undefined"==typeof window||null===window)throw Error("This library only supports node.js and modern browsers.");window.Dropbox=t}t.atob=c,t.btoa=m,t.hmac=y,t.sha1=v,t.encodeKey=S}).call(this);
\ No newline at end of file
diff --git a/lib/client/storage/dropbox/package.json b/lib/client/storage/dropbox/package.json
deleted file mode 100644
index 553f5fa7..00000000
--- a/lib/client/storage/dropbox/package.json
+++ /dev/null
@@ -1,48 +0,0 @@
-{
- "name": "dropbox",
- "version": "0.8.1",
- "description": "Client library for the Dropbox API",
- "keywords": ["dropbox", "filesystem", "storage"],
- "homepage": "http://github.com/dropbox/dropbox-js",
- "author": "Victor Costan (http://www.costan.us)",
- "license": "MIT",
- "contributors": [
- "Aakanksha Sarda "
- ],
- "repository": {
- "type": "git",
- "url": "https://github.com/dropbox/dropbox-js.git"
- },
- "engines": {
- "node": ">= 0.6"
- },
- "dependencies": {
- "open": ">= 0.0.2",
- "xmlhttprequest": ">= 1.5.0"
- },
- "devDependencies": {
- "async": ">= 0.1.22",
- "chai": ">= 1.4.0",
- "codo": ">= 1.5.4",
- "coffee-script": ">= 1.4.0",
- "express": ">= 3.0.6",
- "glob": ">= 3.1.14",
- "mocha": ">= 1.7.4",
- "open": "https://github.com/pwnall/node-open/tarball/master",
- "remove": ">= 0.1.5",
- "sinon": ">= 1.5.2",
- "sinon-chai": ">= 2.3.0",
- "uglify-js": ">= 2.2.3"
- },
- "main": "lib/dropbox.js",
- "directories": {
- "doc": "doc",
- "lib": "lib",
- "src": "src",
- "test": "test"
- },
- "scripts": {
- "prepublish": "node_modules/coffee-script/bin/cake build",
- "test": "node_modules/coffee-script/bin/cake test"
- }
-}
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/README.md b/lib/client/storage/dropbox/samples/checkbox.js/README.md
deleted file mode 100644
index dc593a05..00000000
--- a/lib/client/storage/dropbox/samples/checkbox.js/README.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Checkbox, a dropbox.js Sample Application
-
-This application demonstrates the use of the JavaScript client library for the
-Dropbox API to implement a Dropbox-backed To Do list application.
-
-In 70 lines of HTML, and 250 lines of commented CoffeeScript, Checkbox lets you
-store your To Do list in your Dropbox! Just don't expect award winning design
-or usability from a sample application.
-
-See this sample in action
-[here](https://dl-web.dropbox.com/spa/pjlfdak1tmznswp/checkbox.js/public/index.html).
-
-
-## Dropbox Integration
-
-This proof-of-concept application uses the "App folder" Dropbox access level,
-so Dropbox automatically creates a directory for its app data in the users'
-Dropboxes. The data model optimizes for ease of development and debugging.
-Each task is stored as a file whose name is the task’s description. Tasks are
-grouped under two folders, active and done.
-
-The main advantage of this data model is that operations on tasks cleanly map
-to file operations in Dropbox. At initialization time, the application creates
-its two folders, active and done. A task is created by writing an empty string
-to a file in the active folder, marked as completed by moving the file to the
-done folder, and removed by deleting the associated file.
-
-The lists of tasks are obtained by listing the contents of the active and done
-folders. The data model can be easily extended, by storing JSON-encoded
-information, such as deadlines, in the task files.
-
-This sample uses the following `Dropbox.Client` methods:
-
-* authenticate
-* signOff
-* getUserInfo
-* mkdir
-* readdir
-* writeFile
-* move
-* remove
-
-
-## Building
-
-This sample does not require building. Follow the steps below to get your own
-copy of the sample that you can hack on.
-
-1. [Create a powered_by.js app in your Dropbox](https://dl-web.dropbox.com/spa/pjlfdak1tmznswp/powered_by.js/public/index.html).
-1. [Get your own API key](https://www.dropbox.com/developers/apps).
-1. [Encode your API key](https://dl-web.dropbox.com/spa/pjlfdak1tmznswp/api_keys.js/public/index.html).
-1. Copy the source code to `/Apps/Static Web Apps/powered_by.js` in your Dropbox
-
-## Dependencies
-
-The application uses the following JavaScript libraries.
-
-* [dropbox.js](https://github.com/dropbox/dropbox-js) for Dropbox integration
-* [less](http://lesscss.org/) for CSS conciseness
-* [CoffeeScript](http://coffeescript.org/) for JavaScript conciseness
-* [jQuery](http://jquery.com/) for cross-browser compatibitility
-
-The icons used in the application are all from
-[the noun project](http://thenounproject.com/).
-
-The application follows a good practice of packaging its dependencies, and not
-hot-linking them.
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/checkbox.coffee b/lib/client/storage/dropbox/samples/checkbox.js/public/checkbox.coffee
deleted file mode 100644
index 5d68085b..00000000
--- a/lib/client/storage/dropbox/samples/checkbox.js/public/checkbox.coffee
+++ /dev/null
@@ -1,249 +0,0 @@
-# vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab :
-
-# Controller/View for the application.
-class Checkbox
- # @param {Dropbox.Client} dbClient a non-authenticated Dropbox client
- # @param {DOMElement} root the app's main UI element
- constructor: (@dbClient, root) ->
- @$root = $ root
- @taskTemplate = $('#task-template').text()
- @$activeList = $('#active-task-list')
- @$doneList = $('#done-task-list')
- $('#signout-button').click (event) => @onSignOut event
-
- @dbClient.authenticate (error, data) =>
- return @showError(error) if error
- @dbClient.getUserInfo (error, userInfo) =>
- return @showError(error) if error
- $('#user-name').text userInfo.name
- @tasks = new Tasks @, @dbClient
- @tasks.load =>
- @wire()
- @render()
- @$root.removeClass 'hidden'
-
- # Re-renders all the data.
- render: ->
- @$activeList.empty()
- @$doneList.empty()
- @renderTask(task) for task in @tasks.active
- @renderTask(task) for task in @tasks.done
-
- # Renders a task into the
- renderTask: (task) ->
- $list = if task.done then @$doneList else @$activeList
- $list.append @$taskDom(task)
-
- # Renders the list element representing a task.
- #
- # @param {Task} task the task to be rendered
- # @return {jQuery} jQuery wrapper for the DOM representing the task
- $taskDom: (task) ->
- $task = $ @taskTemplate
- $('.task-name', $task).text task.name
- $('.task-remove-button', $task).click (event) => @onRemoveTask event, task
- if task.done
- $('.task-done-button', $task).addClass 'hidden'
- $('.task-active-button', $task).click (event) =>
- @onActiveTask event, task
- else
- $('.task-active-button', $task).addClass 'hidden'
- $('.task-done-button', $task).click (event) => @onDoneTask event, task
- $task
-
- # Called when the user wants to create a new task.
- onNewTask: (event) ->
- event.preventDefault()
- name = $('#new-task-name').val()
- if @tasks.findByName name
- alert "You already have this task on your list!"
- else
- $('#new-task-button').attr 'disabled', 'disabled'
- $('#new-task-name').attr 'disabled', 'disabled'
- task = new Task()
- task.name = name
- @tasks.addTask task, =>
- $('#new-task-name').removeAttr('disabled').val ''
- $('#new-task-button').removeAttr 'disabled'
- @renderTask task
-
- # Called when the user wants to mark a task as done.
- onDoneTask: (event, task) ->
- $task = @$taskElement event.target
- $('button', $task).attr 'disabled', 'disabled'
- @tasks.setTaskDone task, true, =>
- $task.remove()
- @renderTask task
-
- # Called when the user wants to mark a task as active.
- onActiveTask: (event, task) ->
- $task = @$taskElement event.target
- $('button', $task).attr 'disabled', 'disabled'
- @tasks.setTaskDone task, false, =>
- $task.remove()
- @renderTask task
-
- # Called when the user wants to permanently remove a task.
- onRemoveTask: (event, task) ->
- $task = @$taskElement event.target
- $('button', $task).attr 'disabled', 'disabled'
- @tasks.removeTask task, ->
- $task.remove()
-
- # Called when the user wants to sign out of the application.
- onSignOut: (event, task) ->
- @dbClient.signOut (error) =>
- return @showError(error) if error
- window.location.reload()
-
- # Finds the DOM element representing a task.
- #
- # @param {DOMElement} element any element inside the task element
- # @return {jQuery} a jQuery wrapper around the DOM element
- # representing a task
- $taskElement: (element) ->
- $(element).closest 'li.task'
-
- # Sets up listeners for the relevant DOM events.
- wire: ->
- $('#new-task-form').submit (event) => @onNewTask event
-
- # Updates the UI to show that an error has occurred.
- showError: (error) ->
- $('#error-notice').removeClass 'hidden'
- console.log error if window.console
-
-# Model that wraps all a user's tasks.
-class Tasks
- # @param {Checkbox} controller the application controller
- constructor: (@controller) ->
- @dbClient = @controller.dbClient
- [@active, @done] = [[], []]
-
- # Reads all the from a user's Dropbox.
- #
- # @param {function()} done called when all the tasks are read from the user's
- # Dropbox, and the active and done properties are set
- load: (done) ->
- # We read the done tasks and the active tasks in parallel. The variables
- # below tell us when we're done with both.
- readActive = readDone = false
-
- @dbClient.mkdir '/active', (error, stat) =>
- # Issued mkdir so we always have a directory to read from.
- # In most cases, this will fail, so don't bother checking for errors.
- @dbClient.readdir '/active', (error, entries, dir_stat, entry_stats) =>
- return @showError(error) if error
- @active = ((new Task()).fromStat(stat) for stat in entry_stats)
- readActive = true
- done() if readActive and readDone
- @dbClient.mkdir '/done', (error, stat) =>
- @dbClient.readdir '/done', (error, entries, dir_stat, entry_stats) =>
- return @showError(error) if error
- @done = ((new Task()).fromStat(stat) for stat in entry_stats)
- readDone = true
- done() if readActive and readDone
- @
-
- # Adds a new task to the user's set of tasks.
- #
- # @param {Task} task the task to be added
- # @param {function()} done called when the task is saved to the user's
- # Dropbox
- addTask: (task, done) ->
- task.cleanupName()
- @dbClient.writeFile task.path(), '', (error, stat) =>
- return @showError(error) if error
- @addTaskToModel task
- done()
-
- # Returns a task with the given name, if it exists.
- #
- # @param {String} name the name to search for
- # @return {?Task} task the task with the given name, or null if no such task
- # exists
- findByName: (name) ->
- for tasks in [@active, @done]
- for task in tasks
- return task if task.name is name
- null
-
- # Removes a task from the list of tasks.
- #
- # @param {Task} task the task to be removed
- # @param {function()} done called when the task is removed from the user's
- # Dropbox
- removeTask: (task, done) ->
- @dbClient.remove task.path(), (error, stat) =>
- return @showError(error) if error
- @removeTaskFromModel task
- done()
-
- # Marks a active task as done, or a done task as active.
- #
- # @param {Task} the task to be changed
- setTaskDone: (task, newDoneValue, done) ->
- [oldDoneValue, task.done] = [task.done, newDoneValue]
- newPath = task.path()
- task.done = oldDoneValue
-
- @dbClient.move task.path(), newPath, (error, stat) =>
- return @showError(error) if error
- @removeTaskFromModel task
- task.done = newDoneValue
- @addTaskToModel task
- done()
-
- # Adds a task to the in-memory model. Should not be called directly.
- addTaskToModel: (task) ->
- @taskArray(task).push task
-
- # Remove a task from the in-memory model. Should not be called directly.
- removeTaskFromModel: (task) ->
- taskArray = @taskArray task
- for _task, index in taskArray
- if _task is task
- taskArray.splice index, 1
- break
-
- # @param {Task} the task whose containing array should be returned
- # @return {Array} the array that should contain the given task
- taskArray: (task) ->
- if task.done then @done else @active
-
- # Updates the UI to show that an error has occurred.
- showError: (error) ->
- @controller.showError error
-
-# Model for a single user task.
-class Task
- # Creates a task with default values.
- constructor: ->
- @name = null
- @done = false
-
- # Reads data about a task from the stat of is file in a user's Dropbox.
- #
- # @param {Dropbox.Stat} entry the directory entry representing the task
- fromStat: (entry) ->
- @name = entry.name
- @done = entry.path.split('/', 3)[1] is 'done'
- @
-
- # Cleans up the task name so that it's valid Dropbox file name.
- cleanupName: (name) ->
- # English-only hack that removes slashes from the task name.
- @name = @name.replace(/\ \/\ /g, ' or ').replace(/\//g, ' or ')
- @
-
- # Path to the file representing the task in the user's Dropbox.
- # @return {String} fully-qualified path
- path: ->
- (if @done then '/done/' else '/active/') + @name
-
-# Start up the code when the DOM is fully loaded.
-$ ->
- client = new Dropbox.Client(
- key: '/Fahm0FLioA|ZxKxLxy5irfHqsCRs+Ceo8bwJjVPu8xZlfjgGzeCjQ', sandbox: true)
- client.authDriver new Dropbox.Drivers.Redirect(rememberUser: true)
- new Checkbox client, '#app-ui'
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/checkbox.less b/lib/client/storage/dropbox/samples/checkbox.js/public/checkbox.less
deleted file mode 100644
index 8f562f97..00000000
--- a/lib/client/storage/dropbox/samples/checkbox.js/public/checkbox.less
+++ /dev/null
@@ -1,298 +0,0 @@
-// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab :
-
-.linear-gradient (@top: #ffffff, @bottom: #000000) {
- background: @top;
- filter: ~"progid:DXImageTransform.Microsoft.gradient(startColorstr='@{top}', endColorstr='@{bottom}')";
- background: -webkit-linear-gradient(top, @top 0%, @bottom 100%);
- background: -moz-linear-gradient(top, @top 0%, @bottom 100%);
- background: -ms-linear-gradient(top, @top 0%, @bottom 100%);
- background: linear-gradient(to bottom, @top 0%, @bottom 100%);
-}
-.border-radius (@radius) {
- -webkit-border-radius: @radius;
- -moz-border-radius: @radius;
- border-radius: @radius;
-}
-.box-sizing (@sizing) {
- -webkit-box-sizing: @sizing;
- -moz-box-sizing: @sizing;
- box-sizing: @sizing;
-}
-.box-shadow (@offset-x, @offset-y, @blur, @spread, @color) {
- -webkit-box-shadow: @offset-x @offset-y @blur @spread @color;
- -moz-box-shadow: @offset-x @offset-y @blur @spread @color;
- box-shadow: @offset-x @offset-y @blur @spread @color;
-}
-
-.font-verdana () {
- font-family: Verdana, Geneva, sans-serif;
-}
-.font-helvetica () {
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-}
-
-html, body {
- .linear-gradient (#ffffff, #f2f7fc);
- background-attachment: fixed;
-
- height: 100%;
- margin: 0;
- padding: 0;
-}
-
-#error-notice {
- display: block;
- position: absolute;
- width: 100%;
- .box-sizing(border-box);
-
- color: hsl(0, 75%, 33%);
- font-size: 12pt;
- .font-verdana();
- line-height: 1.5;
- text-align: center;
- margin: 0;
- padding: 0.2em 0 0.1em 0;
-
- #error-refresh-button {
- margin: 0 1em;
- padding: 0 1em;
- }
-
- &.hidden {
- display: none;
- }
-}
-
-#app-ui {
- width: 700px;
- margin: 0 auto;
-
- h1 {
- .font-verdana();
- font-size: 24px;
- font-weight: 300;
- line-height: 2;
- text-transform: lowercase;
- color: #bfbfbf;
- margin: 0;
- padding: 2em 0 0.25em 0;
-
- small {
- .font-verdana();
- font-size: 10px;
- font-weight: 400;
- text-transform: uppercase;
- color: #888888;
-
- a {
- font-style: normal;
- color: #649cd1;
- text-decoration: none;
- }
- }
- }
-
- #notebook-page {
- border: 1px solid #aaaaaa;
- -webkit-border-top-left-radius: 8px;
- -webkit-border-top-right-radius: 8px;
- -moz-border-radius-topleft: 8px;
- -moz-border-radius-topright: 8px;
- border-top-left-radius: 8px;
- border-top-right-radius: 8px;
-
- .box-shadow(0, 0, 10px, 5px, rgba(0, 0, 0, 0.05));
-
- background-color: #fffddb;
- margin: 0;
- padding: 24px 0 60px 0;
- }
- #notebook-page, .task {
- background-image: -webkit-linear-gradient(top, #f3aaaa 0%, #f3aaaa 100%),
- -webkit-linear-gradient(top, #f3aaaa 0%, #f3aaaa 100%);
- background-image: -moz-linear-gradient(top, #f3aaaa 0%, #f3aaaa 100%),
- -moz-linear-gradient(top, #f3aaaa 0%, #f3aaaa 100%);
- background-image: -ms-linear-gradient(top, #f3aaaa 0%, #f3aaaa 100%),
- -ms-linear-gradient(top, #f3aaaa 0%, #f3aaaa 100%);
- background-image: linear-gradient(to bottom, #f3aaaa 0%, #f3aaaa 100%),
- linear-gradient(to bottom, #f3aaaa 0%, #f3aaaa 100%);
- background-position: 70px 0px, 76px 0px;
- background-size: 1px 100%, 1px 100%;
- background-repeat: no-repeat, no-repeat;
- }
-
- #user-info {
- margin: 0;
- padding: 0 16px 8px 88px;
-
- color: #555555;
- .font-helvetica();
- font-size: 16px;
- line-height: 32px;
- font-weight: 200;
- text-align: right;
-
- #user-name {
- display: inline-block;
- padding: 0 0 0 8px;
- }
-
- #signout-button {
- visibility: hidden;
- }
- &:hover {
- color: #000000;
-
- #signout-button {
- visibility: visible;
- }
- }
- }
-
- #new-task-form, h2, .task, .empty-task {
- border-bottom: 1px solid #c9e4f2;
- .font-helvetica();
- font-size: 18px;
- font-weight: 300;
- line-height: 36px;
- color: #555555;
-
- margin: 0;
- padding: 6px 10px 6px 88px;
- }
-
- #new-task-form {
- margin: 0;
-
- #new-task-name {
- font-family: inherit;
- font-size: inherit;
-
- background: rgb(255, 254, 236);
- }
- .task-actions {
- visibility: visible;
- }
- }
- h2 {
- font-size: 20px;
- font-weight: 400;
- color: #000000;
- }
- .task-list {
- list-style: none;
- margin: 0;
- padding: 0;
- }
- .task {
- span.task-name {
- display: inline-block;
- }
- &:hover {
- background-color: #fffcaf;
- .task-actions {
- visibility: visible;
- }
- }
- }
- .task-name {
- width: 373px;
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
- vertical-align: middle;
- }
- .task-actions {
- width: 220px;
- display: inline-block;
- vertical-align: middle;
- line-height: 1;
- visibility: hidden;
- }
-}
-
-input[type=text] {
- display: inline-block;
- margin: 0;
- padding: 0 0.25em 0 0.25em;
- line-height: 30px;
-
- .box-sizing(border-box);
- position: relative;
- left: -4px;
- height: 32px;
-
- border: 1px solid #d2cd70;
- .border-radius(4px);
- -webkit-box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.1);
- -moz-box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.1);
- box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.1);
-}
-
-button {
- display: inline-block;
- vertical-align: middle;
- height: 32px;
- margin: 0;
- padding: 0;
- min-width: 104px;
- cursor: pointer;
-
- border: 1px solid;
- .border-radius(4px);
- .box-shadow(0, 2px, -1px, 0, rgba(0, 0, 0, 0.1));
-
- .font-verdana();
- font-size: 13px;
- font-weight: 400;
- text-align: center;
- text-transform: uppercase;
-
- color: #ffffff;
- text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
- filter: dropshadow(color=rgba(0, 0, 0, 0.5), offx=1, offy=1);
-
- &:hover {
- -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
- inset 0 0 4px rgba(255, 255, 255, 0.6);
- -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
- inset 0 0 4px rgba(255, 255, 255, 0.6);
- box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
- inset 0 0 4px rgba(255, 255, 255, 0.6);
- }
- &:focus {
- .box-shadow(0, 0, 3px, 1px, #33a0e8);
- }
- &:active {
- -webkit-box-shadow: none;
- -moz-box-shadow: none;
- box-shadow: none;
- }
-
- img {
- display: inline-block;
- vertical-align: -4px;
- }
-
- &.task-done-button, new-task-button, &.task-active-button {
- border-color: #448c42;
- .linear-gradient(#8ed66b, #58ba6d);
-
- &:active {
- .linear-gradient(#58ba6d, #8ed66b);
- }
- }
-
- &.task-remove-button, error-refresh-button, signout-button {
- border-color: #a73030;
- .linear-gradient(#f67f73, #bb5757);
- &:active {
- .linear-gradient(#bb5757, #f67f73);
- }
- }
-}
-
-.hidden {
- display: none;
-}
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/images/add.png b/lib/client/storage/dropbox/samples/checkbox.js/public/images/add.png
deleted file mode 100644
index 4566ad47..00000000
Binary files a/lib/client/storage/dropbox/samples/checkbox.js/public/images/add.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/images/done.png b/lib/client/storage/dropbox/samples/checkbox.js/public/images/done.png
deleted file mode 100644
index 69e0921b..00000000
Binary files a/lib/client/storage/dropbox/samples/checkbox.js/public/images/done.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/images/icon.svg b/lib/client/storage/dropbox/samples/checkbox.js/public/images/icon.svg
deleted file mode 100644
index 46b4e9bd..00000000
--- a/lib/client/storage/dropbox/samples/checkbox.js/public/images/icon.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/images/icon128.png b/lib/client/storage/dropbox/samples/checkbox.js/public/images/icon128.png
deleted file mode 100644
index f62d073f..00000000
Binary files a/lib/client/storage/dropbox/samples/checkbox.js/public/images/icon128.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/images/icon16.png b/lib/client/storage/dropbox/samples/checkbox.js/public/images/icon16.png
deleted file mode 100644
index 09c902f4..00000000
Binary files a/lib/client/storage/dropbox/samples/checkbox.js/public/images/icon16.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/images/icon64.png b/lib/client/storage/dropbox/samples/checkbox.js/public/images/icon64.png
deleted file mode 100644
index f6f2c837..00000000
Binary files a/lib/client/storage/dropbox/samples/checkbox.js/public/images/icon64.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/images/not_done.png b/lib/client/storage/dropbox/samples/checkbox.js/public/images/not_done.png
deleted file mode 100644
index 83c7ebdd..00000000
Binary files a/lib/client/storage/dropbox/samples/checkbox.js/public/images/not_done.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/images/remove.png b/lib/client/storage/dropbox/samples/checkbox.js/public/images/remove.png
deleted file mode 100644
index 908b0d36..00000000
Binary files a/lib/client/storage/dropbox/samples/checkbox.js/public/images/remove.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/index.html b/lib/client/storage/dropbox/samples/checkbox.js/public/index.html
deleted file mode 100644
index 4f86ceea..00000000
--- a/lib/client/storage/dropbox/samples/checkbox.js/public/index.html
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
-
- Checkbox - dropbox.js Sample Application
-
-
-
-
-
-
-
-
-
-
-
-
- checkbox
- powered by
- dropbox
-
-
-
-
-
- Sign out
-
-
-
-
Active
-
-
-
-
Done
-
-
-
-
-
-
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/lib/coffee-script.js b/lib/client/storage/dropbox/samples/checkbox.js/public/lib/coffee-script.js
deleted file mode 100644
index 66c387f8..00000000
--- a/lib/client/storage/dropbox/samples/checkbox.js/public/lib/coffee-script.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/**
- * CoffeeScript Compiler v1.4.0
- * http://coffeescript.org
- *
- * Copyright 2011, Jeremy Ashkenas
- * Released under the MIT License
- */
-(function(root){var CoffeeScript=function(){function require(a){return require[a]}return require["./helpers"]=new function(){var a=this;((function(){var b,c,d;a.starts=function(a,b,c){return b===a.substr(c,b.length)},a.ends=function(a,b,c){var d;return d=b.length,b===a.substr(a.length-d-(c||0),d)},a.compact=function(a){var b,c,d,e;e=[];for(c=0,d=a.length;c=0)f+=1;else if(j=g[0],t.call(d,j)>=0)f-=1;a+=1}return a-1},a.prototype.removeLeadingNewlines=function(){var a,b,c,d,e;e=this.tokens;for(a=c=0,d=e.length;c=0)?(d.splice(b,1),0):1})},a.prototype.closeOpenCalls=function(){var a,b;return b=function(a,b){var c;return(c=a[0])===")"||c==="CALL_END"||a[0]==="OUTDENT"&&this.tag(b-1)===")"},a=function(a,b){return this.tokens[a[0]==="OUTDENT"?b-1:b][0]="CALL_END"},this.scanTokens(function(c,d){return c[0]==="CALL_START"&&this.detectEnd(d+1,b,a),1})},a.prototype.closeOpenIndexes=function(){var a,b;return b=function(a,b){var c;return(c=a[0])==="]"||c==="INDEX_END"},a=function(a,b){return a[0]="INDEX_END"},this.scanTokens(function(c,d){return c[0]==="INDEX_START"&&this.detectEnd(d+1,b,a),1})},a.prototype.addImplicitBraces=function(){var a,b,c,f,g,i,j,k;return f=[],g=null,k=null,c=!0,i=0,j=0,b=function(a,b){var d,e,f,g,i,m;return i=this.tokens.slice(b+1,+(b+3)+1||9e9),d=i[0],g=i[1],f=i[2],"HERECOMMENT"===(d!=null?d[0]:void 0)?!1:(e=a[0],t.call(l,e)>=0&&(c=!1),(e==="TERMINATOR"||e==="OUTDENT"||t.call(h,e)>=0&&c&&b-j!==1)&&(!k&&this.tag(b-1)!==","||(g!=null?g[0]:void 0)!==":"&&((d!=null?d[0]:void 0)!=="@"||(f!=null?f[0]:void 0)!==":"))||e===","&&d&&(m=d[0])!=="IDENTIFIER"&&m!=="NUMBER"&&m!=="STRING"&&m!=="@"&&m!=="TERMINATOR"&&m!=="OUTDENT")},a=function(a,b){var c;return c=this.generate("}","}",a[2]),this.tokens.splice(b,0,c)},this.scanTokens(function(h,i,m){var n,o,p,q,r,s,u,v;if(u=q=h[0],t.call(e,u)>=0)return f.push([q==="INDENT"&&this.tag(i-1)==="{"?"{":q,i]),1;if(t.call(d,q)>=0)return g=f.pop(),1;if(q!==":"||(n=this.tag(i-2))!==":"&&((v=f[f.length-1])!=null?v[0]:void 0)==="{")return 1;c=!0,j=i+1,f.push(["{"]),o=n==="@"?i-2:i-1;while(this.tag(o-2)==="HERECOMMENT")o-=2;return p=this.tag(o-1),k=!p||t.call(l,p)>=0,s=new String("{"),s.generated=!0,r=this.generate("{",s,h[2]),m.splice(o,0,r),this.detectEnd(i+2,b,a),2})},a.prototype.addImplicitParentheses=function(){var a,b,c,d,e;return c=e=d=!1,b=function(a,b){var c,g,i,j;g=a[0];if(!e&&a.fromThen)return!0;if(g==="IF"||g==="ELSE"||g==="CATCH"||g==="->"||g==="=>"||g==="CLASS")e=!0;if(g==="IF"||g==="ELSE"||g==="SWITCH"||g==="TRY"||g==="=")d=!0;return g!=="."&&g!=="?."&&g!=="::"||this.tag(b-1)!=="OUTDENT"?!a.generated&&this.tag(b-1)!==","&&(t.call(h,g)>=0||g==="INDENT"&&!d)&&(g!=="INDENT"||(i=this.tag(b-2))!=="CLASS"&&i!=="EXTENDS"&&(j=this.tag(b-1),t.call(f,j)<0)&&(!(c=this.tokens[b+1])||!c.generated||c[0]!=="{")):!0},a=function(a,b){return this.tokens.splice(b,0,this.generate("CALL_END",")",a[2]))},this.scanTokens(function(f,h,k){var m,n,o,p,q,r,s,u;q=f[0];if(q==="CLASS"||q==="IF"||q==="FOR"||q==="WHILE")c=!0;return r=k.slice(h-1,+(h+1)+1||9e9),p=r[0],n=r[1],o=r[2],m=!c&&q==="INDENT"&&o&&o.generated&&o[0]==="{"&&p&&(s=p[0],t.call(i,s)>=0),e=!1,d=!1,t.call(l,q)>=0&&(c=!1),p&&!p.spaced&&q==="?"&&(f.call=!0),f.fromThen?1:m||(p!=null?p.spaced:void 0)&&(p.call||(u=p[0],t.call(i,u)>=0))&&(t.call(g,q)>=0||!f.spaced&&!f.newLine&&t.call(j,q)>=0)?(k.splice(h,0,this.generate("CALL_START","(",f[2])),this.detectEnd(h+1,b,a),p[0]==="?"&&(p[0]="FUNC_EXIST"),2):1})},a.prototype.addImplicitIndentation=function(){var a,b,c,d,e;return e=c=d=null,b=function(a,b){var c;return a[1]!==";"&&(c=a[0],t.call(m,c)>=0)&&(a[0]!=="ELSE"||e==="IF"||e==="THEN")},a=function(a,b){return this.tokens.splice(this.tag(b-1)===","?b-1:b,0,d)},this.scanTokens(function(f,g,h){var i,j,k;return i=f[0],i==="TERMINATOR"&&this.tag(g+1)==="THEN"?(h.splice(g,1),0):i==="ELSE"&&this.tag(g-1)!=="OUTDENT"?(h.splice.apply(h,[g,0].concat(u.call(this.indentation(f)))),2):i!=="CATCH"||(j=this.tag(g+2))!=="OUTDENT"&&j!=="TERMINATOR"&&j!=="FINALLY"?t.call(n,i)>=0&&this.tag(g+1)!=="INDENT"&&(i!=="ELSE"||this.tag(g+1)!=="IF")?(e=i,k=this.indentation(f,!0),c=k[0],d=k[1],e==="THEN"&&(c.fromThen=!0),h.splice(g+1,0,c),this.detectEnd(g+2,b,a),i==="THEN"&&h.splice(g,1),1):1:(h.splice.apply(h,[g+2,0].concat(u.call(this.indentation(f)))),4)})},a.prototype.tagPostfixConditionals=function(){var a,b,c;return c=null,b=function(a,b){var c;return(c=a[0])==="TERMINATOR"||c==="INDENT"},a=function(a,b){if(a[0]!=="INDENT"||a.generated&&!a.fromThen)return c[0]="POST_"+c[0]},this.scanTokens(function(d,e){return d[0]!=="IF"?1:(c=d,this.detectEnd(e+1,b,a),1)})},a.prototype.indentation=function(a,b){var c,d;return b==null&&(b=!1),c=["INDENT",2,a[2]],d=["OUTDENT",2,a[2]],b&&(c.generated=d.generated=!0),[c,d]},a.prototype.generate=function(a,b,c){var d;return d=[a,b,c],d.generated=!0,d},a.prototype.tag=function(a){var b;return(b=this.tokens[a])!=null?b[0]:void 0},a}(),b=[["(",")"],["[","]"],["{","}"],["INDENT","OUTDENT"],["CALL_START","CALL_END"],["PARAM_START","PARAM_END"],["INDEX_START","INDEX_END"]],a.INVERSES=k={},e=[],d=[];for(q=0,r=b.length;q","=>","[","(","{","--","++"],j=["+","-"],f=["->","=>","{","[",","],h=["POST_IF","FOR","WHILE","UNTIL","WHEN","BY","LOOP","TERMINATOR"],n=["ELSE","->","=>","TRY","FINALLY","THEN"],m=["TERMINATOR","CATCH","FINALLY","ELSE","OUTDENT","LEADING_WHEN"],l=["TERMINATOR","INDENT","OUTDENT"]})).call(this)},require["./lexer"]=new function(){var a=this;((function(){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X=[].indexOf||function(a){for(var b=0,c=this.length;b=0||X.call(g,c)>=0)&&(j=c.toUpperCase(),j==="WHEN"&&(l=this.tag(),X.call(v,l)>=0)?j="LEADING_WHEN":j==="FOR"?this.seenFor=!0:j==="UNLESS"?j="IF":X.call(O,j)>=0?j="UNARY":X.call(H,j)>=0&&(j!=="INSTANCEOF"&&this.seenFor?(j="FOR"+j,this.seenFor=!1):(j="RELATION",this.value()==="!"&&(this.tokens.pop(),c="!"+c)))),X.call(t,c)>=0&&(b?(j="IDENTIFIER",c=new String(c),c.reserved=!0):X.call(I,c)>=0&&this.error('reserved word "'+c+'"')),b||(X.call(e,c)>=0&&(c=f[c]),j=function(){switch(c){case"!":return"UNARY";case"==":case"!=":return"COMPARE";case"&&":case"||":return"LOGIC";case"true":case"false":return"BOOL";case"break":case"continue":return"STATEMENT";default:return j}}()),this.token(j,c),a&&this.token(":",":"),d.length)):0},a.prototype.numberToken=function(){var a,b,c,d,e;if(!(c=E.exec(this.chunk)))return 0;d=c[0],/^0[BOX]/.test(d)?this.error("radix prefix '"+d+"' must be lowercase"):/E/.test(d)&&!/^0x/.test(d)?this.error("exponential notation '"+d+"' must be indicated with a lowercase 'e'"):/^0\d*[89]/.test(d)?this.error("decimal literal '"+d+"' must not be prefixed with '0'"):/^0\d+/.test(d)&&this.error("octal literal '"+d+"' must be prefixed with '0o'"),b=d.length;if(e=/^0o([0-7]+)/.exec(d))d="0x"+parseInt(e[1],8).toString(16);if(a=/^0b([01]+)/.exec(d))d="0x"+parseInt(a[1],2).toString(16);return this.token("NUMBER",d),b},a.prototype.stringToken=function(){var a,b,c;switch(this.chunk.charAt(0)){case"'":if(!(a=L.exec(this.chunk)))return 0;this.token("STRING",(c=a[0]).replace(A,"\\\n"));break;case'"':if(!(c=this.balancedString(this.chunk,'"')))return 0;0=0)?0:(c=G.exec(this.chunk))?(g=c,c=g[0],e=g[1],a=g[2],e.slice(0,2)==="/*"&&this.error("regular expressions cannot begin with `*`"),e==="//"&&(e="/(?:)/"),this.token("REGEX",""+e+a),c.length):0)},a.prototype.heregexToken=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n;d=a[0],b=a[1],c=a[2];if(0>b.indexOf("#{"))return e=b.replace(o,"").replace(/\//g,"\\/"),e.match(/^\*/)&&this.error("regular expressions cannot begin with `*`"),this.token("REGEX","/"+(e||"(?:)")+"/"+c),d.length;this.token("IDENTIFIER","RegExp"),this.tokens.push(["CALL_START","("]),g=[],k=this.interpolateString(b,{regex:!0});for(i=0,j=k.length;ithis.indent){if(d)return this.indebt=e-this.indent,this.suppressNewlines(),b.length;a=e-this.indent+this.outdebt,this.token("INDENT",a),this.indents.push(a),this.ends.push("OUTDENT"),this.outdebt=this.indebt=0}else this.indebt=0,this.outdentToken(this.indent-e,d);return this.indent=e,b.length},a.prototype.outdentToken=function(a,b){var c,d;while(a>0)d=this.indents.length-1,this.indents[d]===void 0?a=0:this.indents[d]===this.outdebt?(a-=this.outdebt,this.outdebt=0):this.indents[d]=0)&&this.error('reserved word "'+this.value()+"\" can't be assigned");if((h=b[1])==="||"||h==="&&")return b[0]="COMPOUND_ASSIGN",b[1]+="=",f.length}if(f===";")this.seenFor=!1,e="TERMINATOR";else if(X.call(z,f)>=0)e="MATH";else if(X.call(i,f)>=0)e="COMPARE";else if(X.call(j,f)>=0)e="COMPOUND_ASSIGN";else if(X.call(O,f)>=0)e="UNARY";else if(X.call(K,f)>=0)e="SHIFT";else if(X.call(x,f)>=0||f==="?"&&(b!=null?b.spaced:void 0))e="LOGIC";else if(b&&!b.spaced)if(f==="("&&(k=b[0],X.call(c,k)>=0))b[0]==="?"&&(b[0]="FUNC_EXIST"),e="CALL_START";else if(f==="["&&(l=b[0],X.call(q,l)>=0)){e="INDEX_START";switch(b[0]){case"?":b[0]="INDEX_SOAK"}}switch(f){case"(":case"{":case"[":this.ends.push(r[f]);break;case")":case"}":case"]":this.pair(f)}return this.token(e,f),f.length},a.prototype.sanitizeHeredoc=function(a,b){var c,d,e,f,g;e=b.indent,d=b.herecomment;if(d){l.test(a)&&this.error('block comment cannot contain "*/", starting');if(a.indexOf("\n")<=0)return a}else while(f=m.exec(a)){c=f[1];if(e===null||0<(g=c.length)&&gj;d=1<=j?++i:--i){if(c){--c;continue}switch(e=a.charAt(d)){case"\\":++c;continue;case b:h.pop();if(!h.length)return a.slice(0,+d+1||9e9);b=h[h.length-1];continue}b!=="}"||e!=='"'&&e!=="'"?b==="}"&&e==="/"&&(f=n.exec(a.slice(d))||G.exec(a.slice(d)))?c+=f[0].length-1:b==="}"&&e==="{"?h.push(b="}"):b==='"'&&g==="#"&&e==="{"&&h.push(b="}"):h.push(b=e),g=e}return this.error("missing "+h.pop()+", starting")},a.prototype.interpolateString=function(b,c){var d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;c==null&&(c={}),e=c.heredoc,m=c.regex,o=[],l=0,f=-1;while(j=b.charAt(f+=1)){if(j==="\\"){f+=1;continue}if(j!=="#"||b.charAt(f+1)!=="{"||!(d=this.balancedString(b.slice(f+1),"}")))continue;l1&&(k.unshift(["(","(",this.line]),k.push([")",")",this.line])),o.push(["TOKENS",k])}f+=d.length,l=f+1}f>l&&l1)&&this.token("(","(");for(f=q=0,r=o.length;q|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/,P=/^[^\n\S]+/,h=/^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/,d=/^[-=]>/,B=/^(?:\n[^\n\S]*)+/,L=/^'[^\\']*(?:\\.[^\\']*)*'/,s=/^`[^\\`]*(?:\\.[^\\`]*)*`/,G=/^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/,n=/^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/,o=/\s+(?:#.*)?/g,A=/\n/g,m=/\n+([^\n\S]*)/g,l=/\*\//,w=/^\s*(?:,|\??\.(?![.\d])|::)/,N=/\s+$/,j=["-=","+=","/=","*=","%=","||=","&&=","?=","<<=",">>=",">>>=","&=","^=","|="],O=["!","~","NEW","TYPEOF","DELETE","DO"],x=["&&","||","&","|","^"],K=["<<",">>",">>>"],i=["==","!=","<",">","<=",">="],z=["*","/","%"],H=["IN","OF","INSTANCEOF"],b=["TRUE","FALSE"],C=["NUMBER","REGEX","BOOL","NULL","UNDEFINED","++","--","]"],D=C.concat(")","}","THIS","IDENTIFIER","STRING"),c=["IDENTIFIER","STRING","REGEX",")","]","}","?","::","@","THIS","SUPER"],q=c.concat("NUMBER","BOOL","NULL","UNDEFINED"),v=["INDENT","OUTDENT","TERMINATOR"]})).call(this)},require["./parser"]=new function(){var a=this,b=function(){var a={trace:function(){},yy:{},symbols_:{error:2,Root:3,Body:4,Block:5,TERMINATOR:6,Line:7,Expression:8,Statement:9,Return:10,Comment:11,STATEMENT:12,Value:13,Invocation:14,Code:15,Operation:16,Assign:17,If:18,Try:19,While:20,For:21,Switch:22,Class:23,Throw:24,INDENT:25,OUTDENT:26,Identifier:27,IDENTIFIER:28,AlphaNumeric:29,NUMBER:30,STRING:31,Literal:32,JS:33,REGEX:34,DEBUGGER:35,UNDEFINED:36,NULL:37,BOOL:38,Assignable:39,"=":40,AssignObj:41,ObjAssignable:42,":":43,ThisProperty:44,RETURN:45,HERECOMMENT:46,PARAM_START:47,ParamList:48,PARAM_END:49,FuncGlyph:50,"->":51,"=>":52,OptComma:53,",":54,Param:55,ParamVar:56,"...":57,Array:58,Object:59,Splat:60,SimpleAssignable:61,Accessor:62,Parenthetical:63,Range:64,This:65,".":66,"?.":67,"::":68,Index:69,INDEX_START:70,IndexValue:71,INDEX_END:72,INDEX_SOAK:73,Slice:74,"{":75,AssignList:76,"}":77,CLASS:78,EXTENDS:79,OptFuncExist:80,Arguments:81,SUPER:82,FUNC_EXIST:83,CALL_START:84,CALL_END:85,ArgList:86,THIS:87,"@":88,"[":89,"]":90,RangeDots:91,"..":92,Arg:93,SimpleArgs:94,TRY:95,Catch:96,FINALLY:97,CATCH:98,THROW:99,"(":100,")":101,WhileSource:102,WHILE:103,WHEN:104,UNTIL:105,Loop:106,LOOP:107,ForBody:108,FOR:109,ForStart:110,ForSource:111,ForVariables:112,OWN:113,ForValue:114,FORIN:115,FOROF:116,BY:117,SWITCH:118,Whens:119,ELSE:120,When:121,LEADING_WHEN:122,IfBlock:123,IF:124,POST_IF:125,UNARY:126,"-":127,"+":128,"--":129,"++":130,"?":131,MATH:132,SHIFT:133,COMPARE:134,LOGIC:135,RELATION:136,COMPOUND_ASSIGN:137,$accept:0,$end:1},terminals_:{2:"error",6:"TERMINATOR",12:"STATEMENT",25:"INDENT",26:"OUTDENT",28:"IDENTIFIER",30:"NUMBER",31:"STRING",33:"JS",34:"REGEX",35:"DEBUGGER",36:"UNDEFINED",37:"NULL",38:"BOOL",40:"=",43:":",45:"RETURN",46:"HERECOMMENT",47:"PARAM_START",49:"PARAM_END",51:"->",52:"=>",54:",",57:"...",66:".",67:"?.",68:"::",70:"INDEX_START",72:"INDEX_END",73:"INDEX_SOAK",75:"{",77:"}",78:"CLASS",79:"EXTENDS",82:"SUPER",83:"FUNC_EXIST",84:"CALL_START",85:"CALL_END",87:"THIS",88:"@",89:"[",90:"]",92:"..",95:"TRY",97:"FINALLY",98:"CATCH",99:"THROW",100:"(",101:")",103:"WHILE",104:"WHEN",105:"UNTIL",107:"LOOP",109:"FOR",113:"OWN",115:"FORIN",116:"FOROF",117:"BY",118:"SWITCH",120:"ELSE",122:"LEADING_WHEN",124:"IF",125:"POST_IF",126:"UNARY",127:"-",128:"+",129:"--",130:"++",131:"?",132:"MATH",133:"SHIFT",134:"COMPARE",135:"LOGIC",136:"RELATION",137:"COMPOUND_ASSIGN"},productions_:[0,[3,0],[3,1],[3,2],[4,1],[4,3],[4,2],[7,1],[7,1],[9,1],[9,1],[9,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[8,1],[5,2],[5,3],[27,1],[29,1],[29,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[32,1],[17,3],[17,4],[17,5],[41,1],[41,3],[41,5],[41,1],[42,1],[42,1],[42,1],[10,2],[10,1],[11,1],[15,5],[15,2],[50,1],[50,1],[53,0],[53,1],[48,0],[48,1],[48,3],[48,4],[48,6],[55,1],[55,2],[55,3],[56,1],[56,1],[56,1],[56,1],[60,2],[61,1],[61,2],[61,2],[61,1],[39,1],[39,1],[39,1],[13,1],[13,1],[13,1],[13,1],[13,1],[62,2],[62,2],[62,2],[62,1],[62,1],[69,3],[69,2],[71,1],[71,1],[59,4],[76,0],[76,1],[76,3],[76,4],[76,6],[23,1],[23,2],[23,3],[23,4],[23,2],[23,3],[23,4],[23,5],[14,3],[14,3],[14,1],[14,2],[80,0],[80,1],[81,2],[81,4],[65,1],[65,1],[44,2],[58,2],[58,4],[91,1],[91,1],[64,5],[74,3],[74,2],[74,2],[74,1],[86,1],[86,3],[86,4],[86,4],[86,6],[93,1],[93,1],[94,1],[94,3],[19,2],[19,3],[19,4],[19,5],[96,3],[24,2],[63,3],[63,5],[102,2],[102,4],[102,2],[102,4],[20,2],[20,2],[20,2],[20,1],[106,2],[106,2],[21,2],[21,2],[21,2],[108,2],[108,2],[110,2],[110,3],[114,1],[114,1],[114,1],[114,1],[112,1],[112,3],[111,2],[111,2],[111,4],[111,4],[111,4],[111,6],[111,6],[22,5],[22,7],[22,4],[22,6],[119,1],[119,2],[121,3],[121,4],[123,3],[123,5],[18,1],[18,3],[18,3],[18,3],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,2],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,3],[16,5],[16,3]],performAction:function(b,c,d,e,f,g,h){var i=g.length-1;switch(f){case 1:return this.$=new e.Block;case 2:return this.$=g[i];case 3:return this.$=g[i-1];case 4:this.$=e.Block.wrap([g[i]]);break;case 5:this.$=g[i-2].push(g[i]);break;case 6:this.$=g[i-1];break;case 7:this.$=g[i];break;case 8:this.$=g[i];break;case 9:this.$=g[i];break;case 10:this.$=g[i];break;case 11:this.$=new e.Literal(g[i]);break;case 12:this.$=g[i];break;case 13:this.$=g[i];break;case 14:this.$=g[i];break;case 15:this.$=g[i];break;case 16:this.$=g[i];break;case 17:this.$=g[i];break;case 18:this.$=g[i];break;case 19:this.$=g[i];break;case 20:this.$=g[i];break;case 21:this.$=g[i];break;case 22:this.$=g[i];break;case 23:this.$=g[i];break;case 24:this.$=new e.Block;break;case 25:this.$=g[i-1];break;case 26:this.$=new e.Literal(g[i]);break;case 27:this.$=new e.Literal(g[i]);break;case 28:this.$=new e.Literal(g[i]);break;case 29:this.$=g[i];break;case 30:this.$=new e.Literal(g[i]);break;case 31:this.$=new e.Literal(g[i]);break;case 32:this.$=new e.Literal(g[i]);break;case 33:this.$=new e.Undefined;break;case 34:this.$=new e.Null;break;case 35:this.$=new e.Bool(g[i]);break;case 36:this.$=new e.Assign(g[i-2],g[i]);break;case 37:this.$=new e.Assign(g[i-3],g[i]);break;case 38:this.$=new e.Assign(g[i-4],g[i-1]);break;case 39:this.$=new e.Value(g[i]);break;case 40:this.$=new e.Assign(new e.Value(g[i-2]),g[i],"object");break;case 41:this.$=new e.Assign(new e.Value(g[i-4]),g[i-1],"object");break;case 42:this.$=g[i];break;case 43:this.$=g[i];break;case 44:this.$=g[i];break;case 45:this.$=g[i];break;case 46:this.$=new e.Return(g[i]);break;case 47:this.$=new e.Return;break;case 48:this.$=new e.Comment(g[i]);break;case 49:this.$=new e.Code(g[i-3],g[i],g[i-1]);break;case 50:this.$=new e.Code([],g[i],g[i-1]);break;case 51:this.$="func";break;case 52:this.$="boundfunc";break;case 53:this.$=g[i];break;case 54:this.$=g[i];break;case 55:this.$=[];break;case 56:this.$=[g[i]];break;case 57:this.$=g[i-2].concat(g[i]);break;case 58:this.$=g[i-3].concat(g[i]);break;case 59:this.$=g[i-5].concat(g[i-2]);break;case 60:this.$=new e.Param(g[i]);break;case 61:this.$=new e.Param(g[i-1],null,!0);break;case 62:this.$=new e.Param(g[i-2],g[i]);break;case 63:this.$=g[i];break;case 64:this.$=g[i];break;case 65:this.$=g[i];break;case 66:this.$=g[i];break;case 67:this.$=new e.Splat(g[i-1]);break;case 68:this.$=new e.Value(g[i]);break;case 69:this.$=g[i-1].add(g[i]);break;case 70:this.$=new e.Value(g[i-1],[].concat(g[i]));break;case 71:this.$=g[i];break;case 72:this.$=g[i];break;case 73:this.$=new e.Value(g[i]);break;case 74:this.$=new e.Value(g[i]);break;case 75:this.$=g[i];break;case 76:this.$=new e.Value(g[i]);break;case 77:this.$=new e.Value(g[i]);break;case 78:this.$=new e.Value(g[i]);break;case 79:this.$=g[i];break;case 80:this.$=new e.Access(g[i]);break;case 81:this.$=new e.Access(g[i],"soak");break;case 82:this.$=[new e.Access(new e.Literal("prototype")),new e.Access(g[i])];break;case 83:this.$=new e.Access(new e.Literal("prototype"));break;case 84:this.$=g[i];break;case 85:this.$=g[i-1];break;case 86:this.$=e.extend(g[i],{soak:!0});break;case 87:this.$=new e.Index(g[i]);break;case 88:this.$=new e.Slice(g[i]);break;case 89:this.$=new e.Obj(g[i-2],g[i-3].generated);break;case 90:this.$=[];break;case 91:this.$=[g[i]];break;case 92:this.$=g[i-2].concat(g[i]);break;case 93:this.$=g[i-3].concat(g[i]);break;case 94:this.$=g[i-5].concat(g[i-2]);break;case 95:this.$=new e.Class;break;case 96:this.$=new e.Class(null,null,g[i]);break;case 97:this.$=new e.Class(null,g[i]);break;case 98:this.$=new e.Class(null,g[i-1],g[i]);break;case 99:this.$=new e.Class(g[i]);break;case 100:this.$=new e.Class(g[i-1],null,g[i]);break;case 101:this.$=new e.Class(g[i-2],g[i]);break;case 102:this.$=new e.Class(g[i-3],g[i-1],g[i]);break;case 103:this.$=new e.Call(g[i-2],g[i],g[i-1]);break;case 104:this.$=new e.Call(g[i-2],g[i],g[i-1]);break;case 105:this.$=new e.Call("super",[new e.Splat(new e.Literal("arguments"))]);break;case 106:this.$=new e.Call("super",g[i]);break;case 107:this.$=!1;break;case 108:this.$=!0;break;case 109:this.$=[];break;case 110:this.$=g[i-2];break;case 111:this.$=new e.Value(new e.Literal("this"));break;case 112:this.$=new e.Value(new e.Literal("this"));break;case 113:this.$=new e.Value(new e.Literal("this"),[new e.Access(g[i])],"this");break;case 114:this.$=new e.Arr([]);break;case 115:this.$=new e.Arr(g[i-2]);break;case 116:this.$="inclusive";break;case 117:this.$="exclusive";break;case 118:this.$=new e.Range(g[i-3],g[i-1],g[i-2]);break;case 119:this.$=new e.Range(g[i-2],g[i],g[i-1]);break;case 120:this.$=new e.Range(g[i-1],null,g[i]);break;case 121:this.$=new e.Range(null,g[i],g[i-1]);break;case 122:this.$=new e.Range(null,null,g[i]);break;case 123:this.$=[g[i]];break;case 124:this.$=g[i-2].concat(g[i]);break;case 125:this.$=g[i-3].concat(g[i]);break;case 126:this.$=g[i-2];break;case 127:this.$=g[i-5].concat(g[i-2]);break;case 128:this.$=g[i];break;case 129:this.$=g[i];break;case 130:this.$=g[i];break;case 131:this.$=[].concat(g[i-2],g[i]);break;case 132:this.$=new e.Try(g[i]);break;case 133:this.$=new e.Try(g[i-1],g[i][0],g[i][1]);break;case 134:this.$=new e.Try(g[i-2],null,null,g[i]);break;case 135:this.$=new e.Try(g[i-3],g[i-2][0],g[i-2][1],g[i]);break;case 136:this.$=[g[i-1],g[i]];break;case 137:this.$=new e.Throw(g[i]);break;case 138:this.$=new e.Parens(g[i-1]);break;case 139:this.$=new e.Parens(g[i-2]);break;case 140:this.$=new e.While(g[i]);break;case 141:this.$=new e.While(g[i-2],{guard:g[i]});break;case 142:this.$=new e.While(g[i],{invert:!0});break;case 143:this.$=new e.While(g[i-2],{invert:!0,guard:g[i]});break;case 144:this.$=g[i-1].addBody(g[i]);break;case 145:this.$=g[i].addBody(e.Block.wrap([g[i-1]]));break;case 146:this.$=g[i].addBody(e.Block.wrap([g[i-1]]));break;case 147:this.$=g[i];break;case 148:this.$=(new e.While(new e.Literal("true"))).addBody(g[i]);break;case 149:this.$=(new e.While(new e.Literal("true"))).addBody(e.Block.wrap([g[i]]));break;case 150:this.$=new e.For(g[i-1],g[i]);break;case 151:this.$=new e.For(g[i-1],g[i]);break;case 152:this.$=new e.For(g[i],g[i-1]);break;case 153:this.$={source:new e.Value(g[i])};break;case 154:this.$=function(){return g[i].own=g[i-1].own,g[i].name=g[i-1][0],g[i].index=g[i-1][1],g[i]}();break;case 155:this.$=g[i];break;case 156:this.$=function(){return g[i].own=!0,g[i]}();break;case 157:this.$=g[i];break;case 158:this.$=g[i];break;case 159:this.$=new e.Value(g[i]);break;case 160:this.$=new e.Value(g[i]);break;case 161:this.$=[g[i]];break;case 162:this.$=[g[i-2],g[i]];break;case 163:this.$={source:g[i]};break;case 164:this.$={source:g[i],object:!0};break;case 165:this.$={source:g[i-2],guard:g[i]};break;case 166:this.$={source:g[i-2],guard:g[i],object:!0};break;case 167:this.$={source:g[i-2],step:g[i]};break;case 168:this.$={source:g[i-4],guard:g[i-2],step:g[i]};break;case 169:this.$={source:g[i-4],step:g[i-2],guard:g[i]};break;case 170:this.$=new e.Switch(g[i-3],g[i-1]);break;case 171:this.$=new e.Switch(g[i-5],g[i-3],g[i-1]);break;case 172:this.$=new e.Switch(null,g[i-1]);break;case 173:this.$=new e.Switch(null,g[i-3],g[i-1]);break;case 174:this.$=g[i];break;case 175:this.$=g[i-1].concat(g[i]);break;case 176:this.$=[[g[i-1],g[i]]];break;case 177:this.$=[[g[i-2],g[i-1]]];break;case 178:this.$=new e.If(g[i-1],g[i],{type:g[i-2]});break;case 179:this.$=g[i-4].addElse(new e.If(g[i-1],g[i],{type:g[i-2]}));break;case 180:this.$=g[i];break;case 181:this.$=g[i-2].addElse(g[i]);break;case 182:this.$=new e.If(g[i],e.Block.wrap([g[i-2]]),{type:g[i-1],statement:!0});break;case 183:this.$=new e.If(g[i],e.Block.wrap([g[i-2]]),{type:g[i-1],statement:!0});break;case 184:this.$=new e.Op(g[i-1],g[i]);break;case 185:this.$=new e.Op("-",g[i]);break;case 186:this.$=new e.Op("+",g[i]);break;case 187:this.$=new e.Op("--",g[i]);break;case 188:this.$=new e.Op("++",g[i]);break;case 189:this.$=new e.Op("--",g[i-1],null,!0);break;case 190:this.$=new e.Op("++",g[i-1],null,!0);break;case 191:this.$=new e.Existence(g[i-1]);break;case 192:this.$=new e.Op("+",g[i-2],g[i]);break;case 193:this.$=new e.Op("-",g[i-2],g[i]);break;case 194:this.$=new e.Op(g[i-1],g[i-2],g[i]);break;case 195:this.$=new e.Op(g[i-1],g[i-2],g[i]);break;case 196:this.$=new e.Op(g[i-1],g[i-2],g[i]);break;case 197:this.$=new e.Op(g[i-1],g[i-2],g[i]);break;case 198:this.$=function(){return g[i-1].charAt(0)==="!"?(new e.Op(g[i-1].slice(1),g[i-2],g[i])).invert():new e.Op(g[i-1],g[i-2],g[i])}();break;case 199:this.$=new e.Assign(g[i-2],g[i],g[i-1]);break;case 200:this.$=new e.Assign(g[i-4],g[i-1],g[i-3]);break;case 201:this.$=new e.Extends(g[i-2],g[i])}},table:[{1:[2,1],3:1,4:2,5:3,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[3]},{1:[2,2],6:[1,74]},{6:[1,75]},{1:[2,4],6:[2,4],26:[2,4],101:[2,4]},{4:77,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[1,76],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,7],6:[2,7],26:[2,7],101:[2,7],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,8],6:[2,8],26:[2,8],101:[2,8],102:90,103:[1,65],105:[1,66],108:91,109:[1,68],110:69,125:[1,89]},{1:[2,12],6:[2,12],25:[2,12],26:[2,12],49:[2,12],54:[2,12],57:[2,12],62:93,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],72:[2,12],73:[1,100],77:[2,12],80:92,83:[1,94],84:[2,107],85:[2,12],90:[2,12],92:[2,12],101:[2,12],103:[2,12],104:[2,12],105:[2,12],109:[2,12],117:[2,12],125:[2,12],127:[2,12],128:[2,12],131:[2,12],132:[2,12],133:[2,12],134:[2,12],135:[2,12],136:[2,12]},{1:[2,13],6:[2,13],25:[2,13],26:[2,13],49:[2,13],54:[2,13],57:[2,13],62:102,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],72:[2,13],73:[1,100],77:[2,13],80:101,83:[1,94],84:[2,107],85:[2,13],90:[2,13],92:[2,13],101:[2,13],103:[2,13],104:[2,13],105:[2,13],109:[2,13],117:[2,13],125:[2,13],127:[2,13],128:[2,13],131:[2,13],132:[2,13],133:[2,13],134:[2,13],135:[2,13],136:[2,13]},{1:[2,14],6:[2,14],25:[2,14],26:[2,14],49:[2,14],54:[2,14],57:[2,14],72:[2,14],77:[2,14],85:[2,14],90:[2,14],92:[2,14],101:[2,14],103:[2,14],104:[2,14],105:[2,14],109:[2,14],117:[2,14],125:[2,14],127:[2,14],128:[2,14],131:[2,14],132:[2,14],133:[2,14],134:[2,14],135:[2,14],136:[2,14]},{1:[2,15],6:[2,15],25:[2,15],26:[2,15],49:[2,15],54:[2,15],57:[2,15],72:[2,15],77:[2,15],85:[2,15],90:[2,15],92:[2,15],101:[2,15],103:[2,15],104:[2,15],105:[2,15],109:[2,15],117:[2,15],125:[2,15],127:[2,15],128:[2,15],131:[2,15],132:[2,15],133:[2,15],134:[2,15],135:[2,15],136:[2,15]},{1:[2,16],6:[2,16],25:[2,16],26:[2,16],49:[2,16],54:[2,16],57:[2,16],72:[2,16],77:[2,16],85:[2,16],90:[2,16],92:[2,16],101:[2,16],103:[2,16],104:[2,16],105:[2,16],109:[2,16],117:[2,16],125:[2,16],127:[2,16],128:[2,16],131:[2,16],132:[2,16],133:[2,16],134:[2,16],135:[2,16],136:[2,16]},{1:[2,17],6:[2,17],25:[2,17],26:[2,17],49:[2,17],54:[2,17],57:[2,17],72:[2,17],77:[2,17],85:[2,17],90:[2,17],92:[2,17],101:[2,17],103:[2,17],104:[2,17],105:[2,17],109:[2,17],117:[2,17],125:[2,17],127:[2,17],128:[2,17],131:[2,17],132:[2,17],133:[2,17],134:[2,17],135:[2,17],136:[2,17]},{1:[2,18],6:[2,18],25:[2,18],26:[2,18],49:[2,18],54:[2,18],57:[2,18],72:[2,18],77:[2,18],85:[2,18],90:[2,18],92:[2,18],101:[2,18],103:[2,18],104:[2,18],105:[2,18],109:[2,18],117:[2,18],125:[2,18],127:[2,18],128:[2,18],131:[2,18],132:[2,18],133:[2,18],134:[2,18],135:[2,18],136:[2,18]},{1:[2,19],6:[2,19],25:[2,19],26:[2,19],49:[2,19],54:[2,19],57:[2,19],72:[2,19],77:[2,19],85:[2,19],90:[2,19],92:[2,19],101:[2,19],103:[2,19],104:[2,19],105:[2,19],109:[2,19],117:[2,19],125:[2,19],127:[2,19],128:[2,19],131:[2,19],132:[2,19],133:[2,19],134:[2,19],135:[2,19],136:[2,19]},{1:[2,20],6:[2,20],25:[2,20],26:[2,20],49:[2,20],54:[2,20],57:[2,20],72:[2,20],77:[2,20],85:[2,20],90:[2,20],92:[2,20],101:[2,20],103:[2,20],104:[2,20],105:[2,20],109:[2,20],117:[2,20],125:[2,20],127:[2,20],128:[2,20],131:[2,20],132:[2,20],133:[2,20],134:[2,20],135:[2,20],136:[2,20]},{1:[2,21],6:[2,21],25:[2,21],26:[2,21],49:[2,21],54:[2,21],57:[2,21],72:[2,21],77:[2,21],85:[2,21],90:[2,21],92:[2,21],101:[2,21],103:[2,21],104:[2,21],105:[2,21],109:[2,21],117:[2,21],125:[2,21],127:[2,21],128:[2,21],131:[2,21],132:[2,21],133:[2,21],134:[2,21],135:[2,21],136:[2,21]},{1:[2,22],6:[2,22],25:[2,22],26:[2,22],49:[2,22],54:[2,22],57:[2,22],72:[2,22],77:[2,22],85:[2,22],90:[2,22],92:[2,22],101:[2,22],103:[2,22],104:[2,22],105:[2,22],109:[2,22],117:[2,22],125:[2,22],127:[2,22],128:[2,22],131:[2,22],132:[2,22],133:[2,22],134:[2,22],135:[2,22],136:[2,22]},{1:[2,23],6:[2,23],25:[2,23],26:[2,23],49:[2,23],54:[2,23],57:[2,23],72:[2,23],77:[2,23],85:[2,23],90:[2,23],92:[2,23],101:[2,23],103:[2,23],104:[2,23],105:[2,23],109:[2,23],117:[2,23],125:[2,23],127:[2,23],128:[2,23],131:[2,23],132:[2,23],133:[2,23],134:[2,23],135:[2,23],136:[2,23]},{1:[2,9],6:[2,9],26:[2,9],101:[2,9],103:[2,9],105:[2,9],109:[2,9],125:[2,9]},{1:[2,10],6:[2,10],26:[2,10],101:[2,10],103:[2,10],105:[2,10],109:[2,10],125:[2,10]},{1:[2,11],6:[2,11],26:[2,11],101:[2,11],103:[2,11],105:[2,11],109:[2,11],125:[2,11]},{1:[2,75],6:[2,75],25:[2,75],26:[2,75],40:[1,103],49:[2,75],54:[2,75],57:[2,75],66:[2,75],67:[2,75],68:[2,75],70:[2,75],72:[2,75],73:[2,75],77:[2,75],83:[2,75],84:[2,75],85:[2,75],90:[2,75],92:[2,75],101:[2,75],103:[2,75],104:[2,75],105:[2,75],109:[2,75],117:[2,75],125:[2,75],127:[2,75],128:[2,75],131:[2,75],132:[2,75],133:[2,75],134:[2,75],135:[2,75],136:[2,75]},{1:[2,76],6:[2,76],25:[2,76],26:[2,76],49:[2,76],54:[2,76],57:[2,76],66:[2,76],67:[2,76],68:[2,76],70:[2,76],72:[2,76],73:[2,76],77:[2,76],83:[2,76],84:[2,76],85:[2,76],90:[2,76],92:[2,76],101:[2,76],103:[2,76],104:[2,76],105:[2,76],109:[2,76],117:[2,76],125:[2,76],127:[2,76],128:[2,76],131:[2,76],132:[2,76],133:[2,76],134:[2,76],135:[2,76],136:[2,76]},{1:[2,77],6:[2,77],25:[2,77],26:[2,77],49:[2,77],54:[2,77],57:[2,77],66:[2,77],67:[2,77],68:[2,77],70:[2,77],72:[2,77],73:[2,77],77:[2,77],83:[2,77],84:[2,77],85:[2,77],90:[2,77],92:[2,77],101:[2,77],103:[2,77],104:[2,77],105:[2,77],109:[2,77],117:[2,77],125:[2,77],127:[2,77],128:[2,77],131:[2,77],132:[2,77],133:[2,77],134:[2,77],135:[2,77],136:[2,77]},{1:[2,78],6:[2,78],25:[2,78],26:[2,78],49:[2,78],54:[2,78],57:[2,78],66:[2,78],67:[2,78],68:[2,78],70:[2,78],72:[2,78],73:[2,78],77:[2,78],83:[2,78],84:[2,78],85:[2,78],90:[2,78],92:[2,78],101:[2,78],103:[2,78],104:[2,78],105:[2,78],109:[2,78],117:[2,78],125:[2,78],127:[2,78],128:[2,78],131:[2,78],132:[2,78],133:[2,78],134:[2,78],135:[2,78],136:[2,78]},{1:[2,79],6:[2,79],25:[2,79],26:[2,79],49:[2,79],54:[2,79],57:[2,79],66:[2,79],67:[2,79],68:[2,79],70:[2,79],72:[2,79],73:[2,79],77:[2,79],83:[2,79],84:[2,79],85:[2,79],90:[2,79],92:[2,79],101:[2,79],103:[2,79],104:[2,79],105:[2,79],109:[2,79],117:[2,79],125:[2,79],127:[2,79],128:[2,79],131:[2,79],132:[2,79],133:[2,79],134:[2,79],135:[2,79],136:[2,79]},{1:[2,105],6:[2,105],25:[2,105],26:[2,105],49:[2,105],54:[2,105],57:[2,105],66:[2,105],67:[2,105],68:[2,105],70:[2,105],72:[2,105],73:[2,105],77:[2,105],81:104,83:[2,105],84:[1,105],85:[2,105],90:[2,105],92:[2,105],101:[2,105],103:[2,105],104:[2,105],105:[2,105],109:[2,105],117:[2,105],125:[2,105],127:[2,105],128:[2,105],131:[2,105],132:[2,105],133:[2,105],134:[2,105],135:[2,105],136:[2,105]},{6:[2,55],25:[2,55],27:109,28:[1,73],44:110,48:106,49:[2,55],54:[2,55],55:107,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{5:115,25:[1,5]},{8:116,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:118,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:119,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{13:121,14:122,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,58:47,59:48,61:120,63:25,64:26,65:27,75:[1,70],82:[1,28],87:[1,58],88:[1,59],89:[1,57],100:[1,56]},{13:121,14:122,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,58:47,59:48,61:124,63:25,64:26,65:27,75:[1,70],82:[1,28],87:[1,58],88:[1,59],89:[1,57],100:[1,56]},{1:[2,72],6:[2,72],25:[2,72],26:[2,72],40:[2,72],49:[2,72],54:[2,72],57:[2,72],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,72],73:[2,72],77:[2,72],79:[1,128],83:[2,72],84:[2,72],85:[2,72],90:[2,72],92:[2,72],101:[2,72],103:[2,72],104:[2,72],105:[2,72],109:[2,72],117:[2,72],125:[2,72],127:[2,72],128:[2,72],129:[1,125],130:[1,126],131:[2,72],132:[2,72],133:[2,72],134:[2,72],135:[2,72],136:[2,72],137:[1,127]},{1:[2,180],6:[2,180],25:[2,180],26:[2,180],49:[2,180],54:[2,180],57:[2,180],72:[2,180],77:[2,180],85:[2,180],90:[2,180],92:[2,180],101:[2,180],103:[2,180],104:[2,180],105:[2,180],109:[2,180],117:[2,180],120:[1,129],125:[2,180],127:[2,180],128:[2,180],131:[2,180],132:[2,180],133:[2,180],134:[2,180],135:[2,180],136:[2,180]},{5:130,25:[1,5]},{5:131,25:[1,5]},{1:[2,147],6:[2,147],25:[2,147],26:[2,147],49:[2,147],54:[2,147],57:[2,147],72:[2,147],77:[2,147],85:[2,147],90:[2,147],92:[2,147],101:[2,147],103:[2,147],104:[2,147],105:[2,147],109:[2,147],117:[2,147],125:[2,147],127:[2,147],128:[2,147],131:[2,147],132:[2,147],133:[2,147],134:[2,147],135:[2,147],136:[2,147]},{5:132,25:[1,5]},{8:133,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,134],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,95],5:135,6:[2,95],13:121,14:122,25:[1,5],26:[2,95],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:123,44:63,49:[2,95],54:[2,95],57:[2,95],58:47,59:48,61:137,63:25,64:26,65:27,72:[2,95],75:[1,70],77:[2,95],79:[1,136],82:[1,28],85:[2,95],87:[1,58],88:[1,59],89:[1,57],90:[2,95],92:[2,95],100:[1,56],101:[2,95],103:[2,95],104:[2,95],105:[2,95],109:[2,95],117:[2,95],125:[2,95],127:[2,95],128:[2,95],131:[2,95],132:[2,95],133:[2,95],134:[2,95],135:[2,95],136:[2,95]},{8:138,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,47],6:[2,47],8:139,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,47],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],101:[2,47],102:39,103:[2,47],105:[2,47],106:40,107:[1,67],108:41,109:[2,47],110:69,118:[1,42],123:37,124:[1,64],125:[2,47],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,48],6:[2,48],25:[2,48],26:[2,48],54:[2,48],77:[2,48],101:[2,48],103:[2,48],105:[2,48],109:[2,48],125:[2,48]},{1:[2,73],6:[2,73],25:[2,73],26:[2,73],40:[2,73],49:[2,73],54:[2,73],57:[2,73],66:[2,73],67:[2,73],68:[2,73],70:[2,73],72:[2,73],73:[2,73],77:[2,73],83:[2,73],84:[2,73],85:[2,73],90:[2,73],92:[2,73],101:[2,73],103:[2,73],104:[2,73],105:[2,73],109:[2,73],117:[2,73],125:[2,73],127:[2,73],128:[2,73],131:[2,73],132:[2,73],133:[2,73],134:[2,73],135:[2,73],136:[2,73]},{1:[2,74],6:[2,74],25:[2,74],26:[2,74],40:[2,74],49:[2,74],54:[2,74],57:[2,74],66:[2,74],67:[2,74],68:[2,74],70:[2,74],72:[2,74],73:[2,74],77:[2,74],83:[2,74],84:[2,74],85:[2,74],90:[2,74],92:[2,74],101:[2,74],103:[2,74],104:[2,74],105:[2,74],109:[2,74],117:[2,74],125:[2,74],127:[2,74],128:[2,74],131:[2,74],132:[2,74],133:[2,74],134:[2,74],135:[2,74],136:[2,74]},{1:[2,29],6:[2,29],25:[2,29],26:[2,29],49:[2,29],54:[2,29],57:[2,29],66:[2,29],67:[2,29],68:[2,29],70:[2,29],72:[2,29],73:[2,29],77:[2,29],83:[2,29],84:[2,29],85:[2,29],90:[2,29],92:[2,29],101:[2,29],103:[2,29],104:[2,29],105:[2,29],109:[2,29],117:[2,29],125:[2,29],127:[2,29],128:[2,29],131:[2,29],132:[2,29],133:[2,29],134:[2,29],135:[2,29],136:[2,29]},{1:[2,30],6:[2,30],25:[2,30],26:[2,30],49:[2,30],54:[2,30],57:[2,30],66:[2,30],67:[2,30],68:[2,30],70:[2,30],72:[2,30],73:[2,30],77:[2,30],83:[2,30],84:[2,30],85:[2,30],90:[2,30],92:[2,30],101:[2,30],103:[2,30],104:[2,30],105:[2,30],109:[2,30],117:[2,30],125:[2,30],127:[2,30],128:[2,30],131:[2,30],132:[2,30],133:[2,30],134:[2,30],135:[2,30],136:[2,30]},{1:[2,31],6:[2,31],25:[2,31],26:[2,31],49:[2,31],54:[2,31],57:[2,31],66:[2,31],67:[2,31],68:[2,31],70:[2,31],72:[2,31],73:[2,31],77:[2,31],83:[2,31],84:[2,31],85:[2,31],90:[2,31],92:[2,31],101:[2,31],103:[2,31],104:[2,31],105:[2,31],109:[2,31],117:[2,31],125:[2,31],127:[2,31],128:[2,31],131:[2,31],132:[2,31],133:[2,31],134:[2,31],135:[2,31],136:[2,31]},{1:[2,32],6:[2,32],25:[2,32],26:[2,32],49:[2,32],54:[2,32],57:[2,32],66:[2,32],67:[2,32],68:[2,32],70:[2,32],72:[2,32],73:[2,32],77:[2,32],83:[2,32],84:[2,32],85:[2,32],90:[2,32],92:[2,32],101:[2,32],103:[2,32],104:[2,32],105:[2,32],109:[2,32],117:[2,32],125:[2,32],127:[2,32],128:[2,32],131:[2,32],132:[2,32],133:[2,32],134:[2,32],135:[2,32],136:[2,32]},{1:[2,33],6:[2,33],25:[2,33],26:[2,33],49:[2,33],54:[2,33],57:[2,33],66:[2,33],67:[2,33],68:[2,33],70:[2,33],72:[2,33],73:[2,33],77:[2,33],83:[2,33],84:[2,33],85:[2,33],90:[2,33],92:[2,33],101:[2,33],103:[2,33],104:[2,33],105:[2,33],109:[2,33],117:[2,33],125:[2,33],127:[2,33],128:[2,33],131:[2,33],132:[2,33],133:[2,33],134:[2,33],135:[2,33],136:[2,33]},{1:[2,34],6:[2,34],25:[2,34],26:[2,34],49:[2,34],54:[2,34],57:[2,34],66:[2,34],67:[2,34],68:[2,34],70:[2,34],72:[2,34],73:[2,34],77:[2,34],83:[2,34],84:[2,34],85:[2,34],90:[2,34],92:[2,34],101:[2,34],103:[2,34],104:[2,34],105:[2,34],109:[2,34],117:[2,34],125:[2,34],127:[2,34],128:[2,34],131:[2,34],132:[2,34],133:[2,34],134:[2,34],135:[2,34],136:[2,34]},{1:[2,35],6:[2,35],25:[2,35],26:[2,35],49:[2,35],54:[2,35],57:[2,35],66:[2,35],67:[2,35],68:[2,35],70:[2,35],72:[2,35],73:[2,35],77:[2,35],83:[2,35],84:[2,35],85:[2,35],90:[2,35],92:[2,35],101:[2,35],103:[2,35],104:[2,35],105:[2,35],109:[2,35],117:[2,35],125:[2,35],127:[2,35],128:[2,35],131:[2,35],132:[2,35],133:[2,35],134:[2,35],135:[2,35],136:[2,35]},{4:140,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,141],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:142,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:144,87:[1,58],88:[1,59],89:[1,57],90:[1,143],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,111],6:[2,111],25:[2,111],26:[2,111],49:[2,111],54:[2,111],57:[2,111],66:[2,111],67:[2,111],68:[2,111],70:[2,111],72:[2,111],73:[2,111],77:[2,111],83:[2,111],84:[2,111],85:[2,111],90:[2,111],92:[2,111],101:[2,111],103:[2,111],104:[2,111],105:[2,111],109:[2,111],117:[2,111],125:[2,111],127:[2,111],128:[2,111],131:[2,111],132:[2,111],133:[2,111],134:[2,111],135:[2,111],136:[2,111]},{1:[2,112],6:[2,112],25:[2,112],26:[2,112],27:148,28:[1,73],49:[2,112],54:[2,112],57:[2,112],66:[2,112],67:[2,112],68:[2,112],70:[2,112],72:[2,112],73:[2,112],77:[2,112],83:[2,112],84:[2,112],85:[2,112],90:[2,112],92:[2,112],101:[2,112],103:[2,112],104:[2,112],105:[2,112],109:[2,112],117:[2,112],125:[2,112],127:[2,112],128:[2,112],131:[2,112],132:[2,112],133:[2,112],134:[2,112],135:[2,112],136:[2,112]},{25:[2,51]},{25:[2,52]},{1:[2,68],6:[2,68],25:[2,68],26:[2,68],40:[2,68],49:[2,68],54:[2,68],57:[2,68],66:[2,68],67:[2,68],68:[2,68],70:[2,68],72:[2,68],73:[2,68],77:[2,68],79:[2,68],83:[2,68],84:[2,68],85:[2,68],90:[2,68],92:[2,68],101:[2,68],103:[2,68],104:[2,68],105:[2,68],109:[2,68],117:[2,68],125:[2,68],127:[2,68],128:[2,68],129:[2,68],130:[2,68],131:[2,68],132:[2,68],133:[2,68],134:[2,68],135:[2,68],136:[2,68],137:[2,68]},{1:[2,71],6:[2,71],25:[2,71],26:[2,71],40:[2,71],49:[2,71],54:[2,71],57:[2,71],66:[2,71],67:[2,71],68:[2,71],70:[2,71],72:[2,71],73:[2,71],77:[2,71],79:[2,71],83:[2,71],84:[2,71],85:[2,71],90:[2,71],92:[2,71],101:[2,71],103:[2,71],104:[2,71],105:[2,71],109:[2,71],117:[2,71],125:[2,71],127:[2,71],128:[2,71],129:[2,71],130:[2,71],131:[2,71],132:[2,71],133:[2,71],134:[2,71],135:[2,71],136:[2,71],137:[2,71]},{8:149,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:150,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:151,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{5:152,8:153,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,5],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{27:158,28:[1,73],44:159,58:160,59:161,64:154,75:[1,70],88:[1,113],89:[1,57],112:155,113:[1,156],114:157},{111:162,115:[1,163],116:[1,164]},{6:[2,90],11:168,25:[2,90],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:166,42:167,44:171,46:[1,46],54:[2,90],76:165,77:[2,90],88:[1,113]},{1:[2,27],6:[2,27],25:[2,27],26:[2,27],43:[2,27],49:[2,27],54:[2,27],57:[2,27],66:[2,27],67:[2,27],68:[2,27],70:[2,27],72:[2,27],73:[2,27],77:[2,27],83:[2,27],84:[2,27],85:[2,27],90:[2,27],92:[2,27],101:[2,27],103:[2,27],104:[2,27],105:[2,27],109:[2,27],117:[2,27],125:[2,27],127:[2,27],128:[2,27],131:[2,27],132:[2,27],133:[2,27],134:[2,27],135:[2,27],136:[2,27]},{1:[2,28],6:[2,28],25:[2,28],26:[2,28],43:[2,28],49:[2,28],54:[2,28],57:[2,28],66:[2,28],67:[2,28],68:[2,28],70:[2,28],72:[2,28],73:[2,28],77:[2,28],83:[2,28],84:[2,28],85:[2,28],90:[2,28],92:[2,28],101:[2,28],103:[2,28],104:[2,28],105:[2,28],109:[2,28],117:[2,28],125:[2,28],127:[2,28],128:[2,28],131:[2,28],132:[2,28],133:[2,28],134:[2,28],135:[2,28],136:[2,28]},{1:[2,26],6:[2,26],25:[2,26],26:[2,26],40:[2,26],43:[2,26],49:[2,26],54:[2,26],57:[2,26],66:[2,26],67:[2,26],68:[2,26],70:[2,26],72:[2,26],73:[2,26],77:[2,26],79:[2,26],83:[2,26],84:[2,26],85:[2,26],90:[2,26],92:[2,26],101:[2,26],103:[2,26],104:[2,26],105:[2,26],109:[2,26],115:[2,26],116:[2,26],117:[2,26],125:[2,26],127:[2,26],128:[2,26],129:[2,26],130:[2,26],131:[2,26],132:[2,26],133:[2,26],134:[2,26],135:[2,26],136:[2,26],137:[2,26]},{1:[2,6],6:[2,6],7:172,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,26:[2,6],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],101:[2,6],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,3]},{1:[2,24],6:[2,24],25:[2,24],26:[2,24],49:[2,24],54:[2,24],57:[2,24],72:[2,24],77:[2,24],85:[2,24],90:[2,24],92:[2,24],97:[2,24],98:[2,24],101:[2,24],103:[2,24],104:[2,24],105:[2,24],109:[2,24],117:[2,24],120:[2,24],122:[2,24],125:[2,24],127:[2,24],128:[2,24],131:[2,24],132:[2,24],133:[2,24],134:[2,24],135:[2,24],136:[2,24]},{6:[1,74],26:[1,173]},{1:[2,191],6:[2,191],25:[2,191],26:[2,191],49:[2,191],54:[2,191],57:[2,191],72:[2,191],77:[2,191],85:[2,191],90:[2,191],92:[2,191],101:[2,191],103:[2,191],104:[2,191],105:[2,191],109:[2,191],117:[2,191],125:[2,191],127:[2,191],128:[2,191],131:[2,191],132:[2,191],133:[2,191],134:[2,191],135:[2,191],136:[2,191]},{8:174,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:175,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:176,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:177,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:178,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:179,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:180,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:181,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,146],6:[2,146],25:[2,146],26:[2,146],49:[2,146],54:[2,146],57:[2,146],72:[2,146],77:[2,146],85:[2,146],90:[2,146],92:[2,146],101:[2,146],103:[2,146],104:[2,146],105:[2,146],109:[2,146],117:[2,146],125:[2,146],127:[2,146],128:[2,146],131:[2,146],132:[2,146],133:[2,146],134:[2,146],135:[2,146],136:[2,146]},{1:[2,151],6:[2,151],25:[2,151],26:[2,151],49:[2,151],54:[2,151],57:[2,151],72:[2,151],77:[2,151],85:[2,151],90:[2,151],92:[2,151],101:[2,151],103:[2,151],104:[2,151],105:[2,151],109:[2,151],117:[2,151],125:[2,151],127:[2,151],128:[2,151],131:[2,151],132:[2,151],133:[2,151],134:[2,151],135:[2,151],136:[2,151]},{8:182,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,145],6:[2,145],25:[2,145],26:[2,145],49:[2,145],54:[2,145],57:[2,145],72:[2,145],77:[2,145],85:[2,145],90:[2,145],92:[2,145],101:[2,145],103:[2,145],104:[2,145],105:[2,145],109:[2,145],117:[2,145],125:[2,145],127:[2,145],128:[2,145],131:[2,145],132:[2,145],133:[2,145],134:[2,145],135:[2,145],136:[2,145]},{1:[2,150],6:[2,150],25:[2,150],26:[2,150],49:[2,150],54:[2,150],57:[2,150],72:[2,150],77:[2,150],85:[2,150],90:[2,150],92:[2,150],101:[2,150],103:[2,150],104:[2,150],105:[2,150],109:[2,150],117:[2,150],125:[2,150],127:[2,150],128:[2,150],131:[2,150],132:[2,150],133:[2,150],134:[2,150],135:[2,150],136:[2,150]},{81:183,84:[1,105]},{1:[2,69],6:[2,69],25:[2,69],26:[2,69],40:[2,69],49:[2,69],54:[2,69],57:[2,69],66:[2,69],67:[2,69],68:[2,69],70:[2,69],72:[2,69],73:[2,69],77:[2,69],79:[2,69],83:[2,69],84:[2,69],85:[2,69],90:[2,69],92:[2,69],101:[2,69],103:[2,69],104:[2,69],105:[2,69],109:[2,69],117:[2,69],125:[2,69],127:[2,69],128:[2,69],129:[2,69],130:[2,69],131:[2,69],132:[2,69],133:[2,69],134:[2,69],135:[2,69],136:[2,69],137:[2,69]},{84:[2,108]},{27:184,28:[1,73]},{27:185,28:[1,73]},{1:[2,83],6:[2,83],25:[2,83],26:[2,83],27:186,28:[1,73],40:[2,83],49:[2,83],54:[2,83],57:[2,83],66:[2,83],67:[2,83],68:[2,83],70:[2,83],72:[2,83],73:[2,83],77:[2,83],79:[2,83],83:[2,83],84:[2,83],85:[2,83],90:[2,83],92:[2,83],101:[2,83],103:[2,83],104:[2,83],105:[2,83],109:[2,83],117:[2,83],125:[2,83],127:[2,83],128:[2,83],129:[2,83],130:[2,83],131:[2,83],132:[2,83],133:[2,83],134:[2,83],135:[2,83],136:[2,83],137:[2,83]},{1:[2,84],6:[2,84],25:[2,84],26:[2,84],40:[2,84],49:[2,84],54:[2,84],57:[2,84],66:[2,84],67:[2,84],68:[2,84],70:[2,84],72:[2,84],73:[2,84],77:[2,84],79:[2,84],83:[2,84],84:[2,84],85:[2,84],90:[2,84],92:[2,84],101:[2,84],103:[2,84],104:[2,84],105:[2,84],109:[2,84],117:[2,84],125:[2,84],127:[2,84],128:[2,84],129:[2,84],130:[2,84],131:[2,84],132:[2,84],133:[2,84],134:[2,84],135:[2,84],136:[2,84],137:[2,84]},{8:188,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],57:[1,192],58:47,59:48,61:36,63:25,64:26,65:27,71:187,74:189,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],91:190,92:[1,191],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{69:193,70:[1,99],73:[1,100]},{81:194,84:[1,105]},{1:[2,70],6:[2,70],25:[2,70],26:[2,70],40:[2,70],49:[2,70],54:[2,70],57:[2,70],66:[2,70],67:[2,70],68:[2,70],70:[2,70],72:[2,70],73:[2,70],77:[2,70],79:[2,70],83:[2,70],84:[2,70],85:[2,70],90:[2,70],92:[2,70],101:[2,70],103:[2,70],104:[2,70],105:[2,70],109:[2,70],117:[2,70],125:[2,70],127:[2,70],128:[2,70],129:[2,70],130:[2,70],131:[2,70],132:[2,70],133:[2,70],134:[2,70],135:[2,70],136:[2,70],137:[2,70]},{6:[1,196],8:195,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,197],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,106],6:[2,106],25:[2,106],26:[2,106],49:[2,106],54:[2,106],57:[2,106],66:[2,106],67:[2,106],68:[2,106],70:[2,106],72:[2,106],73:[2,106],77:[2,106],83:[2,106],84:[2,106],85:[2,106],90:[2,106],92:[2,106],101:[2,106],103:[2,106],104:[2,106],105:[2,106],109:[2,106],117:[2,106],125:[2,106],127:[2,106],128:[2,106],131:[2,106],132:[2,106],133:[2,106],134:[2,106],135:[2,106],136:[2,106]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],85:[1,198],86:199,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],49:[1,201],53:203,54:[1,202]},{6:[2,56],25:[2,56],26:[2,56],49:[2,56],54:[2,56]},{6:[2,60],25:[2,60],26:[2,60],40:[1,205],49:[2,60],54:[2,60],57:[1,204]},{6:[2,63],25:[2,63],26:[2,63],40:[2,63],49:[2,63],54:[2,63],57:[2,63]},{6:[2,64],25:[2,64],26:[2,64],40:[2,64],49:[2,64],54:[2,64],57:[2,64]},{6:[2,65],25:[2,65],26:[2,65],40:[2,65],49:[2,65],54:[2,65],57:[2,65]},{6:[2,66],25:[2,66],26:[2,66],40:[2,66],49:[2,66],54:[2,66],57:[2,66]},{27:148,28:[1,73]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:144,87:[1,58],88:[1,59],89:[1,57],90:[1,143],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,50],6:[2,50],25:[2,50],26:[2,50],49:[2,50],54:[2,50],57:[2,50],72:[2,50],77:[2,50],85:[2,50],90:[2,50],92:[2,50],101:[2,50],103:[2,50],104:[2,50],105:[2,50],109:[2,50],117:[2,50],125:[2,50],127:[2,50],128:[2,50],131:[2,50],132:[2,50],133:[2,50],134:[2,50],135:[2,50],136:[2,50]},{1:[2,184],6:[2,184],25:[2,184],26:[2,184],49:[2,184],54:[2,184],57:[2,184],72:[2,184],77:[2,184],85:[2,184],90:[2,184],92:[2,184],101:[2,184],102:87,103:[2,184],104:[2,184],105:[2,184],108:88,109:[2,184],110:69,117:[2,184],125:[2,184],127:[2,184],128:[2,184],131:[1,78],132:[2,184],133:[2,184],134:[2,184],135:[2,184],136:[2,184]},{102:90,103:[1,65],105:[1,66],108:91,109:[1,68],110:69,125:[1,89]},{1:[2,185],6:[2,185],25:[2,185],26:[2,185],49:[2,185],54:[2,185],57:[2,185],72:[2,185],77:[2,185],85:[2,185],90:[2,185],92:[2,185],101:[2,185],102:87,103:[2,185],104:[2,185],105:[2,185],108:88,109:[2,185],110:69,117:[2,185],125:[2,185],127:[2,185],128:[2,185],131:[1,78],132:[2,185],133:[2,185],134:[2,185],135:[2,185],136:[2,185]},{1:[2,186],6:[2,186],25:[2,186],26:[2,186],49:[2,186],54:[2,186],57:[2,186],72:[2,186],77:[2,186],85:[2,186],90:[2,186],92:[2,186],101:[2,186],102:87,103:[2,186],104:[2,186],105:[2,186],108:88,109:[2,186],110:69,117:[2,186],125:[2,186],127:[2,186],128:[2,186],131:[1,78],132:[2,186],133:[2,186],134:[2,186],135:[2,186],136:[2,186]},{1:[2,187],6:[2,187],25:[2,187],26:[2,187],49:[2,187],54:[2,187],57:[2,187],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,187],73:[2,72],77:[2,187],83:[2,72],84:[2,72],85:[2,187],90:[2,187],92:[2,187],101:[2,187],103:[2,187],104:[2,187],105:[2,187],109:[2,187],117:[2,187],125:[2,187],127:[2,187],128:[2,187],131:[2,187],132:[2,187],133:[2,187],134:[2,187],135:[2,187],136:[2,187]},{62:93,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],73:[1,100],80:92,83:[1,94],84:[2,107]},{62:102,66:[1,95],67:[1,96],68:[1,97],69:98,70:[1,99],73:[1,100],80:101,83:[1,94],84:[2,107]},{66:[2,75],67:[2,75],68:[2,75],70:[2,75],73:[2,75],83:[2,75],84:[2,75]},{1:[2,188],6:[2,188],25:[2,188],26:[2,188],49:[2,188],54:[2,188],57:[2,188],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,188],73:[2,72],77:[2,188],83:[2,72],84:[2,72],85:[2,188],90:[2,188],92:[2,188],101:[2,188],103:[2,188],104:[2,188],105:[2,188],109:[2,188],117:[2,188],125:[2,188],127:[2,188],128:[2,188],131:[2,188],132:[2,188],133:[2,188],134:[2,188],135:[2,188],136:[2,188]},{1:[2,189],6:[2,189],25:[2,189],26:[2,189],49:[2,189],54:[2,189],57:[2,189],72:[2,189],77:[2,189],85:[2,189],90:[2,189],92:[2,189],101:[2,189],103:[2,189],104:[2,189],105:[2,189],109:[2,189],117:[2,189],125:[2,189],127:[2,189],128:[2,189],131:[2,189],132:[2,189],133:[2,189],134:[2,189],135:[2,189],136:[2,189]},{1:[2,190],6:[2,190],25:[2,190],26:[2,190],49:[2,190],54:[2,190],57:[2,190],72:[2,190],77:[2,190],85:[2,190],90:[2,190],92:[2,190],101:[2,190],103:[2,190],104:[2,190],105:[2,190],109:[2,190],117:[2,190],125:[2,190],127:[2,190],128:[2,190],131:[2,190],132:[2,190],133:[2,190],134:[2,190],135:[2,190],136:[2,190]},{8:206,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,207],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:208,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{5:209,25:[1,5],124:[1,210]},{1:[2,132],6:[2,132],25:[2,132],26:[2,132],49:[2,132],54:[2,132],57:[2,132],72:[2,132],77:[2,132],85:[2,132],90:[2,132],92:[2,132],96:211,97:[1,212],98:[1,213],101:[2,132],103:[2,132],104:[2,132],105:[2,132],109:[2,132],117:[2,132],125:[2,132],127:[2,132],128:[2,132],131:[2,132],132:[2,132],133:[2,132],134:[2,132],135:[2,132],136:[2,132]},{1:[2,144],6:[2,144],25:[2,144],26:[2,144],49:[2,144],54:[2,144],57:[2,144],72:[2,144],77:[2,144],85:[2,144],90:[2,144],92:[2,144],101:[2,144],103:[2,144],104:[2,144],105:[2,144],109:[2,144],117:[2,144],125:[2,144],127:[2,144],128:[2,144],131:[2,144],132:[2,144],133:[2,144],134:[2,144],135:[2,144],136:[2,144]},{1:[2,152],6:[2,152],25:[2,152],26:[2,152],49:[2,152],54:[2,152],57:[2,152],72:[2,152],77:[2,152],85:[2,152],90:[2,152],92:[2,152],101:[2,152],103:[2,152],104:[2,152],105:[2,152],109:[2,152],117:[2,152],125:[2,152],127:[2,152],128:[2,152],131:[2,152],132:[2,152],133:[2,152],134:[2,152],135:[2,152],136:[2,152]},{25:[1,214],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{119:215,121:216,122:[1,217]},{1:[2,96],6:[2,96],25:[2,96],26:[2,96],49:[2,96],54:[2,96],57:[2,96],72:[2,96],77:[2,96],85:[2,96],90:[2,96],92:[2,96],101:[2,96],103:[2,96],104:[2,96],105:[2,96],109:[2,96],117:[2,96],125:[2,96],127:[2,96],128:[2,96],131:[2,96],132:[2,96],133:[2,96],134:[2,96],135:[2,96],136:[2,96]},{8:218,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,99],5:219,6:[2,99],25:[1,5],26:[2,99],49:[2,99],54:[2,99],57:[2,99],66:[2,72],67:[2,72],68:[2,72],70:[2,72],72:[2,99],73:[2,72],77:[2,99],79:[1,220],83:[2,72],84:[2,72],85:[2,99],90:[2,99],92:[2,99],101:[2,99],103:[2,99],104:[2,99],105:[2,99],109:[2,99],117:[2,99],125:[2,99],127:[2,99],128:[2,99],131:[2,99],132:[2,99],133:[2,99],134:[2,99],135:[2,99],136:[2,99]},{1:[2,137],6:[2,137],25:[2,137],26:[2,137],49:[2,137],54:[2,137],57:[2,137],72:[2,137],77:[2,137],85:[2,137],90:[2,137],92:[2,137],101:[2,137],102:87,103:[2,137],104:[2,137],105:[2,137],108:88,109:[2,137],110:69,117:[2,137],125:[2,137],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,46],6:[2,46],26:[2,46],101:[2,46],102:87,103:[2,46],105:[2,46],108:88,109:[2,46],110:69,125:[2,46],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,74],101:[1,221]},{4:222,7:4,8:6,9:7,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,128],25:[2,128],54:[2,128],57:[1,224],90:[2,128],91:223,92:[1,191],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,114],6:[2,114],25:[2,114],26:[2,114],40:[2,114],49:[2,114],54:[2,114],57:[2,114],66:[2,114],67:[2,114],68:[2,114],70:[2,114],72:[2,114],73:[2,114],77:[2,114],83:[2,114],84:[2,114],85:[2,114],90:[2,114],92:[2,114],101:[2,114],103:[2,114],104:[2,114],105:[2,114],109:[2,114],115:[2,114],116:[2,114],117:[2,114],125:[2,114],127:[2,114],128:[2,114],131:[2,114],132:[2,114],133:[2,114],134:[2,114],135:[2,114],136:[2,114]},{6:[2,53],25:[2,53],53:225,54:[1,226],90:[2,53]},{6:[2,123],25:[2,123],26:[2,123],54:[2,123],85:[2,123],90:[2,123]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:227,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,129],25:[2,129],26:[2,129],54:[2,129],85:[2,129],90:[2,129]},{1:[2,113],6:[2,113],25:[2,113],26:[2,113],40:[2,113],43:[2,113],49:[2,113],54:[2,113],57:[2,113],66:[2,113],67:[2,113],68:[2,113],70:[2,113],72:[2,113],73:[2,113],77:[2,113],79:[2,113],83:[2,113],84:[2,113],85:[2,113],90:[2,113],92:[2,113],101:[2,113],103:[2,113],104:[2,113],105:[2,113],109:[2,113],115:[2,113],116:[2,113],117:[2,113],125:[2,113],127:[2,113],128:[2,113],129:[2,113],130:[2,113],131:[2,113],132:[2,113],133:[2,113],134:[2,113],135:[2,113],136:[2,113],137:[2,113]},{5:228,25:[1,5],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,140],6:[2,140],25:[2,140],26:[2,140],49:[2,140],54:[2,140],57:[2,140],72:[2,140],77:[2,140],85:[2,140],90:[2,140],92:[2,140],101:[2,140],102:87,103:[1,65],104:[1,229],105:[1,66],108:88,109:[1,68],110:69,117:[2,140],125:[2,140],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,142],6:[2,142],25:[2,142],26:[2,142],49:[2,142],54:[2,142],57:[2,142],72:[2,142],77:[2,142],85:[2,142],90:[2,142],92:[2,142],101:[2,142],102:87,103:[1,65],104:[1,230],105:[1,66],108:88,109:[1,68],110:69,117:[2,142],125:[2,142],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,148],6:[2,148],25:[2,148],26:[2,148],49:[2,148],54:[2,148],57:[2,148],72:[2,148],77:[2,148],85:[2,148],90:[2,148],92:[2,148],101:[2,148],103:[2,148],104:[2,148],105:[2,148],109:[2,148],117:[2,148],125:[2,148],127:[2,148],128:[2,148],131:[2,148],132:[2,148],133:[2,148],134:[2,148],135:[2,148],136:[2,148]},{1:[2,149],6:[2,149],25:[2,149],26:[2,149],49:[2,149],54:[2,149],57:[2,149],72:[2,149],77:[2,149],85:[2,149],90:[2,149],92:[2,149],101:[2,149],102:87,103:[1,65],104:[2,149],105:[1,66],108:88,109:[1,68],110:69,117:[2,149],125:[2,149],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,153],6:[2,153],25:[2,153],26:[2,153],49:[2,153],54:[2,153],57:[2,153],72:[2,153],77:[2,153],85:[2,153],90:[2,153],92:[2,153],101:[2,153],103:[2,153],104:[2,153],105:[2,153],109:[2,153],117:[2,153],125:[2,153],127:[2,153],128:[2,153],131:[2,153],132:[2,153],133:[2,153],134:[2,153],135:[2,153],136:[2,153]},{115:[2,155],116:[2,155]},{27:158,28:[1,73],44:159,58:160,59:161,75:[1,70],88:[1,113],89:[1,114],112:231,114:157},{54:[1,232],115:[2,161],116:[2,161]},{54:[2,157],115:[2,157],116:[2,157]},{54:[2,158],115:[2,158],116:[2,158]},{54:[2,159],115:[2,159],116:[2,159]},{54:[2,160],115:[2,160],116:[2,160]},{1:[2,154],6:[2,154],25:[2,154],26:[2,154],49:[2,154],54:[2,154],57:[2,154],72:[2,154],77:[2,154],85:[2,154],90:[2,154],92:[2,154],101:[2,154],103:[2,154],104:[2,154],105:[2,154],109:[2,154],117:[2,154],125:[2,154],127:[2,154],128:[2,154],131:[2,154],132:[2,154],133:[2,154],134:[2,154],135:[2,154],136:[2,154]},{8:233,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:234,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],53:235,54:[1,236],77:[2,53]},{6:[2,91],25:[2,91],26:[2,91],54:[2,91],77:[2,91]},{6:[2,39],25:[2,39],26:[2,39],43:[1,237],54:[2,39],77:[2,39]},{6:[2,42],25:[2,42],26:[2,42],54:[2,42],77:[2,42]},{6:[2,43],25:[2,43],26:[2,43],43:[2,43],54:[2,43],77:[2,43]},{6:[2,44],25:[2,44],26:[2,44],43:[2,44],54:[2,44],77:[2,44]},{6:[2,45],25:[2,45],26:[2,45],43:[2,45],54:[2,45],77:[2,45]},{1:[2,5],6:[2,5],26:[2,5],101:[2,5]},{1:[2,25],6:[2,25],25:[2,25],26:[2,25],49:[2,25],54:[2,25],57:[2,25],72:[2,25],77:[2,25],85:[2,25],90:[2,25],92:[2,25],97:[2,25],98:[2,25],101:[2,25],103:[2,25],104:[2,25],105:[2,25],109:[2,25],117:[2,25],120:[2,25],122:[2,25],125:[2,25],127:[2,25],128:[2,25],131:[2,25],132:[2,25],133:[2,25],134:[2,25],135:[2,25],136:[2,25]},{1:[2,192],6:[2,192],25:[2,192],26:[2,192],49:[2,192],54:[2,192],57:[2,192],72:[2,192],77:[2,192],85:[2,192],90:[2,192],92:[2,192],101:[2,192],102:87,103:[2,192],104:[2,192],105:[2,192],108:88,109:[2,192],110:69,117:[2,192],125:[2,192],127:[2,192],128:[2,192],131:[1,78],132:[1,81],133:[2,192],134:[2,192],135:[2,192],136:[2,192]},{1:[2,193],6:[2,193],25:[2,193],26:[2,193],49:[2,193],54:[2,193],57:[2,193],72:[2,193],77:[2,193],85:[2,193],90:[2,193],92:[2,193],101:[2,193],102:87,103:[2,193],104:[2,193],105:[2,193],108:88,109:[2,193],110:69,117:[2,193],125:[2,193],127:[2,193],128:[2,193],131:[1,78],132:[1,81],133:[2,193],134:[2,193],135:[2,193],136:[2,193]},{1:[2,194],6:[2,194],25:[2,194],26:[2,194],49:[2,194],54:[2,194],57:[2,194],72:[2,194],77:[2,194],85:[2,194],90:[2,194],92:[2,194],101:[2,194],102:87,103:[2,194],104:[2,194],105:[2,194],108:88,109:[2,194],110:69,117:[2,194],125:[2,194],127:[2,194],128:[2,194],131:[1,78],132:[2,194],133:[2,194],134:[2,194],135:[2,194],136:[2,194]},{1:[2,195],6:[2,195],25:[2,195],26:[2,195],49:[2,195],54:[2,195],57:[2,195],72:[2,195],77:[2,195],85:[2,195],90:[2,195],92:[2,195],101:[2,195],102:87,103:[2,195],104:[2,195],105:[2,195],108:88,109:[2,195],110:69,117:[2,195],125:[2,195],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[2,195],134:[2,195],135:[2,195],136:[2,195]},{1:[2,196],6:[2,196],25:[2,196],26:[2,196],49:[2,196],54:[2,196],57:[2,196],72:[2,196],77:[2,196],85:[2,196],90:[2,196],92:[2,196],101:[2,196],102:87,103:[2,196],104:[2,196],105:[2,196],108:88,109:[2,196],110:69,117:[2,196],125:[2,196],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[2,196],135:[2,196],136:[1,85]},{1:[2,197],6:[2,197],25:[2,197],26:[2,197],49:[2,197],54:[2,197],57:[2,197],72:[2,197],77:[2,197],85:[2,197],90:[2,197],92:[2,197],101:[2,197],102:87,103:[2,197],104:[2,197],105:[2,197],108:88,109:[2,197],110:69,117:[2,197],125:[2,197],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[2,197],136:[1,85]},{1:[2,198],6:[2,198],25:[2,198],26:[2,198],49:[2,198],54:[2,198],57:[2,198],72:[2,198],77:[2,198],85:[2,198],90:[2,198],92:[2,198],101:[2,198],102:87,103:[2,198],104:[2,198],105:[2,198],108:88,109:[2,198],110:69,117:[2,198],125:[2,198],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[2,198],135:[2,198],136:[2,198]},{1:[2,183],6:[2,183],25:[2,183],26:[2,183],49:[2,183],54:[2,183],57:[2,183],72:[2,183],77:[2,183],85:[2,183],90:[2,183],92:[2,183],101:[2,183],102:87,103:[1,65],104:[2,183],105:[1,66],108:88,109:[1,68],110:69,117:[2,183],125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,182],6:[2,182],25:[2,182],26:[2,182],49:[2,182],54:[2,182],57:[2,182],72:[2,182],77:[2,182],85:[2,182],90:[2,182],92:[2,182],101:[2,182],102:87,103:[1,65],104:[2,182],105:[1,66],108:88,109:[1,68],110:69,117:[2,182],125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,103],6:[2,103],25:[2,103],26:[2,103],49:[2,103],54:[2,103],57:[2,103],66:[2,103],67:[2,103],68:[2,103],70:[2,103],72:[2,103],73:[2,103],77:[2,103],83:[2,103],84:[2,103],85:[2,103],90:[2,103],92:[2,103],101:[2,103],103:[2,103],104:[2,103],105:[2,103],109:[2,103],117:[2,103],125:[2,103],127:[2,103],128:[2,103],131:[2,103],132:[2,103],133:[2,103],134:[2,103],135:[2,103],136:[2,103]},{1:[2,80],6:[2,80],25:[2,80],26:[2,80],40:[2,80],49:[2,80],54:[2,80],57:[2,80],66:[2,80],67:[2,80],68:[2,80],70:[2,80],72:[2,80],73:[2,80],77:[2,80],79:[2,80],83:[2,80],84:[2,80],85:[2,80],90:[2,80],92:[2,80],101:[2,80],103:[2,80],104:[2,80],105:[2,80],109:[2,80],117:[2,80],125:[2,80],127:[2,80],128:[2,80],129:[2,80],130:[2,80],131:[2,80],132:[2,80],133:[2,80],134:[2,80],135:[2,80],136:[2,80],137:[2,80]},{1:[2,81],6:[2,81],25:[2,81],26:[2,81],40:[2,81],49:[2,81],54:[2,81],57:[2,81],66:[2,81],67:[2,81],68:[2,81],70:[2,81],72:[2,81],73:[2,81],77:[2,81],79:[2,81],83:[2,81],84:[2,81],85:[2,81],90:[2,81],92:[2,81],101:[2,81],103:[2,81],104:[2,81],105:[2,81],109:[2,81],117:[2,81],125:[2,81],127:[2,81],128:[2,81],129:[2,81],130:[2,81],131:[2,81],132:[2,81],133:[2,81],134:[2,81],135:[2,81],136:[2,81],137:[2,81]},{1:[2,82],6:[2,82],25:[2,82],26:[2,82],40:[2,82],49:[2,82],54:[2,82],57:[2,82],66:[2,82],67:[2,82],68:[2,82],70:[2,82],72:[2,82],73:[2,82],77:[2,82],79:[2,82],83:[2,82],84:[2,82],85:[2,82],90:[2,82],92:[2,82],101:[2,82],103:[2,82],104:[2,82],105:[2,82],109:[2,82],117:[2,82],125:[2,82],127:[2,82],128:[2,82],129:[2,82],130:[2,82],131:[2,82],132:[2,82],133:[2,82],134:[2,82],135:[2,82],136:[2,82],137:[2,82]},{72:[1,238]},{57:[1,192],72:[2,87],91:239,92:[1,191],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{72:[2,88]},{8:240,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,72:[2,122],75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{12:[2,116],28:[2,116],30:[2,116],31:[2,116],33:[2,116],34:[2,116],35:[2,116],36:[2,116],37:[2,116],38:[2,116],45:[2,116],46:[2,116],47:[2,116],51:[2,116],52:[2,116],72:[2,116],75:[2,116],78:[2,116],82:[2,116],87:[2,116],88:[2,116],89:[2,116],95:[2,116],99:[2,116],100:[2,116],103:[2,116],105:[2,116],107:[2,116],109:[2,116],118:[2,116],124:[2,116],126:[2,116],127:[2,116],128:[2,116],129:[2,116],130:[2,116]},{12:[2,117],28:[2,117],30:[2,117],31:[2,117],33:[2,117],34:[2,117],35:[2,117],36:[2,117],37:[2,117],38:[2,117],45:[2,117],46:[2,117],47:[2,117],51:[2,117],52:[2,117],72:[2,117],75:[2,117],78:[2,117],82:[2,117],87:[2,117],88:[2,117],89:[2,117],95:[2,117],99:[2,117],100:[2,117],103:[2,117],105:[2,117],107:[2,117],109:[2,117],118:[2,117],124:[2,117],126:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117]},{1:[2,86],6:[2,86],25:[2,86],26:[2,86],40:[2,86],49:[2,86],54:[2,86],57:[2,86],66:[2,86],67:[2,86],68:[2,86],70:[2,86],72:[2,86],73:[2,86],77:[2,86],79:[2,86],83:[2,86],84:[2,86],85:[2,86],90:[2,86],92:[2,86],101:[2,86],103:[2,86],104:[2,86],105:[2,86],109:[2,86],117:[2,86],125:[2,86],127:[2,86],128:[2,86],129:[2,86],130:[2,86],131:[2,86],132:[2,86],133:[2,86],134:[2,86],135:[2,86],136:[2,86],137:[2,86]},{1:[2,104],6:[2,104],25:[2,104],26:[2,104],49:[2,104],54:[2,104],57:[2,104],66:[2,104],67:[2,104],68:[2,104],70:[2,104],72:[2,104],73:[2,104],77:[2,104],83:[2,104],84:[2,104],85:[2,104],90:[2,104],92:[2,104],101:[2,104],103:[2,104],104:[2,104],105:[2,104],109:[2,104],117:[2,104],125:[2,104],127:[2,104],128:[2,104],131:[2,104],132:[2,104],133:[2,104],134:[2,104],135:[2,104],136:[2,104]},{1:[2,36],6:[2,36],25:[2,36],26:[2,36],49:[2,36],54:[2,36],57:[2,36],72:[2,36],77:[2,36],85:[2,36],90:[2,36],92:[2,36],101:[2,36],102:87,103:[2,36],104:[2,36],105:[2,36],108:88,109:[2,36],110:69,117:[2,36],125:[2,36],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:241,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:242,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,109],6:[2,109],25:[2,109],26:[2,109],49:[2,109],54:[2,109],57:[2,109],66:[2,109],67:[2,109],68:[2,109],70:[2,109],72:[2,109],73:[2,109],77:[2,109],83:[2,109],84:[2,109],85:[2,109],90:[2,109],92:[2,109],101:[2,109],103:[2,109],104:[2,109],105:[2,109],109:[2,109],117:[2,109],125:[2,109],127:[2,109],128:[2,109],131:[2,109],132:[2,109],133:[2,109],134:[2,109],135:[2,109],136:[2,109]},{6:[2,53],25:[2,53],53:243,54:[1,226],85:[2,53]},{6:[2,128],25:[2,128],26:[2,128],54:[2,128],57:[1,244],85:[2,128],90:[2,128],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{50:245,51:[1,60],52:[1,61]},{6:[2,54],25:[2,54],26:[2,54],27:109,28:[1,73],44:110,55:246,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[1,247],25:[1,248]},{6:[2,61],25:[2,61],26:[2,61],49:[2,61],54:[2,61]},{8:249,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,199],6:[2,199],25:[2,199],26:[2,199],49:[2,199],54:[2,199],57:[2,199],72:[2,199],77:[2,199],85:[2,199],90:[2,199],92:[2,199],101:[2,199],102:87,103:[2,199],104:[2,199],105:[2,199],108:88,109:[2,199],110:69,117:[2,199],125:[2,199],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:250,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,201],6:[2,201],25:[2,201],26:[2,201],49:[2,201],54:[2,201],57:[2,201],72:[2,201],77:[2,201],85:[2,201],90:[2,201],92:[2,201],101:[2,201],102:87,103:[2,201],104:[2,201],105:[2,201],108:88,109:[2,201],110:69,117:[2,201],125:[2,201],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,181],6:[2,181],25:[2,181],26:[2,181],49:[2,181],54:[2,181],57:[2,181],72:[2,181],77:[2,181],85:[2,181],90:[2,181],92:[2,181],101:[2,181],103:[2,181],104:[2,181],105:[2,181],109:[2,181],117:[2,181],125:[2,181],127:[2,181],128:[2,181],131:[2,181],132:[2,181],133:[2,181],134:[2,181],135:[2,181],136:[2,181]},{8:251,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,133],6:[2,133],25:[2,133],26:[2,133],49:[2,133],54:[2,133],57:[2,133],72:[2,133],77:[2,133],85:[2,133],90:[2,133],92:[2,133],97:[1,252],101:[2,133],103:[2,133],104:[2,133],105:[2,133],109:[2,133],117:[2,133],125:[2,133],127:[2,133],128:[2,133],131:[2,133],132:[2,133],133:[2,133],134:[2,133],135:[2,133],136:[2,133]},{5:253,25:[1,5]},{27:254,28:[1,73]},{119:255,121:216,122:[1,217]},{26:[1,256],120:[1,257],121:258,122:[1,217]},{26:[2,174],120:[2,174],122:[2,174]},{8:260,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],94:259,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,97],5:261,6:[2,97],25:[1,5],26:[2,97],49:[2,97],54:[2,97],57:[2,97],72:[2,97],77:[2,97],85:[2,97],90:[2,97],92:[2,97],101:[2,97],102:87,103:[1,65],104:[2,97],105:[1,66],108:88,109:[1,68],110:69,117:[2,97],125:[2,97],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,100],6:[2,100],25:[2,100],26:[2,100],49:[2,100],54:[2,100],57:[2,100],72:[2,100],77:[2,100],85:[2,100],90:[2,100],92:[2,100],101:[2,100],103:[2,100],104:[2,100],105:[2,100],109:[2,100],117:[2,100],125:[2,100],127:[2,100],128:[2,100],131:[2,100],132:[2,100],133:[2,100],134:[2,100],135:[2,100],136:[2,100]},{8:262,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,138],6:[2,138],25:[2,138],26:[2,138],49:[2,138],54:[2,138],57:[2,138],66:[2,138],67:[2,138],68:[2,138],70:[2,138],72:[2,138],73:[2,138],77:[2,138],83:[2,138],84:[2,138],85:[2,138],90:[2,138],92:[2,138],101:[2,138],103:[2,138],104:[2,138],105:[2,138],109:[2,138],117:[2,138],125:[2,138],127:[2,138],128:[2,138],131:[2,138],132:[2,138],133:[2,138],134:[2,138],135:[2,138],136:[2,138]},{6:[1,74],26:[1,263]},{8:264,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,67],12:[2,117],25:[2,67],28:[2,117],30:[2,117],31:[2,117],33:[2,117],34:[2,117],35:[2,117],36:[2,117],37:[2,117],38:[2,117],45:[2,117],46:[2,117],47:[2,117],51:[2,117],52:[2,117],54:[2,67],75:[2,117],78:[2,117],82:[2,117],87:[2,117],88:[2,117],89:[2,117],90:[2,67],95:[2,117],99:[2,117],100:[2,117],103:[2,117],105:[2,117],107:[2,117],109:[2,117],118:[2,117],124:[2,117],126:[2,117],127:[2,117],128:[2,117],129:[2,117],130:[2,117]},{6:[1,266],25:[1,267],90:[1,265]},{6:[2,54],8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[2,54],26:[2,54],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],85:[2,54],87:[1,58],88:[1,59],89:[1,57],90:[2,54],93:268,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,53],25:[2,53],26:[2,53],53:269,54:[1,226]},{1:[2,178],6:[2,178],25:[2,178],26:[2,178],49:[2,178],54:[2,178],57:[2,178],72:[2,178],77:[2,178],85:[2,178],90:[2,178],92:[2,178],101:[2,178],103:[2,178],104:[2,178],105:[2,178],109:[2,178],117:[2,178],120:[2,178],125:[2,178],127:[2,178],128:[2,178],131:[2,178],132:[2,178],133:[2,178],134:[2,178],135:[2,178],136:[2,178]},{8:270,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:271,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{115:[2,156],116:[2,156]},{27:158,28:[1,73],44:159,58:160,59:161,75:[1,70],88:[1,113],89:[1,114],114:272},{1:[2,163],6:[2,163],25:[2,163],26:[2,163],49:[2,163],54:[2,163],57:[2,163],72:[2,163],77:[2,163],85:[2,163],90:[2,163],92:[2,163],101:[2,163],102:87,103:[2,163],104:[1,273],105:[2,163],108:88,109:[2,163],110:69,117:[1,274],125:[2,163],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,164],6:[2,164],25:[2,164],26:[2,164],49:[2,164],54:[2,164],57:[2,164],72:[2,164],77:[2,164],85:[2,164],90:[2,164],92:[2,164],101:[2,164],102:87,103:[2,164],104:[1,275],105:[2,164],108:88,109:[2,164],110:69,117:[2,164],125:[2,164],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,277],25:[1,278],77:[1,276]},{6:[2,54],11:168,25:[2,54],26:[2,54],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:279,42:167,44:171,46:[1,46],77:[2,54],88:[1,113]},{8:280,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,281],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,85],6:[2,85],25:[2,85],26:[2,85],40:[2,85],49:[2,85],54:[2,85],57:[2,85],66:[2,85],67:[2,85],68:[2,85],70:[2,85],72:[2,85],73:[2,85],77:[2,85],79:[2,85],83:[2,85],84:[2,85],85:[2,85],90:[2,85],92:[2,85],101:[2,85],103:[2,85],104:[2,85],105:[2,85],109:[2,85],117:[2,85],125:[2,85],127:[2,85],128:[2,85],129:[2,85],130:[2,85],131:[2,85],132:[2,85],133:[2,85],134:[2,85],135:[2,85],136:[2,85],137:[2,85]},{8:282,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,72:[2,120],75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{72:[2,121],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,37],6:[2,37],25:[2,37],26:[2,37],49:[2,37],54:[2,37],57:[2,37],72:[2,37],77:[2,37],85:[2,37],90:[2,37],92:[2,37],101:[2,37],102:87,103:[2,37],104:[2,37],105:[2,37],108:88,109:[2,37],110:69,117:[2,37],125:[2,37],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{26:[1,283],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,266],25:[1,267],85:[1,284]},{6:[2,67],25:[2,67],26:[2,67],54:[2,67],85:[2,67],90:[2,67]},{5:285,25:[1,5]},{6:[2,57],25:[2,57],26:[2,57],49:[2,57],54:[2,57]},{27:109,28:[1,73],44:110,55:286,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[2,55],25:[2,55],26:[2,55],27:109,28:[1,73],44:110,48:287,54:[2,55],55:107,56:108,58:111,59:112,75:[1,70],88:[1,113],89:[1,114]},{6:[2,62],25:[2,62],26:[2,62],49:[2,62],54:[2,62],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{26:[1,288],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{5:289,25:[1,5],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{5:290,25:[1,5]},{1:[2,134],6:[2,134],25:[2,134],26:[2,134],49:[2,134],54:[2,134],57:[2,134],72:[2,134],77:[2,134],85:[2,134],90:[2,134],92:[2,134],101:[2,134],103:[2,134],104:[2,134],105:[2,134],109:[2,134],117:[2,134],125:[2,134],127:[2,134],128:[2,134],131:[2,134],132:[2,134],133:[2,134],134:[2,134],135:[2,134],136:[2,134]},{5:291,25:[1,5]},{26:[1,292],120:[1,293],121:258,122:[1,217]},{1:[2,172],6:[2,172],25:[2,172],26:[2,172],49:[2,172],54:[2,172],57:[2,172],72:[2,172],77:[2,172],85:[2,172],90:[2,172],92:[2,172],101:[2,172],103:[2,172],104:[2,172],105:[2,172],109:[2,172],117:[2,172],125:[2,172],127:[2,172],128:[2,172],131:[2,172],132:[2,172],133:[2,172],134:[2,172],135:[2,172],136:[2,172]},{5:294,25:[1,5]},{26:[2,175],120:[2,175],122:[2,175]},{5:295,25:[1,5],54:[1,296]},{25:[2,130],54:[2,130],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,98],6:[2,98],25:[2,98],26:[2,98],49:[2,98],54:[2,98],57:[2,98],72:[2,98],77:[2,98],85:[2,98],90:[2,98],92:[2,98],101:[2,98],103:[2,98],104:[2,98],105:[2,98],109:[2,98],117:[2,98],125:[2,98],127:[2,98],128:[2,98],131:[2,98],132:[2,98],133:[2,98],134:[2,98],135:[2,98],136:[2,98]},{1:[2,101],5:297,6:[2,101],25:[1,5],26:[2,101],49:[2,101],54:[2,101],57:[2,101],72:[2,101],77:[2,101],85:[2,101],90:[2,101],92:[2,101],101:[2,101],102:87,103:[1,65],104:[2,101],105:[1,66],108:88,109:[1,68],110:69,117:[2,101],125:[2,101],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{101:[1,298]},{90:[1,299],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,115],6:[2,115],25:[2,115],26:[2,115],40:[2,115],49:[2,115],54:[2,115],57:[2,115],66:[2,115],67:[2,115],68:[2,115],70:[2,115],72:[2,115],73:[2,115],77:[2,115],83:[2,115],84:[2,115],85:[2,115],90:[2,115],92:[2,115],101:[2,115],103:[2,115],104:[2,115],105:[2,115],109:[2,115],115:[2,115],116:[2,115],117:[2,115],125:[2,115],127:[2,115],128:[2,115],131:[2,115],132:[2,115],133:[2,115],134:[2,115],135:[2,115],136:[2,115]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],93:300,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:200,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,25:[1,146],27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,60:147,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],86:301,87:[1,58],88:[1,59],89:[1,57],93:145,95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[2,124],25:[2,124],26:[2,124],54:[2,124],85:[2,124],90:[2,124]},{6:[1,266],25:[1,267],26:[1,302]},{1:[2,141],6:[2,141],25:[2,141],26:[2,141],49:[2,141],54:[2,141],57:[2,141],72:[2,141],77:[2,141],85:[2,141],90:[2,141],92:[2,141],101:[2,141],102:87,103:[1,65],104:[2,141],105:[1,66],108:88,109:[1,68],110:69,117:[2,141],125:[2,141],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,143],6:[2,143],25:[2,143],26:[2,143],49:[2,143],54:[2,143],57:[2,143],72:[2,143],77:[2,143],85:[2,143],90:[2,143],92:[2,143],101:[2,143],102:87,103:[1,65],104:[2,143],105:[1,66],108:88,109:[1,68],110:69,117:[2,143],125:[2,143],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{115:[2,162],116:[2,162]},{8:303,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:304,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:305,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,89],6:[2,89],25:[2,89],26:[2,89],40:[2,89],49:[2,89],54:[2,89],57:[2,89],66:[2,89],67:[2,89],68:[2,89],70:[2,89],72:[2,89],73:[2,89],77:[2,89],83:[2,89],84:[2,89],85:[2,89],90:[2,89],92:[2,89],101:[2,89],103:[2,89],104:[2,89],105:[2,89],109:[2,89],115:[2,89],116:[2,89],117:[2,89],125:[2,89],127:[2,89],128:[2,89],131:[2,89],132:[2,89],133:[2,89],134:[2,89],135:[2,89],136:[2,89]},{11:168,27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:306,42:167,44:171,46:[1,46],88:[1,113]},{6:[2,90],11:168,25:[2,90],26:[2,90],27:169,28:[1,73],29:170,30:[1,71],31:[1,72],41:166,42:167,44:171,46:[1,46],54:[2,90],76:307,88:[1,113]},{6:[2,92],25:[2,92],26:[2,92],54:[2,92],77:[2,92]},{6:[2,40],25:[2,40],26:[2,40],54:[2,40],77:[2,40],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{8:308,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{72:[2,119],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,38],6:[2,38],25:[2,38],26:[2,38],49:[2,38],54:[2,38],57:[2,38],72:[2,38],77:[2,38],85:[2,38],90:[2,38],92:[2,38],101:[2,38],103:[2,38],104:[2,38],105:[2,38],109:[2,38],117:[2,38],125:[2,38],127:[2,38],128:[2,38],131:[2,38],132:[2,38],133:[2,38],134:[2,38],135:[2,38],136:[2,38]},{1:[2,110],6:[2,110],25:[2,110],26:[2,110],49:[2,110],54:[2,110],57:[2,110],66:[2,110],67:[2,110],68:[2,110],70:[2,110],72:[2,110],73:[2,110],77:[2,110],83:[2,110],84:[2,110],85:[2,110],90:[2,110],92:[2,110],101:[2,110],103:[2,110],104:[2,110],105:[2,110],109:[2,110],117:[2,110],125:[2,110],127:[2,110],128:[2,110],131:[2,110],132:[2,110],133:[2,110],134:[2,110],135:[2,110],136:[2,110]},{1:[2,49],6:[2,49],25:[2,49],26:[2,49],49:[2,49],54:[2,49],57:[2,49],72:[2,49],77:[2,49],85:[2,49],90:[2,49],92:[2,49],101:[2,49],103:[2,49],104:[2,49],105:[2,49],109:[2,49],117:[2,49],125:[2,49],127:[2,49],128:[2,49],131:[2,49],132:[2,49],133:[2,49],134:[2,49],135:[2,49],136:[2,49]},{6:[2,58],25:[2,58],26:[2,58],49:[2,58],54:[2,58]},{6:[2,53],25:[2,53],26:[2,53],53:309,54:[1,202]},{1:[2,200],6:[2,200],25:[2,200],26:[2,200],49:[2,200],54:[2,200],57:[2,200],72:[2,200],77:[2,200],85:[2,200],90:[2,200],92:[2,200],101:[2,200],103:[2,200],104:[2,200],105:[2,200],109:[2,200],117:[2,200],125:[2,200],127:[2,200],128:[2,200],131:[2,200],132:[2,200],133:[2,200],134:[2,200],135:[2,200],136:[2,200]},{1:[2,179],6:[2,179],25:[2,179],26:[2,179],49:[2,179],54:[2,179],57:[2,179],72:[2,179],77:[2,179],85:[2,179],90:[2,179],92:[2,179],101:[2,179],103:[2,179],104:[2,179],105:[2,179],109:[2,179],117:[2,179],120:[2,179],125:[2,179],127:[2,179],128:[2,179],131:[2,179],132:[2,179],133:[2,179],134:[2,179],135:[2,179],136:[2,179]},{1:[2,135],6:[2,135],25:[2,135],26:[2,135],49:[2,135],54:[2,135],57:[2,135],72:[2,135],77:[2,135],85:[2,135],90:[2,135],92:[2,135],101:[2,135],103:[2,135],104:[2,135],105:[2,135],109:[2,135],117:[2,135],125:[2,135],127:[2,135],128:[2,135],131:[2,135],132:[2,135],133:[2,135],134:[2,135],135:[2,135],136:[2,135]},{1:[2,136],6:[2,136],25:[2,136],26:[2,136],49:[2,136],54:[2,136],57:[2,136],72:[2,136],77:[2,136],85:[2,136],90:[2,136],92:[2,136],97:[2,136],101:[2,136],103:[2,136],104:[2,136],105:[2,136],109:[2,136],117:[2,136],125:[2,136],127:[2,136],128:[2,136],131:[2,136],132:[2,136],133:[2,136],134:[2,136],135:[2,136],136:[2,136]},{1:[2,170],6:[2,170],25:[2,170],26:[2,170],49:[2,170],54:[2,170],57:[2,170],72:[2,170],77:[2,170],85:[2,170],90:[2,170],92:[2,170],101:[2,170],103:[2,170],104:[2,170],105:[2,170],109:[2,170],117:[2,170],125:[2,170],127:[2,170],128:[2,170],131:[2,170],132:[2,170],133:[2,170],134:[2,170],135:[2,170],136:[2,170]},{5:310,25:[1,5]},{26:[1,311]},{6:[1,312],26:[2,176],120:[2,176],122:[2,176]},{8:313,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{1:[2,102],6:[2,102],25:[2,102],26:[2,102],49:[2,102],54:[2,102],57:[2,102],72:[2,102],77:[2,102],85:[2,102],90:[2,102],92:[2,102],101:[2,102],103:[2,102],104:[2,102],105:[2,102],109:[2,102],117:[2,102],125:[2,102],127:[2,102],128:[2,102],131:[2,102],132:[2,102],133:[2,102],134:[2,102],135:[2,102],136:[2,102]},{1:[2,139],6:[2,139],25:[2,139],26:[2,139],49:[2,139],54:[2,139],57:[2,139],66:[2,139],67:[2,139],68:[2,139],70:[2,139],72:[2,139],73:[2,139],77:[2,139],83:[2,139],84:[2,139],85:[2,139],90:[2,139],92:[2,139],101:[2,139],103:[2,139],104:[2,139],105:[2,139],109:[2,139],117:[2,139],125:[2,139],127:[2,139],128:[2,139],131:[2,139],132:[2,139],133:[2,139],134:[2,139],135:[2,139],136:[2,139]},{1:[2,118],6:[2,118],25:[2,118],26:[2,118],49:[2,118],54:[2,118],57:[2,118],66:[2,118],67:[2,118],68:[2,118],70:[2,118],72:[2,118],73:[2,118],77:[2,118],83:[2,118],84:[2,118],85:[2,118],90:[2,118],92:[2,118],101:[2,118],103:[2,118],104:[2,118],105:[2,118],109:[2,118],117:[2,118],125:[2,118],127:[2,118],128:[2,118],131:[2,118],132:[2,118],133:[2,118],134:[2,118],135:[2,118],136:[2,118]},{6:[2,125],25:[2,125],26:[2,125],54:[2,125],85:[2,125],90:[2,125]},{6:[2,53],25:[2,53],26:[2,53],53:314,54:[1,226]},{6:[2,126],25:[2,126],26:[2,126],54:[2,126],85:[2,126],90:[2,126]},{1:[2,165],6:[2,165],25:[2,165],26:[2,165],49:[2,165],54:[2,165],57:[2,165],72:[2,165],77:[2,165],85:[2,165],90:[2,165],92:[2,165],101:[2,165],102:87,103:[2,165],104:[2,165],105:[2,165],108:88,109:[2,165],110:69,117:[1,315],125:[2,165],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,167],6:[2,167],25:[2,167],26:[2,167],49:[2,167],54:[2,167],57:[2,167],72:[2,167],77:[2,167],85:[2,167],90:[2,167],92:[2,167],101:[2,167],102:87,103:[2,167],104:[1,316],105:[2,167],108:88,109:[2,167],110:69,117:[2,167],125:[2,167],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,166],6:[2,166],25:[2,166],26:[2,166],49:[2,166],54:[2,166],57:[2,166],72:[2,166],77:[2,166],85:[2,166],90:[2,166],92:[2,166],101:[2,166],102:87,103:[2,166],104:[2,166],105:[2,166],108:88,109:[2,166],110:69,117:[2,166],125:[2,166],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[2,93],25:[2,93],26:[2,93],54:[2,93],77:[2,93]},{6:[2,53],25:[2,53],26:[2,53],53:317,54:[1,236]},{26:[1,318],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,247],25:[1,248],26:[1,319]},{26:[1,320]},{1:[2,173],6:[2,173],25:[2,173],26:[2,173],49:[2,173],54:[2,173],57:[2,173],72:[2,173],77:[2,173],85:[2,173],90:[2,173],92:[2,173],101:[2,173],103:[2,173],104:[2,173],105:[2,173],109:[2,173],117:[2,173],125:[2,173],127:[2,173],128:[2,173],131:[2,173],132:[2,173],133:[2,173],134:[2,173],135:[2,173],136:[2,173]},{26:[2,177],120:[2,177],122:[2,177]},{25:[2,131],54:[2,131],102:87,103:[1,65],105:[1,66],108:88,109:[1,68],110:69,125:[1,86],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[1,266],25:[1,267],26:[1,321]},{8:322,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{8:323,9:117,10:20,11:21,12:[1,22],13:8,14:9,15:10,16:11,17:12,18:13,19:14,20:15,21:16,22:17,23:18,24:19,27:62,28:[1,73],29:49,30:[1,71],31:[1,72],32:24,33:[1,50],34:[1,51],35:[1,52],36:[1,53],37:[1,54],38:[1,55],39:23,44:63,45:[1,45],46:[1,46],47:[1,29],50:30,51:[1,60],52:[1,61],58:47,59:48,61:36,63:25,64:26,65:27,75:[1,70],78:[1,43],82:[1,28],87:[1,58],88:[1,59],89:[1,57],95:[1,38],99:[1,44],100:[1,56],102:39,103:[1,65],105:[1,66],106:40,107:[1,67],108:41,109:[1,68],110:69,118:[1,42],123:37,124:[1,64],126:[1,31],127:[1,32],128:[1,33],129:[1,34],130:[1,35]},{6:[1,277],25:[1,278],26:[1,324]},{6:[2,41],25:[2,41],26:[2,41],54:[2,41],77:[2,41]},{6:[2,59],25:[2,59],26:[2,59],49:[2,59],54:[2,59]},{1:[2,171],6:[2,171],25:[2,171],26:[2,171],49:[2,171],54:[2,171],57:[2,171],72:[2,171],77:[2,171],85:[2,171],90:[2,171],92:[2,171],101:[2,171],103:[2,171],104:[2,171],105:[2,171],109:[2,171],117:[2,171],125:[2,171],127:[2,171],128:[2,171],131:[2,171],132:[2,171],133:[2,171],134:[2,171],135:[2,171],136:[2,171]},{6:[2,127],25:[2,127],26:[2,127],54:[2,127],85:[2,127],90:[2,127]},{1:[2,168],6:[2,168],25:[2,168],26:[2,168],49:[2,168],54:[2,168],57:[2,168],72:[2,168],77:[2,168],85:[2,168],90:[2,168],92:[2,168],101:[2,168],102:87,103:[2,168],104:[2,168],105:[2,168],108:88,109:[2,168],110:69,117:[2,168],125:[2,168],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{1:[2,169],6:[2,169],25:[2,169],26:[2,169],49:[2,169],54:[2,169],57:[2,169],72:[2,169],77:[2,169],85:[2,169],90:[2,169],92:[2,169],101:[2,169],102:87,103:[2,169],104:[2,169],105:[2,169],108:88,109:[2,169],110:69,117:[2,169],125:[2,169],127:[1,80],128:[1,79],131:[1,78],132:[1,81],133:[1,82],134:[1,83],135:[1,84],136:[1,85]},{6:[2,94],25:[2,94],26:[2,94],54:[2,94],77:[2,94]}],defaultActions:{60:[2,51],61:[2,52],75:[2,3],94:[2,108],189:[2,88]},parseError:function(b,c){throw new Error(b)},parse:function(b){function o(a){d.length=d.length-2*a,e.length=e.length-a,f.length=f.length-a}function p(){var a;return a=c.lexer.lex()||1,typeof a!="number"&&(a=c.symbols_[a]||a),a}var c=this,d=[0],e=[null],f=[],g=this.table,h="",i=0,j=0,k=0,l=2,m=1;this.lexer.setInput(b),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,typeof this.lexer.yylloc=="undefined"&&(this.lexer.yylloc={});var n=this.lexer.yylloc;f.push(n),typeof this.yy.parseError=="function"&&(this.parseError=this.yy.parseError);var q,r,s,t,u,v,w={},x,y,z,A;for(;;){s=d[d.length-1],this.defaultActions[s]?t=this.defaultActions[s]:(q==null&&(q=p()),t=g[s]&&g[s][q]);if(typeof t=="undefined"||!t.length||!t[0]){if(!k){A=[];for(x in g[s])this.terminals_[x]&&x>2&&A.push("'"+this.terminals_[x]+"'");var B="";this.lexer.showPosition?B="Parse error on line "+(i+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+A.join(", ")+", got '"+this.terminals_[q]+"'":B="Parse error on line "+(i+1)+": Unexpected "+(q==1?"end of input":"'"+(this.terminals_[q]||q)+"'"),this.parseError(B,{text:this.lexer.match,token:this.terminals_[q]||q,line:this.lexer.yylineno,loc:n,expected:A})}if(k==3){if(q==m)throw new Error(B||"Parsing halted.");j=this.lexer.yyleng,h=this.lexer.yytext,i=this.lexer.yylineno,n=this.lexer.yylloc,q=p()}for(;;){if(l.toString()in g[s])break;if(s==0)throw new Error(B||"Parsing halted.");o(1),s=d[d.length-1]}r=q,q=l,s=d[d.length-1],t=g[s]&&g[s][l],k=3}if(t[0]instanceof Array&&t.length>1)throw new Error("Parse Error: multiple actions possible at state: "+s+", token: "+q);switch(t[0]){case 1:d.push(q),e.push(this.lexer.yytext),f.push(this.lexer.yylloc),d.push(t[1]),q=null,r?(q=r,r=null):(j=this.lexer.yyleng,h=this.lexer.yytext,i=this.lexer.yylineno,n=this.lexer.yylloc,k>0&&k--);break;case 2:y=this.productions_[t[1]][1],w.$=e[e.length-y],w._$={first_line:f[f.length-(y||1)].first_line,last_line:f[f.length-1].last_line,first_column:f[f.length-(y||1)].first_column,last_column:f[f.length-1].last_column},v=this.performAction.call(w,h,j,i,this.yy,t[1],e,f);if(typeof v!="undefined")return v;y&&(d=d.slice(0,-1*y*2),e=e.slice(0,-1*y),f=f.slice(0,-1*y)),d.push(this.productions_[t[1]][0]),e.push(w.$),f.push(w._$),z=g[d[d.length-2]][d[d.length-1]],d.push(z);break;case 3:return!0}}return!0}};return undefined,a}();typeof require!="undefined"&&typeof a!="undefined"&&(a.parser=b,a.parse=function(){return b.parse.apply(b,arguments)},a.main=function(c){if(!c[1])throw new Error("Usage: "+c[0]+" FILE");if(typeof process!="undefined")var d=require("fs").readFileSync(require("path").join(process.cwd(),c[1]),"utf8");else var e=require("file").path(require("file").cwd()),d=e.join(c[1]).read({charset:"utf-8"});return a.parser.parse(d)},typeof module!="undefined"&&require.main===module&&a.main(typeof process!="undefined"?process.argv.slice(1):require("system").args))},require["./scope"]=new function(){var a=this;((function(){var b,c,d,e;e=require("./helpers"),c=e.extend,d=e.last,a.Scope=b=function(){function a(b,c,d){this.parent=b,this.expressions=c,this.method=d,this.variables=[{name:"arguments",type:"arguments"}],this.positions={},this.parent||(a.root=this)}return a.root=null,a.prototype.add=function(a,b,c){return this.shared&&!c?this.parent.add(a,b,c):Object.prototype.hasOwnProperty.call(this.positions,a)?this.variables[this.positions[a]].type=b:this.positions[a]=this.variables.push({name:a,type:b})-1},a.prototype.namedMethod=function(){return this.method.name||!this.parent?this.method:this.parent.namedMethod()},a.prototype.find=function(a){return this.check(a)?!0:(this.add(a,"var"),!1)},a.prototype.parameter=function(a){if(this.shared&&this.parent.check(a,!0))return;return this.add(a,"param")},a.prototype.check=function(a){var b;return!!(this.type(a)||((b=this.parent)!=null?b.check(a):void 0))},a.prototype.temporary=function(a,b){return a.length>1?"_"+a+(b>1?b-1:""):"_"+(b+parseInt(a,36)).toString(36).replace(/\d/g,"a")},a.prototype.type=function(a){var b,c,d,e;e=this.variables;for(c=0,d=e.length;c1&&a.level>=w?"("+c+")":c)},b.prototype.compileRoot=function(a){var b,c,d,e,f,g;return a.indent=a.bare?"":R,a.scope=new N(null,this,null),a.level=z,this.spaced=!0,e="",a.bare||(f=function(){var a,b,e,f;e=this.expressions,f=[];for(d=a=0,b=e.length;a=u?"(void 0)":"void 0"},b}(e),a.Null=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return bm(b,a),b.prototype.isAssignable=D,b.prototype.isComplex=D,b.prototype.compileNode=function(){return"null"},b}(e),a.Bool=function(a){function b(a){this.val=a}return bm(b,a),b.prototype.isAssignable=D,b.prototype.isComplex=D,b.prototype.compileNode=function(){return this.val},b}(e),a.Return=K=function(a){function b(a){a&&!a.unwrap().isUndefined&&(this.expression=a)}return bm(b,a),b.prototype.children=["expression"],b.prototype.isStatement=Y,b.prototype.makeReturn=S,b.prototype.jumps=S,b.prototype.compile=function(a,c){var d,e;return d=(e=this.expression)!=null?e.makeReturn():void 0,!d||d instanceof b?b.__super__.compile.call(this,a,c):d.compile(a,c)},b.prototype.compileNode=function(a){return this.tab+("return"+[this.expression?" "+this.expression.compile(a,y):void 0]+";")},b}(e),a.Value=W=function(a){function b(a,c,d){return!c&&a instanceof b?a:(this.base=a,this.properties=c||[],d&&(this[d]=!0),this)}return bm(b,a),b.prototype.children=["base","properties"],b.prototype.add=function(a){return this.properties=this.properties.concat(a),this},b.prototype.hasProperties=function(){return!!this.properties.length},b.prototype.isArray=function(){return!this.properties.length&&this.base instanceof c},b.prototype.isComplex=function(){return this.hasProperties()||this.base.isComplex()},b.prototype.isAssignable=function(){return this.hasProperties()||this.base.isAssignable()},b.prototype.isSimpleNumber=function(){return this.base instanceof A&&L.test(this.base.value)},b.prototype.isString=function(){return this.base instanceof A&&q.test(this.base.value)},b.prototype.isAtomic=function(){var a,b,c,d;d=this.properties.concat(this.base);for(b=0,c=d.length;b"+this.equals],i=n[0],e=n[1],c=this.stepNum?+this.stepNum>0?""+i+" "+this.toVar:""+e+" "+this.toVar:h?(o=[+this.fromNum,+this.toNum],d=o[0],l=o[1],o,d<=l?""+i+" "+l:""+e+" "+l):(b=""+this.fromVar+" <= "+this.toVar,""+b+" ? "+i+" "+this.toVar+" : "+e+" "+this.toVar),k=this.stepVar?""+f+" += "+this.stepVar:h?j?d<=l?"++"+f:"--"+f:d<=l?""+f+"++":""+f+"--":j?""+b+" ? ++"+f+" : --"+f:""+b+" ? "+f+"++ : "+f+"--",j&&(m=""+g+" = "+m),j&&(k=""+g+" = "+k),""+m+"; "+c+"; "+k):this.compileArray(a)},b.prototype.compileArray=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p;if(this.fromNum&&this.toNum&&Math.abs(this.fromNum-this.toNum)<=20)return j=function(){p=[];for(var a=n=+this.fromNum,b=+this.toNum;n<=b?a<=b:a>=b;n<=b?a++:a--)p.push(a);return p}.apply(this),this.exclusive&&j.pop(),"["+j.join(", ")+"]";g=this.tab+R,f=a.scope.freeVariable("i"),k=a.scope.freeVariable("results"),i="\n"+g+k+" = [];",this.fromNum&&this.toNum?(a.index=f,c=this.compileNode(a)):(l=""+f+" = "+this.fromC+(this.toC!==this.toVar?", "+this.toC:""),d=""+this.fromVar+" <= "+this.toVar,c="var "+l+"; "+d+" ? "+f+" <"+this.equals+" "+this.toVar+" : "+f+" >"+this.equals+" "+this.toVar+"; "+d+" ? "+f+"++ : "+f+"--"),h="{ "+k+".push("+f+"); }\n"+g+"return "+k+";\n"+a.indent,e=function(a){return a!=null?a.contains(function(a){return a instanceof A&&a.value==="arguments"&&!a.asKey}):void 0};if(e(this.from)||e(this.to))b=", arguments";return"(function() {"+i+"\n"+g+"for ("+c+")"+h+"}).apply(this"+(b!=null?b:"")+")"},b}(e),a.Slice=O=function(a){function b(a){this.range=a,b.__super__.constructor.call(this)}return bm(b,a),b.prototype.children=["range"],b.prototype.compileNode=function(a){var b,c,d,e,f,g;return g=this.range,e=g.to,c=g.from,d=c&&c.compile(a,y)||"0",b=e&&e.compile(a,y),e&&(!!this.range.exclusive||+b!==-1)&&(f=", "+(this.range.exclusive?b:L.test(b)?""+(+b+1):(b=e.compile(a,u),"+"+b+" + 1 || 9e9"))),".slice("+d+(f||"")+")"},b}(e),a.Obj=E=function(a){function b(a,b){this.generated=b!=null?b:!1,this.objects=this.properties=a||[]}return bm(b,a),b.prototype.children=["properties"],b.prototype.compileNode=function(a){var b,c,e,f,g,h,i,j,l,m,n;l=this.properties;if(!l.length)return this.front?"({})":"{}";if(this.generated)for(m=0,n=l.length;m=0?"[\n"+a.indent+b+"\n"+this.tab+"]":"["+b+"]")):"[]"},b.prototype.assigns=function(a){var b,c,d,e;e=this.objects;for(c=0,d=e.length;c=0)throw SyntaxError("variable name may not be "+a);return a&&(a=o.test(a)&&a)},c.prototype.setContext=function(a){return this.body.traverseChildren(!1,function(b){if(b.classBody)return!1;if(b instanceof A&&b.value==="this")return b.value=a;if(b instanceof j){b.klass=a;if(b.bound)return b.context=a}})},c.prototype.addBoundFunctions=function(a){var c,d,e,f,g,h;if(this.boundFuncs.length){g=this.boundFuncs,h=[];for(e=0,f=g.length;e=0);if(e&&this.context!=="object")throw SyntaxError('variable name may not be "'+f+'"')}return bm(c,a),c.prototype.children=["variable","value"],c.prototype.isStatement=function(a){return(a!=null?a.level:void 0)===z&&this.context!=null&&bn.call(this.context,"?")>=0},c.prototype.assigns=function(a){return this[this.context==="object"?"value":"variable"].assigns(a)},c.prototype.unfoldSoak=function(a){return bh(a,this,"variable")},c.prototype.compileNode=function(a){var b,c,d,e,f,g,h,i,k;if(b=this.variable instanceof W){if(this.variable.isArray()||this.variable.isObject())return this.compilePatternMatch(a);if(this.variable.isSplice())return this.compileSplice(a);if((g=this.context)==="||="||g==="&&="||g==="?=")return this.compileConditional(a)}d=this.variable.compile(a,w);if(!this.context){if(!(f=this.variable.unwrapAll()).isAssignable())throw SyntaxError('"'+this.variable.compile(a)+'" cannot be assigned.');if(typeof f.hasProperties=="function"?!f.hasProperties():!void 0)this.param?a.scope.add(d,"var"):a.scope.find(d)}return this.value instanceof j&&(c=B.exec(d))&&(c[1]&&(this.value.klass=c[1]),this.value.name=(h=(i=(k=c[2])!=null?k:c[3])!=null?i:c[4])!=null?h:c[5]),e=this.value.compile(a,w),this.context==="object"?""+d+": "+e:(e=d+(" "+(this.context||"=")+" ")+e,a.level<=w?e:"("+e+")")},c.prototype.compilePatternMatch=function(a){var d,e,f,g,h,i,j,k,l,m,n,p,q,r,s,u,v,y,B,C,D,E,F,G,J,K,L;s=a.level===z,v=this.value,m=this.variable.base.objects;if(!(n=m.length))return f=v.compile(a),a.level>=x?"("+f+")":f;i=this.variable.isObject();if(s&&n===1&&!((l=m[0])instanceof P)){l instanceof c?(D=l,E=D.variable,h=E.base,l=D.value):l.base instanceof H?(F=(new W(l.unwrapAll())).cacheReference(a),l=F[0],h=F[1]):h=i?l["this"]?l.properties[0].name:l:new A(0),d=o.test(h.unwrap().value||0),v=new W(v),v.properties.push(new(d?b:t)(h));if(G=l.unwrap().value,bn.call(I,G)>=0)throw new SyntaxError("assignment to a reserved word: "+l.compile(a)+" = "+v.compile(a));return(new c(l,v,null,{param:this.param})).compile(a,z)}y=v.compile(a,w),e=[],r=!1;if(!o.test(y)||this.variable.assigns(y))e.push(""+(p=a.scope.freeVariable("ref"))+" = "+y),y=p;for(g=B=0,C=m.length;B=0)throw new SyntaxError("assignment to a reserved word: "+l.compile(a)+" = "+u.compile(a));e.push((new c(l,u,null,{param:this.param,subpattern:!0})).compile(a,w))}return!s&&!this.subpattern&&e.push(y),f=e.join(", "),a.level=0&&(a.isExistentialEquals=!0),(new F(this.context.slice(0,-1),b,new c(d,this.value,"="))).compile(a)},c.prototype.compileSplice=function(a){var b,c,d,e,f,g,h,i,j,k,l,m;return k=this.variable.properties.pop().range,d=k.from,h=k.to,c=k.exclusive,g=this.variable.compile(a),l=(d!=null?d.cache(a,x):void 0)||["0","0"],e=l[0],f=l[1],h?(d!=null?d.isSimpleNumber():void 0)&&h.isSimpleNumber()?(h=+h.compile(a)- +f,c||(h+=1)):(h=h.compile(a,u)+" - "+f,c||(h+=" + 1")):h="9e9",m=this.value.cache(a,w),i=m[0],j=m[1],b="[].splice.apply("+g+", ["+e+", "+h+"].concat("+i+")), "+j,a.level>z?"("+b+")":b},c}(e),a.Code=j=function(a){function b(a,b,c){this.params=a||[],this.body=b||new f,this.bound=c==="boundfunc",this.bound&&(this.context="_this")}return bm(b,a),b.prototype.children=["params","body"],b.prototype.isStatement=function(){return!!this.ctor},b.prototype.jumps=D,b.prototype.compileNode=function(a){var b,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,v,w,x,y,z,B,C,D,E,G,H,I,J,K,L,M,O;a.scope=new N(a.scope,this.body,this),a.scope.shared=$(a,"sharedScope"),a.indent+=R,delete a.bare,delete a.isExistentialEquals,l=[],e=[],H=this.paramNames();for(s=0,x=H.length;s=0)throw SyntaxError("multiple parameters named '"+i+"'");o.push(i)}return!q&&!this.noReturn&&this.body.makeReturn(),this.bound&&(((O=a.scope.parent.method)!=null?O.bound:void 0)?this.bound=this.context=a.scope.parent.method.context:this["static"]||a.scope.parent.assign("_this","this")),g=a.indent,b="function",this.ctor&&(b+=" "+this.name),b+="("+l.join(", ")+") {",this.body.isEmpty()||(b+="\n"+this.body.compileWithDeclarations(a)+"\n"+this.tab),b+="}",this.ctor?this.tab+b:this.front||a.level>=u?"("+b+")":b},b.prototype.paramNames=function(){var a,b,c,d,e;a=[],e=this.params;for(c=0,d=e.length;c=0)throw SyntaxError('parameter name "'+a+'" is not allowed')}return bm(b,a),b.prototype.children=["name","value"],b.prototype.compile=function(a){return this.name.compile(a,w)},b.prototype.asReference=function(a){var b;return this.reference?this.reference:(b=this.name,b["this"]?(b=b.properties[0].name,b.value.reserved&&(b=new A(a.scope.freeVariable(b.value)))):b.isComplex()&&(b=new A(a.scope.freeVariable("arg"))),b=new W(b),this.splat&&(b=new P(b)),this.reference=b)},b.prototype.isComplex=function(){return this.name.isComplex()},b.prototype.names=function(a){var b,c,e,f,g,h;a==null&&(a=this.name),b=function(a){var b;return b=a.properties[0].name.value,b.reserved?[]:[b]};if(a instanceof A)return[a.value];if(a instanceof W)return b(a);c=[],h=a.objects;for(f=0,g=h.length;f=c.length)return"";if(c.length===1)return g=c[0].compile(a,w),d?g:""+bi("slice")+".call("+g+")";e=c.slice(i);for(h=k=0,l=e.length;k1?b.expressions.unshift(new r((new H(this.guard)).invert(),new A("continue"))):this.guard&&(b=f.wrap([new r(this.guard,b)]))),b="\n"+b.compile(a,z)+"\n"+this.tab),c=e+this.tab+("while ("+this.condition.compile(a,y)+") {"+b+"}"),this.returns&&(c+="\n"+this.tab+"return "+d+";"),c},b}(e),a.Op=F=function(a){function e(a,c,d,e){if(a==="in")return new s(c,d);if(a==="do")return this.generateDo(c);if(a==="new"){if(c instanceof g&&!c["do"]&&!c.isNew)return c.newInstance();if(c instanceof j&&c.bound||c["do"])c=new H(c)}return this.operator=b[a]||a,this.first=c,this.second=d,this.flip=!!e,this}var b,c;return bm(e,a),b={"==":"===","!=":"!==",of:"in"},c={"!==":"===","===":"!=="},e.prototype.children=["first","second"],e.prototype.isSimpleNumber=D,e.prototype.isUnary=function(){return!this.second},e.prototype.isComplex=function(){var a;return!this.isUnary()||(a=this.operator)!=="+"&&a!=="-"||this.first.isComplex()},e.prototype.isChainable=function(){var a;return(a=this.operator)==="<"||a===">"||a===">="||a==="<="||a==="==="||a==="!=="},e.prototype.invert=function(){var a,b,d,f,g;if(this.isChainable()&&this.first.isChainable()){a=!0,b=this;while(b&&b.operator)a&&(a=b.operator in c),b=b.first;if(!a)return(new H(this)).invert();b=this;while(b&&b.operator)b.invert=!b.invert,b.operator=c[b.operator],b=b.first;return this}return(f=c[this.operator])?(this.operator=f,this.first.unwrap()instanceof e&&this.first.invert(),this):this.second?(new H(this)).invert():this.operator==="!"&&(d=this.first.unwrap())instanceof e&&((g=d.operator)==="!"||g==="in"||g==="instanceof")?d:new e("!",this)},e.prototype.unfoldSoak=function(a){var b;return((b=this.operator)==="++"||b==="--"||b==="delete")&&bh(a,this,"first")},e.prototype.generateDo=function(a){var b,c,e,f,h,i,k,l;f=[],c=a instanceof d&&(h=a.value.unwrap())instanceof j?h:a,l=c.params||[];for(i=0,k=l.length;i=0))throw SyntaxError("prefix increment/decrement may not have eval or arguments operand");return this.isUnary()?this.compileUnary(a):c?this.compileChain(a):this.operator==="?"?this.compileExistence(a):(b=this.first.compile(a,x)+" "+this.operator+" "+this.second.compile(a,x),a.level<=x?b:"("+b+")")},e.prototype.compileChain=function(a){var b,c,d,e;return e=this.first.second.cache(a),this.first.second=e[0],d=e[1],c=this.first.compile(a,x),b=""+c+" "+(this.invert?"&&":"||")+" "+d.compile(a)+" "+this.operator+" "+this.second.compile(a,x),"("+b+")"},e.prototype.compileExistence=function(a){var b,c;return this.first.isComplex()?(c=new A(a.scope.freeVariable("ref")),b=new H(new d(c,this.first))):(b=this.first,c=b),(new r(new l(b),c,{type:"if"})).addElse(this.second).compile(a)},e.prototype.compileUnary=function(a){var b,c,d;if(a.level>=u)return(new H(this)).compile(a);c=[b=this.operator],d=b==="+"||b==="-",(b==="new"||b==="typeof"||b==="delete"||d&&this.first instanceof e&&this.first.operator===b)&&c.push(" ");if(d&&this.first instanceof e||b==="new"&&this.first.isStatement(a))this.first=new H(this.first);return c.push(this.first.compile(a,x)),this.flip&&c.reverse(),c.join("")},e.prototype.toString=function(a){return e.__super__.toString.call(this,a,this.constructor.name+" "+this.operator)},e}(e),a.In=s=function(a){function b(a,b){this.object=a,this.array=b}return bm(b,a),b.prototype.children=["object","array"],b.prototype.invert=C,b.prototype.compileNode=function(a){var b,c,d,e,f;if(this.array instanceof W&&this.array.isArray()){f=this.array.base.objects;for(d=0,e=f.length;d= 0"),d===c?b:(b=d+", "+b,a.level=0)throw SyntaxError('catch variable may not be "'+this.error.value+'"');return a.scope.check(this.error.value)||a.scope.add(this.error.value,"param")," catch"+d+"{\n"+this.recovery.compile(a,z)+"\n"+this.tab+"}"}if(!this.ensure&&!this.recovery)return" catch (_error) {}"}.call(this),c=this.ensure?" finally {\n"+this.ensure.compile(a,z)+"\n"+this.tab+"}":"",""+this.tab+"try {\n"+e+"\n"+this.tab+"}"+(b||"")+c},b}(e),a.Throw=T=function(a){function b(a){this.expression=a}return bm(b,a),b.prototype.children=["expression"],b.prototype.isStatement=Y,b.prototype.jumps=D,b.prototype.makeReturn=S,b.prototype.compileNode=function(a){return this.tab+("throw "+this.expression.compile(a)+";")},b}(e),a.Existence=l=function(a){function b(a){this.expression=a}return bm(b,a),b.prototype.children=["expression"],b.prototype.invert=C,b.prototype.compileNode=function(a){var b,c,d,e;return this.expression.front=this.front,d=this.expression.compile(a,x),o.test(d)&&!a.scope.check(d)?(e=this.negated?["===","||"]:["!==","&&"],b=e[0],c=e[1],d="typeof "+d+" "+b+' "undefined" '+c+" "+d+" "+b+" null"):d=""+d+" "+(this.negated?"==":"!=")+" null",a.level<=v?d:"("+d+")"},b}(e),a.Parens=H=function(a){function b(a){this.body=a}return bm(b,a),b.prototype.children=["body"],b.prototype.unwrap=function(){return this.body},b.prototype.isComplex=function(){return this.body.isComplex()},b.prototype.compileNode=function(a){var b,c,d;return d=this.body.unwrap(),d instanceof W&&d.isAtomic()?(d.front=this.front,d.compile(a)):(c=d.compile(a,y),b=a.level1?b.expressions.unshift(new r((new H(this.guard)).invert(),new A("continue"))):this.guard&&(b=f.wrap([new r(this.guard,b)]))),this.pattern&&b.expressions.unshift(new d(this.name,new A(""+F+"["+l+"]"))),c+=this.pluckDirectCall(a,b),s&&(G="\n"+i+s+";"),this.object&&(e=""+l+" in "+F,this.own&&(h="\n"+i+"if (!"+bi("hasProp")+".call("+F+", "+l+")) continue;")),b=b.compile(bd(a,{indent:i}),z),b&&(b="\n"+b+"\n"),""+c+(u||"")+this.tab+"for ("+e+") {"+h+G+b+this.tab+"}"+(v||"")},b.prototype.pluckDirectCall=function(a,b){var c,e,f,h,i,k,l,m,n,o,p,q,r,s,t;e="",o=b.expressions;for(i=m=0,n=o.length;m=v?"("+d+")":d},b.prototype.unfoldSoak=function(){return this.soak&&this},b}(e),i={wrap:function(a,c,d){var e,h,i,k,l;if(a.jumps())return a;i=new j([],f.wrap([a])),e=[];if((k=a.contains(this.literalArgs))||a.contains(this.literalThis))l=new A(k?"apply":"call"),e=[new A("this")],k&&e.push(new A("arguments")),i=new W(i,[new b(l)]);return i.noReturn=d,h=new g(i,e),c?f.wrap([h]):h},literalArgs:function(a){return a instanceof A&&a.value==="arguments"&&!a.asKey},literalThis:function(a){return a instanceof A&&a.value==="this"&&!a.asKey||a instanceof j&&a.bound||a instanceof g&&a.isSuper}},bh=function(a,b,c){var d;if(!(d=b[c].unfoldSoak(a)))return;return b[c]=d.body,d.body=new W(b),d},V={"extends":function(){return"function(child, parent) { for (var key in parent) { if ("+bi("hasProp")+".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }"},bind:function(){return"function(fn, me){ return function(){ return fn.apply(me, arguments); }; }"},indexOf:function(){return"[].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }"},hasProp:function(){return"{}.hasOwnProperty"},slice:function(){return"[].slice"}},z=1,y=2,w=3,v=4,x=5,u=6,R=" ",p="[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*",o=RegExp("^"+p+"$"),L=/^[+-]?\d+$/,B=RegExp("^(?:("+p+")\\.prototype(?:\\.("+p+")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|("+p+")$"),q=/^['"]/,bi=function(a){var b;return b="__"+a,N.root.assign(b,V[a]()),b},be=function(a,b){return a=a.replace(/\n/g,"$&"+b),a.replace(/\s+$/,"")}})).call(this)},require["./coffee-script"]=new function(){var a=this;((function(){var b,c,d,e,f,g,h,i,j,k,l={}.hasOwnProperty;e=require("fs"),h=require("path"),k=require("./lexer"),b=k.Lexer,c=k.RESERVED,g=require("./parser").parser,j=require("vm"),i=function(a){return a.charCodeAt(0)===65279?a.substring(1):a},require.extensions&&(require.extensions[".coffee"]=function(a,b){var c;return c=d(i(e.readFileSync(b,"utf8")),{filename:b}),a._compile(c,b)}),a.VERSION="1.4.0",a.RESERVED=c,a.helpers=require("./helpers"),a.compile=d=function(b,c){var d,e,h;c==null&&(c={}),h=a.helpers.merge;try{e=g.parse(f.tokenize(b)).compile(c);if(!c.header)return e}catch(i){throw c.filename&&(i.message="In "+c.filename+", "+i.message),i}return d="Generated by CoffeeScript "+this.VERSION,"// "+d+"\n"+e},a.tokens=function(a,b){return f.tokenize(a,b)},a.nodes=function(a,b){return typeof a=="string"?g.parse(f.tokenize(a,b)):g.parse(a)},a.run=function(a,b){var c;return b==null&&(b={}),c=require.main,c.filename=process.argv[1]=b.filename?e.realpathSync(b.filename):".",c.moduleCache&&(c.moduleCache={}),c.paths=require("module")._nodeModulePaths(h.dirname(e.realpathSync(b.filename))),h.extname(c.filename)!==".coffee"||require.extensions?c._compile(d(a,b),c.filename):c._compile(a,c.filename)},a.eval=function(a,b){var c,e,f,g,i,k,m,n,o,p,q,r,s,t;b==null&&(b={});if(!(a=a.trim()))return;e=j.Script;if(e){if(b.sandbox!=null){if(b.sandbox instanceof e.createContext().constructor)m=b.sandbox;else{m=e.createContext(),r=b.sandbox;for(g in r){if(!l.call(r,g))continue;n=r[g],m[g]=n}}m.global=m.root=m.GLOBAL=m}else m=global;m.__filename=b.filename||"eval",m.__dirname=h.dirname(m.__filename);if(m===global&&!m.module&&!m.require){c=require("module"),m.module=q=new c(b.modulename||"eval"),m.require=t=function(a){return c._load(a,q,!0)},q.filename=m.__filename,s=Object.getOwnPropertyNames(require);for(o=0,p=s.length;oe;e++)if(e in this&&this[e]===t)return e;return-1};if(t=function(){function t(t){this.client=new e(t)}return t}(),t.ApiError=function(){function t(t,e,r){var n;if(this.method=e,this.url=r,this.status=t.status,n=t.responseType?t.response||t.responseText:t.responseText)try{this.responseText=""+n,this.response=JSON.parse(n)}catch(o){this.response=null}else this.responseText="(no response)",this.response=null}return t.prototype.status=void 0,t.prototype.method=void 0,t.prototype.url=void 0,t.prototype.responseText=void 0,t.prototype.response=void 0,t.prototype.toString=function(){return"Dropbox API error "+this.status+" from "+this.method+" "+this.url+" :: "+this.responseText},t.prototype.inspect=function(){return""+this},t}(),"undefined"!=typeof window&&null!==window?window.atob&&window.btoa?(u=function(t){return window.atob(t)},f=function(t){return window.btoa(t)}):(p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",y=function(t,e,r){var n,o;for(o=3-e,t<<=8*o,n=3;n>=o;)r.push(p.charAt(63&t>>6*n)),n-=1;for(n=e;3>n;)r.push("="),n+=1;return null},l=function(t,e,r){var n,o;for(o=4-e,t<<=6*o,n=2;n>=o;)r.push(String.fromCharCode(255&t>>8*n)),n-=1;return null},f=function(t){var e,r,n,o,i,s;for(o=[],e=0,r=0,n=i=0,s=t.length;s>=0?s>i:i>s;n=s>=0?++i:--i)e=e<<8|t.charCodeAt(n),r+=1,3===r&&(y(e,r,o),e=r=0);return r>0&&y(e,r,o),o.join("")},u=function(t){var e,r,n,o,i,s,a;for(i=[],e=0,n=0,o=s=0,a=t.length;(a>=0?a>s:s>a)&&(r=t.charAt(o),"="!==r);o=a>=0?++s:--s)e=e<<6|p.indexOf(r),n+=1,4===n&&(l(e,n,i),e=n=0);return n>0&&l(e,n,i),i.join("")}):(u=function(t){var e,r;return e=new Buffer(t,"base64"),function(){var t,n,o;for(o=[],r=t=0,n=e.length;n>=0?n>t:t>n;r=n>=0?++t:--t)o.push(String.fromCharCode(e[r]));return o}().join("")},f=function(t){var e,r;return e=new Buffer(function(){var e,n,o;for(o=[],r=e=0,n=t.length;n>=0?n>e:e>n;r=n>=0?++e:--e)o.push(t.charCodeAt(r));return o}()),e.toString("base64")}),t.Client=function(){function r(e){this.sandbox=e.sandbox||!1,this.apiServer=e.server||this.defaultApiServer(),this.authServer=e.authServer||this.defaultAuthServer(),this.fileServer=e.fileServer||this.defaultFileServer(),this.downloadServer=e.downloadServer||this.defaultDownloadServer(),this.onXhr=new t.EventSource({cancelable:!0}),this.onError=new t.EventSource,this.onAuthStateChange=new t.EventSource,this.oauth=new t.Oauth(e),this.driver=null,this.filter=null,this.uid=null,this.authState=null,this.authError=null,this._credentials=null,this.setCredentials(e),this.setupUrls()}return r.prototype.authDriver=function(t){return this.driver=t,this},r.prototype.onXhr=null,r.prototype.onError=null,r.prototype.onAuthStateChange=null,r.prototype.dropboxUid=function(){return this.uid},r.prototype.credentials=function(){return this._credentials||this.computeCredentials(),this._credentials},r.prototype.authenticate=function(r){var n,o,i=this;if(n=null,!this.driver&&this.authState!==e.DONE)throw Error("Call authDriver to set an authentication driver");return o=function(){var s;if(n!==i.authState&&(null!==n&&i.onAuthStateChange.dispatch(i),n=i.authState,i.driver&&i.driver.onAuthStateChange))return i.driver.onAuthStateChange(i,o);switch(i.authState){case e.RESET:return i.requestToken(function(t,r){var n,s;return t?(i.authError=t,i.authState=e.ERROR):(n=r.oauth_token,s=r.oauth_token_secret,i.oauth.setToken(n,s),i.authState=e.REQUEST),i._credentials=null,o()});case e.REQUEST:return s=i.authorizeUrl(i.oauth.token),i.driver.doAuthorize(s,i.oauth.token,i.oauth.tokenSecret,function(){return i.authState=e.AUTHORIZED,i._credentials=null,o()});case e.AUTHORIZED:return i.getAccessToken(function(t,r){return t?(i.authError=t,i.authState=e.ERROR):(i.oauth.setToken(r.oauth_token,r.oauth_token_secret),i.uid=r.uid,i.authState=e.DONE),i._credentials=null,o()});case e.DONE:return r(null,i);case t.SIGNED_OFF:return i.authState=e.RESET,i.reset(),o();case e.ERROR:return r(i.authError)}},o(),this},r.prototype.isAuthenticated=function(){return this.authState===e.DONE},r.prototype.signOut=function(r){var n,o=this;return n=new t.Xhr("POST",this.urls.signOut),n.signWithOauth(this.oauth),this.dispatchXhr(n,function(t){return t?r(t):(o.authState=e.RESET,o.reset(),o.authState=e.SIGNED_OFF,o.onAuthStateChange.dispatch(o),o.driver.onAuthStateChange?o.driver.onAuthStateChange(o,function(){return r(t)}):r(t))})},r.prototype.signOff=function(t){return this.signOut(t)},r.prototype.getUserInfo=function(e){var r;return r=new t.Xhr("GET",this.urls.accountInfo),r.signWithOauth(this.oauth),this.dispatchXhr(r,function(r,n){return e(r,t.UserInfo.parse(n),n)})},r.prototype.readFile=function(e,r,n){var o,i,s,a,h,u;return n||"function"!=typeof r||(n=r,r=null),o={},h=null,s=null,r&&(r.versionTag?o.rev=r.versionTag:r.rev&&(o.rev=r.rev),r.arrayBuffer?h="arraybuffer":r.blob?h="blob":r.binary&&(h="b"),r.length?(null!=r.start?(a=r.start,i=r.start+r.length-1):(a="",i=r.length),s="bytes="+a+"-"+i):null!=r.start&&(s="bytes="+r.start+"-")),u=new t.Xhr("GET",""+this.urls.getFile+"/"+this.urlEncodePath(e)),u.setParams(o).signWithOauth(this.oauth).setResponseType(h),s&&u.setHeader("Range",s),this.dispatchXhr(u,function(e,r,o){return n(e,r,t.Stat.parse(o))})},r.prototype.writeFile=function(e,r,n,o){var i;return o||"function"!=typeof n||(o=n,n=null),i=t.Xhr.canSendForms&&"object"==typeof r,i?this.writeFileUsingForm(e,r,n,o):this.writeFileUsingPut(e,r,n,o)},r.prototype.writeFileUsingForm=function(e,r,n,o){var i,s,a,h;return a=e.lastIndexOf("/"),-1===a?(i=e,e=""):(i=e.substring(a),e=e.substring(0,a)),s={file:i},n&&(n.noOverwrite&&(s.overwrite="false"),n.lastVersionTag?s.parent_rev=n.lastVersionTag:(n.parentRev||n.parent_rev)&&(s.parent_rev=n.parentRev||n.parent_rev)),h=new t.Xhr("POST",""+this.urls.postFile+"/"+this.urlEncodePath(e)),h.setParams(s).signWithOauth(this.oauth).setFileField("file",i,r,"application/octet-stream"),delete s.file,this.dispatchXhr(h,function(e,r){return o(e,t.Stat.parse(r))})},r.prototype.writeFileUsingPut=function(e,r,n,o){var i,s;return i={},n&&(n.noOverwrite&&(i.overwrite="false"),n.lastVersionTag?i.parent_rev=n.lastVersionTag:(n.parentRev||n.parent_rev)&&(i.parent_rev=n.parentRev||n.parent_rev)),s=new t.Xhr("POST",""+this.urls.putFile+"/"+this.urlEncodePath(e)),s.setBody(r).setParams(i).signWithOauth(this.oauth),this.dispatchXhr(s,function(e,r){return o(e,t.Stat.parse(r))})},r.prototype.resumableUploadStep=function(e,r,n){var o,i;return r?(o={offset:r.offset},r.tag&&(o.upload_id=r.tag)):o={offset:0},i=new t.Xhr("POST",this.urls.chunkedUpload),i.setBody(e).setParams(o).signWithOauth(this.oauth),this.dispatchXhr(i,function(e,r){return e&&400===e.status&&e.response.upload_id&&e.response.offset?n(null,t.UploadCursor.parse(e.response)):n(e,t.UploadCursor.parse(r))})},r.prototype.resumableUploadFinish=function(e,r,n,o){var i,s;return o||"function"!=typeof n||(o=n,n=null),i={upload_id:r.tag},n&&(n.lastVersionTag?i.parent_rev=n.lastVersionTag:(n.parentRev||n.parent_rev)&&(i.parent_rev=n.parentRev||n.parent_rev),n.noOverwrite&&(i.autorename=!0)),s=new t.Xhr("POST",""+this.urls.commitChunkedUpload+"/"+this.urlEncodePath(e)),s.setParams(i).signWithOauth(this.oauth),this.dispatchXhr(s,function(e,r){return o(e,t.Stat.parse(r))})},r.prototype.stat=function(e,r,n){var o,i;return n||"function"!=typeof r||(n=r,r=null),o={},r&&(null!=r.version&&(o.rev=r.version),(r.removed||r.deleted)&&(o.include_deleted="true"),r.readDir&&(o.list="true",r.readDir!==!0&&(o.file_limit=""+r.readDir)),r.cacheHash&&(o.hash=r.cacheHash)),o.include_deleted||(o.include_deleted="false"),o.list||(o.list="false"),i=new t.Xhr("GET",""+this.urls.metadata+"/"+this.urlEncodePath(e)),i.setParams(o).signWithOauth(this.oauth),this.dispatchXhr(i,function(e,r){var o,i,s;return s=t.Stat.parse(r),o=(null!=r?r.contents:void 0)?function(){var e,n,o,s;for(o=r.contents,s=[],e=0,n=o.length;n>e;e++)i=o[e],s.push(t.Stat.parse(i));return s}():void 0,n(e,s,o)})},r.prototype.readdir=function(t,e,r){var n;return r||"function"!=typeof e||(r=e,e=null),n={readDir:!0},e&&(null!=e.limit&&(n.readDir=e.limit),e.versionTag&&(n.versionTag=e.versionTag)),this.stat(t,n,function(t,e,n){var o,i;return o=n?function(){var t,e,r;for(r=[],t=0,e=n.length;e>t;t++)i=n[t],r.push(i.name);return r}():null,r(t,o,e,n)})},r.prototype.metadata=function(t,e,r){return this.stat(t,e,r)},r.prototype.makeUrl=function(e,r,n){var o,i,s,a,h;return n||"function"!=typeof r||(n=r,r=null),i=r&&(r["long"]||r.longUrl||r.downloadHack)?{short_url:"false"}:{},e=this.urlEncodePath(e),s=""+this.urls.shares+"/"+e,o=!1,a=!1,r&&(r.downloadHack?(o=!0,a=!0):r.download&&(o=!0,s=""+this.urls.media+"/"+e)),h=new t.Xhr("POST",s).setParams(i).signWithOauth(this.oauth),this.dispatchXhr(h,function(e,r){return a&&r&&r.url&&(r.url=r.url.replace(this.authServer,this.downloadServer)),n(e,t.PublicUrl.parse(r,o))})},r.prototype.history=function(e,r,n){var o,i;return n||"function"!=typeof r||(n=r,r=null),o={},r&&null!=r.limit&&(o.rev_limit=r.limit),i=new t.Xhr("GET",""+this.urls.revisions+"/"+this.urlEncodePath(e)),i.setParams(o).signWithOauth(this.oauth),this.dispatchXhr(i,function(e,r){var o,i;return i=r?function(){var e,n,i;for(i=[],e=0,n=r.length;n>e;e++)o=r[e],i.push(t.Stat.parse(o));return i}():void 0,n(e,i)})},r.prototype.revisions=function(t,e,r){return this.history(t,e,r)},r.prototype.thumbnailUrl=function(t,e){var r;return r=this.thumbnailXhr(t,e),r.paramsToUrl().url},r.prototype.readThumbnail=function(e,r,n){var o,i;return n||"function"!=typeof r||(n=r,r=null),o="b",r&&r.blob&&(o="blob"),i=this.thumbnailXhr(e,r),i.setResponseType(o),this.dispatchXhr(i,function(e,r,o){return n(e,r,t.Stat.parse(o))})},r.prototype.thumbnailXhr=function(e,r){var n,o;return n={},r&&(r.format?n.format=r.format:r.png&&(n.format="png"),r.size&&(n.size=r.size)),o=new t.Xhr("GET",""+this.urls.thumbnails+"/"+this.urlEncodePath(e)),o.setParams(n).signWithOauth(this.oauth)},r.prototype.revertFile=function(e,r,n){var o;return o=new t.Xhr("POST",""+this.urls.restore+"/"+this.urlEncodePath(e)),o.setParams({rev:r}).signWithOauth(this.oauth),this.dispatchXhr(o,function(e,r){return n(e,t.Stat.parse(r))})},r.prototype.restore=function(t,e,r){return this.revertFile(t,e,r)},r.prototype.findByName=function(e,r,n,o){var i,s;return o||"function"!=typeof n||(o=n,n=null),i={query:r},n&&(null!=n.limit&&(i.file_limit=n.limit),(n.removed||n.deleted)&&(i.include_deleted=!0)),s=new t.Xhr("GET",""+this.urls.search+"/"+this.urlEncodePath(e)),s.setParams(i).signWithOauth(this.oauth),this.dispatchXhr(s,function(e,r){var n,i;return i=r?function(){var e,o,i;for(i=[],e=0,o=r.length;o>e;e++)n=r[e],i.push(t.Stat.parse(n));return i}():void 0,o(e,i)})},r.prototype.search=function(t,e,r,n){return this.findByName(t,e,r,n)},r.prototype.makeCopyReference=function(e,r){var n;return n=new t.Xhr("GET",""+this.urls.copyRef+"/"+this.urlEncodePath(e)),n.signWithOauth(this.oauth),this.dispatchXhr(n,function(e,n){return r(e,t.CopyReference.parse(n))})},r.prototype.copyRef=function(t,e){return this.makeCopyReference(t,e)},r.prototype.pullChanges=function(e,r){var n,o;return r||"function"!=typeof e||(r=e,e=null),n=e?e.cursorTag?{cursor:e.cursorTag}:{cursor:e}:{},o=new t.Xhr("POST",this.urls.delta),o.setParams(n).signWithOauth(this.oauth),this.dispatchXhr(o,function(e,n){return r(e,t.PulledChanges.parse(n))})},r.prototype.delta=function(t,e){return this.pullChanges(t,e)},r.prototype.mkdir=function(e,r){var n;return n=new t.Xhr("POST",this.urls.fileopsCreateFolder),n.setParams({root:this.fileRoot,path:this.normalizePath(e)}).signWithOauth(this.oauth),this.dispatchXhr(n,function(e,n){return r(e,t.Stat.parse(n))})},r.prototype.remove=function(e,r){var n;return n=new t.Xhr("POST",this.urls.fileopsDelete),n.setParams({root:this.fileRoot,path:this.normalizePath(e)}).signWithOauth(this.oauth),this.dispatchXhr(n,function(e,n){return r(e,t.Stat.parse(n))})},r.prototype.unlink=function(t,e){return this.remove(t,e)},r.prototype["delete"]=function(t,e){return this.remove(t,e)},r.prototype.copy=function(e,r,n){var o,i,s;return n||"function"!=typeof o||(n=o,o=null),i={root:this.fileRoot,to_path:this.normalizePath(r)},e instanceof t.CopyReference?i.from_copy_ref=e.tag:i.from_path=this.normalizePath(e),s=new t.Xhr("POST",this.urls.fileopsCopy),s.setParams(i).signWithOauth(this.oauth),this.dispatchXhr(s,function(e,r){return n(e,t.Stat.parse(r))})},r.prototype.move=function(e,r,n){var o,i;return n||"function"!=typeof o||(n=o,o=null),i=new t.Xhr("POST",this.urls.fileopsMove),i.setParams({root:this.fileRoot,from_path:this.normalizePath(e),to_path:this.normalizePath(r)}).signWithOauth(this.oauth),this.dispatchXhr(i,function(e,r){return n(e,t.Stat.parse(r))})},r.prototype.reset=function(){var t;return this.uid=null,this.oauth.setToken(null,""),t=this.authState,this.authState=e.RESET,t!==this.authState&&this.onAuthStateChange.dispatch(this),this.authError=null,this._credentials=null,this},r.prototype.setCredentials=function(t){var r;return r=this.authState,this.oauth.reset(t),this.uid=t.uid||null,this.authState=t.authState?t.authState:t.token?e.DONE:e.RESET,this.authError=null,this._credentials=null,r!==this.authState&&this.onAuthStateChange.dispatch(this),this},r.prototype.appHash=function(){return this.oauth.appHash()},r.prototype.setupUrls=function(){return this.fileRoot=this.sandbox?"sandbox":"dropbox",this.urls={requestToken:""+this.apiServer+"/1/oauth/request_token",authorize:""+this.authServer+"/1/oauth/authorize",accessToken:""+this.apiServer+"/1/oauth/access_token",signOut:""+this.apiServer+"/1/unlink_access_token",accountInfo:""+this.apiServer+"/1/account/info",getFile:""+this.fileServer+"/1/files/"+this.fileRoot,postFile:""+this.fileServer+"/1/files/"+this.fileRoot,putFile:""+this.fileServer+"/1/files_put/"+this.fileRoot,metadata:""+this.apiServer+"/1/metadata/"+this.fileRoot,delta:""+this.apiServer+"/1/delta",revisions:""+this.apiServer+"/1/revisions/"+this.fileRoot,restore:""+this.apiServer+"/1/restore/"+this.fileRoot,search:""+this.apiServer+"/1/search/"+this.fileRoot,shares:""+this.apiServer+"/1/shares/"+this.fileRoot,media:""+this.apiServer+"/1/media/"+this.fileRoot,copyRef:""+this.apiServer+"/1/copy_ref/"+this.fileRoot,thumbnails:""+this.fileServer+"/1/thumbnails/"+this.fileRoot,chunkedUpload:""+this.fileServer+"/1/chunked_upload",commitChunkedUpload:""+this.fileServer+"/1/commit_chunked_upload/"+this.fileRoot,fileopsCopy:""+this.apiServer+"/1/fileops/copy",fileopsCreateFolder:""+this.apiServer+"/1/fileops/create_folder",fileopsDelete:""+this.apiServer+"/1/fileops/delete",fileopsMove:""+this.apiServer+"/1/fileops/move"}},r.prototype.authState=null,r.ERROR=0,r.RESET=1,r.REQUEST=2,r.AUTHORIZED=3,r.DONE=4,r.SIGNED_OFF=5,r.prototype.urlEncodePath=function(e){return t.Xhr.urlEncodeValue(this.normalizePath(e)).replace(/%2F/gi,"/")},r.prototype.normalizePath=function(t){var e;if("/"===t.substring(0,1)){for(e=1;"/"===t.substring(e,e+1);)e+=1;return t.substring(e)}return t},r.prototype.requestToken=function(e){var r;return r=new t.Xhr("POST",this.urls.requestToken).signWithOauth(this.oauth),this.dispatchXhr(r,e)},r.prototype.authorizeUrl=function(e){var r;return r={oauth_token:e,oauth_callback:this.driver.url()},""+this.urls.authorize+"?"+t.Xhr.urlEncode(r)},r.prototype.getAccessToken=function(e){var r;return r=new t.Xhr("POST",this.urls.accessToken).signWithOauth(this.oauth),this.dispatchXhr(r,e)},r.prototype.dispatchXhr=function(t,e){var r;return t.setCallback(e),t.onError=this.onError,t.prepare(),r=t.xhr,this.onXhr.dispatch(t)&&t.send(),r},r.prototype.defaultApiServer=function(){return"https://api.dropbox.com"},r.prototype.defaultAuthServer=function(){return this.apiServer.replace("api.","www.")},r.prototype.defaultFileServer=function(){return this.apiServer.replace("api.","api-content.")},r.prototype.defaultDownloadServer=function(){return this.apiServer.replace("api.","dl.")},r.prototype.computeCredentials=function(){var t;return t={key:this.oauth.key,sandbox:this.sandbox},this.oauth.secret&&(t.secret=this.oauth.secret),this.oauth.token&&(t.token=this.oauth.token,t.tokenSecret=this.oauth.tokenSecret),this.uid&&(t.uid=this.uid),this.authState!==e.ERROR&&this.authState!==e.RESET&&this.authState!==e.DONE&&this.authState!==e.SIGNED_OFF&&(t.authState=this.authState),this.apiServer!==this.defaultApiServer()&&(t.server=this.apiServer),this.authServer!==this.defaultAuthServer()&&(t.authServer=this.authServer),this.fileServer!==this.defaultFileServer()&&(t.fileServer=this.fileServer),this.downloadServer!==this.defaultDownloadServer()&&(t.downloadServer=this.downloadServer),this._credentials=t},r}(),e=t.Client,t.AuthDriver=function(){function t(){}return t.prototype.url=function(){return"https://some.url"},t.prototype.doAuthorize=function(t,e,r,n){return n("oauth-token")},t.prototype.onAuthStateChange=function(t,e){return e()},t}(),t.Drivers={},t.Drivers.BrowserBase=function(){function t(t){this.rememberUser=(null!=t?t.rememberUser:void 0)||!1,this.scope=(null!=t?t.scope:void 0)||"default"}return t.prototype.onAuthStateChange=function(t,r){var n=this;switch(this.setStorageKey(t),t.authState){case e.RESET:return this.loadCredentials(function(e){return e?e.authState?(t.setCredentials(e),r()):n.rememberUser?(t.setCredentials(e),t.getUserInfo(function(e){return e?(t.reset(),n.forgetCredentials(r)):r()})):(n.forgetCredentials(),r()):r()});case e.REQUEST:return this.storeCredentials(t.credentials(),r);case e.DONE:return this.rememberUser?this.storeCredentials(t.credentials(),r):this.forgetCredentials(r);case e.SIGNED_OFF:return this.forgetCredentials(r);case e.ERROR:return this.forgetCredentials(r);default:return r(),this}},t.prototype.setStorageKey=function(t){return this.storageKey="dropbox-auth:"+this.scope+":"+t.appHash(),this},t.prototype.storeCredentials=function(t,e){return localStorage.setItem(this.storageKey,JSON.stringify(t)),e(),this},t.prototype.loadCredentials=function(t){var e;if(e=localStorage.getItem(this.storageKey),!e)return t(null),this;try{t(JSON.parse(e))}catch(r){t(null)}return this},t.prototype.forgetCredentials=function(t){return localStorage.removeItem(this.storageKey),t(),this},t.currentLocation=function(){return window.location.href},t}(),t.Drivers.Redirect=function(r){function n(t){n.__super__.constructor.call(this,t),this.useQuery=(null!=t?t.useQuery:void 0)||!1,this.receiverUrl=this.computeUrl(t),this.tokenRe=RegExp("(#|\\?|&)oauth_token=([^]+)(&|#|$)")}return T(n,r),n.prototype.onAuthStateChange=function(t,r){var o,i=this;return o=function(){return function(){return n.__super__.onAuthStateChange.call(i,t,r)}}(),this.setStorageKey(t),t.authState===e.RESET?this.loadCredentials(function(t){return t&&t.authState?t.token===i.locationToken()&&t.authState===e.REQUEST?(t.authState=e.AUTHORIZED,i.storeCredentials(t,o)):i.forgetCredentials(o):o()}):o()},n.prototype.url=function(){return this.receiverUrl},n.prototype.doAuthorize=function(t){return window.location.assign(t)},n.prototype.computeUrl=function(){var e,r,n,o;return o="_dropboxjs_scope="+encodeURIComponent(this.scope),r=t.Drivers.BrowserBase.currentLocation(),-1===r.indexOf("#")?e=null:(n=r.split("#",2),r=n[0],e=n[1]),this.useQuery?r+=-1===r.indexOf("?")?"?"+o:"&"+o:e="?"+o,e?r+"#"+e:r},n.prototype.locationToken=function(){var e,r,n;return e=t.Drivers.BrowserBase.currentLocation(),n="_dropboxjs_scope="+encodeURIComponent(this.scope)+"&",-1===("function"==typeof e.indexOf?e.indexOf(n):void 0)?null:(r=this.tokenRe.exec(e),r?decodeURIComponent(r[2]):null)},n}(t.Drivers.BrowserBase),t.Drivers.Popup=function(r){function n(t){n.__super__.constructor.call(this,t),this.receiverUrl=this.computeUrl(t),this.tokenRe=RegExp("(#|\\?|&)oauth_token=([^]+)(&|#|$)")}return T(n,r),n.prototype.onAuthStateChange=function(t,r){var o,i=this;return o=function(){return function(){return n.__super__.onAuthStateChange.call(i,t,r)}}(),this.setStorageKey(t),t.authState===e.RESET?this.loadCredentials(function(t){return t&&t.authState?i.forgetCredentials(o):o()}):o()},n.prototype.doAuthorize=function(t,e,r,n){return this.listenForMessage(e,n),this.openWindow(t)},n.prototype.url=function(){return this.receiverUrl},n.prototype.computeUrl=function(e){var r;if(e){if(e.receiverUrl)return e.noFragment||-1!==e.receiverUrl.indexOf("#")?e.receiverUrl:e.receiverUrl+"#";if(e.receiverFile)return r=t.Drivers.BrowserBase.currentLocation().split("/"),r[r.length-1]=e.receiverFile,e.noFragment?r.join("/"):r.join("/")+"#"}return t.Drivers.BrowserBase.currentLocation()},n.prototype.openWindow=function(t){return window.open(t,"_dropboxOauthSigninWindow",this.popupWindowSpec(980,700))},n.prototype.popupWindowSpec=function(t,e){var r,n,o,i,s,a,h,u,l,p;return s=null!=(h=window.screenX)?h:window.screenLeft,a=null!=(u=window.screenY)?u:window.screenTop,i=null!=(l=window.outerWidth)?l:document.documentElement.clientWidth,r=null!=(p=window.outerHeight)?p:document.documentElement.clientHeight,n=Math.round(s+(i-t)/2),o=Math.round(a+(r-e)/2.5),s>n&&(n=s),a>o&&(o=a),"width="+t+",height="+e+","+("left="+n+",top="+o)+"dialog=yes,dependent=yes,scrollbars=yes,location=yes"},n.prototype.listenForMessage=function(t,e){var r,n=this;return r=function(o){var i;return i=n.tokenRe.exec(""+o.data),i&&decodeURIComponent(i[2])===t?(window.removeEventListener("message",r),e()):void 0},window.addEventListener("message",r,!1)},n}(t.Drivers.BrowserBase),t.Drivers.NodeServer=function(){function t(t){this.port=(null!=t?t.port:void 0)||8912,this.faviconFile=(null!=t?t.favicon:void 0)||null,this.fs=require("fs"),this.http=require("http"),this.open=require("open"),this.callbacks={},this.urlRe=RegExp("^/oauth_callback\\?"),this.tokenRe=RegExp("(\\?|&)oauth_token=([^&]+)(&|$)"),this.createApp()}return t.prototype.url=function(){return"http://localhost:"+this.port+"/oauth_callback"},t.prototype.doAuthorize=function(t,e,r,n){return this.callbacks[e]=n,this.openBrowser(t)},t.prototype.openBrowser=function(t){if(!t.match(/^https?:\/\//))throw Error("Not a http/https URL: "+t);return this.open(t)},t.prototype.createApp=function(){var t=this;return this.app=this.http.createServer(function(e,r){return t.doRequest(e,r)}),this.app.listen(this.port)},t.prototype.closeServer=function(){return this.app.close()},t.prototype.doRequest=function(t,e){var r,n,o,i=this;return this.urlRe.exec(t.url)&&(n=this.tokenRe.exec(t.url),n&&(o=decodeURIComponent(n[2]),this.callbacks[o]&&(this.callbacks[o](),delete this.callbacks[o]))),r="",t.on("data",function(t){return r+=t}),t.on("end",function(){return i.faviconFile&&"/favicon.ico"===t.url?i.sendFavicon(e):i.closeBrowser(e)})},t.prototype.closeBrowser=function(t){var e;return e='\n\n
Please close this window.
',t.writeHead(200,{"Content-Length":e.length,"Content-Type":"text/html"}),t.write(e),t.end},t.prototype.sendFavicon=function(t){return this.fs.readFile(this.faviconFile,function(e,r){return t.writeHead(200,{"Content-Length":r.length,"Content-Type":"image/x-icon"}),t.write(r),t.end})},t}(),t.EventSource=function(){function t(t){this._cancelable=t&&t.cancelable,this._listeners=[]}return t.prototype.addListener=function(t){if("function"!=typeof t)throw new TypeError("Invalid listener type; expected function");return 0>R.call(this._listeners,t)&&this._listeners.push(t),this},t.prototype.removeListener=function(t){var e,r,n,o,i,s;if(this._listeners.indexOf)r=this._listeners.indexOf(t),-1!==r&&this._listeners.splice(r,1);else for(s=this._listeners,e=o=0,i=s.length;i>o;e=++o)if(n=s[e],n===t){this._listeners.splice(e,1);break}return this},t.prototype.dispatch=function(t){var e,r,n,o,i;for(i=this._listeners,n=0,o=i.length;o>n;n++)if(e=i[n],r=e(t),this._cancelable&&r===!1)return!1;return!0},t}(),c=function(t,e){return h(g(b(t),b(e),t.length,e.length))},d=function(t){return h(S(b(t),t.length))},("undefined"==typeof window||null===window)&&(v=require("crypto"),c=function(t,e){var r;return r=v.createHmac("sha1",e),r.update(t),r.digest("base64")},d=function(t){var e;return e=v.createHash("sha1"),e.update(t),e.digest("base64")}),g=function(t,e,r,n){var o,i,s,a;return e.length>16&&(e=S(e,n)),s=function(){var t,r;for(r=[],i=t=0;16>t;i=++t)r.push(909522486^e[i]);return r}(),a=function(){var t,r;for(r=[],i=t=0;16>t;i=++t)r.push(1549556828^e[i]);return r}(),o=S(s.concat(t),64+r),S(a.concat(o),84)},S=function(t,e){var r,n,o,i,s,h,u,l,p,c,d,f,y,v,m,g,S,b;for(t[e>>2]|=1<<31-((3&e)<<3),t[(e+8>>6<<4)+15]=e<<3,g=Array(80),r=1732584193,o=-271733879,s=-1732584194,u=271733878,p=-1009589776,f=0,m=t.length;m>f;){for(n=r,i=o,h=s,l=u,c=p,y=b=0;80>b;y=++b)g[y]=16>y?t[f+y]:w(g[y-3]^g[y-8]^g[y-14]^g[y-16],1),20>y?(d=o&s|~o&u,v=1518500249):40>y?(d=o^s^u,v=1859775393):60>y?(d=o&s|o&u|s&u,v=-1894007588):(d=o^s^u,v=-899497514),S=a(a(w(r,5),d),a(a(p,g[y]),v)),p=u,u=s,s=w(o,30),o=r,r=S;r=a(r,n),o=a(o,i),s=a(s,h),u=a(u,l),p=a(p,c),f+=16}return[r,o,s,u,p]},w=function(t,e){return t<>>32-e},a=function(t,e){var r,n;return n=(65535&t)+(65535&e),r=(t>>16)+(e>>16)+(n>>16),r<<16|65535&n},h=function(t){var e,r,n,o,i;for(o="",e=0,n=4*t.length;n>e;)r=e,i=(255&t[r>>2]>>(3-(3&r)<<3))<<16,r+=1,i|=(255&t[r>>2]>>(3-(3&r)<<3))<<8,r+=1,i|=255&t[r>>2]>>(3-(3&r)<<3),o+=_[63&i>>18],o+=_[63&i>>12],e+=1,o+=e>=n?"=":_[63&i>>6],e+=1,o+=e>=n?"=":_[63&i],e+=1;return o},_="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",b=function(t){var e,r,n,o,i;for(e=[],n=255,r=o=0,i=t.length;i>=0?i>o:o>i;r=i>=0?++o:--o)e[r>>2]|=(t.charCodeAt(r)&n)<<(3-(3&r)<<3);return e},t.Oauth=function(){function e(t){this.key=this.k=null,this.secret=this.s=null,this.token=null,this.tokenSecret=null,this._appHash=null,this.reset(t)}return e.prototype.reset=function(t){var e,r,n,o;if(t.secret)this.k=this.key=t.key,this.s=this.secret=t.secret,this._appHash=null;else if(t.key)this.key=t.key,this.secret=null,n=u(m(this.key).split("|",2)[1]),o=n.split("?",2),e=o[0],r=o[1],this.k=decodeURIComponent(e),this.s=decodeURIComponent(r),this._appHash=null;else if(!this.k)throw Error("No API key supplied");return t.token?this.setToken(t.token,t.tokenSecret):this.setToken(null,"")},e.prototype.setToken=function(e,r){if(e&&!r)throw Error("No secret supplied with the user token");return this.token=e,this.tokenSecret=r||"",this.hmacKey=t.Xhr.urlEncodeValue(this.s)+"&"+t.Xhr.urlEncodeValue(r),null},e.prototype.authHeader=function(e,r,n){var o,i,s,a,h,u;this.addAuthParams(e,r,n),i=[];for(s in n)a=n[s],"oauth_"===s.substring(0,6)&&i.push(s);for(i.sort(),o=[],h=0,u=i.length;u>h;h++)s=i[h],o.push(t.Xhr.urlEncodeValue(s)+'="'+t.Xhr.urlEncodeValue(n[s])+'"'),delete n[s];return"OAuth "+o.join(",")},e.prototype.addAuthParams=function(t,e,r){return this.boilerplateParams(r),r.oauth_signature=this.signature(t,e,r),r},e.prototype.boilerplateParams=function(t){return t.oauth_consumer_key=this.k,t.oauth_nonce=this.nonce(),t.oauth_signature_method="HMAC-SHA1",this.token&&(t.oauth_token=this.token),t.oauth_timestamp=Math.floor(Date.now()/1e3),t.oauth_version="1.0",t},e.prototype.nonce=function(){return Date.now().toString(36)+Math.random().toString(36)},e.prototype.signature=function(e,r,n){var o;return o=e.toUpperCase()+"&"+t.Xhr.urlEncodeValue(r)+"&"+t.Xhr.urlEncodeValue(t.Xhr.urlEncode(n)),c(o,this.hmacKey)},e.prototype.appHash=function(){return this._appHash?this._appHash:this._appHash=d(this.k).replace(/\=/g,"")},e}(),null==Date.now&&(Date.now=function(){return(new Date).getTime()}),m=function(t,e){var r,n,o,i,s,a,h,l,p,c,d,y;for(e?(e=[encodeURIComponent(t),encodeURIComponent(e)].join("?"),t=function(){var e,n,o;for(o=[],r=e=0,n=t.length/2;n>=0?n>e:e>n;r=n>=0?++e:--e)o.push(16*(15&t.charCodeAt(2*r))+(15&t.charCodeAt(2*r+1)));return o}()):(c=t.split("|",2),t=c[0],e=c[1],t=u(t),t=function(){var e,n,o;for(o=[],r=e=0,n=t.length;n>=0?n>e:e>n;r=n>=0?++e:--e)o.push(t.charCodeAt(r));return o}(),e=u(e)),i=function(){for(y=[],l=0;256>l;l++)y.push(l);return y}.apply(this),a=0,s=p=0;256>p;s=++p)a=(a+i[r]+t[s%t.length])%256,d=[i[a],i[s]],i[s]=d[0],i[a]=d[1];return s=a=0,o=function(){var t,r,o,u;for(u=[],h=t=0,r=e.length;r>=0?r>t:t>r;h=r>=0?++t:--t)s=(s+1)%256,a=(a+i[s])%256,o=[i[a],i[s]],i[s]=o[0],i[a]=o[1],n=i[(i[s]+i[a])%256],u.push(String.fromCharCode((n^e.charCodeAt(h))%256));return u}(),t=function(){var e,n,o;for(o=[],r=e=0,n=t.length;n>=0?n>e:e>n;r=n>=0?++e:--e)o.push(String.fromCharCode(t[r]));return o}(),[f(t.join("")),f(o.join(""))].join("|")},t.PulledChanges=function(){function e(e){var r;this.blankSlate=e.reset||!1,this.cursorTag=e.cursor,this.shouldPullAgain=e.has_more,this.shouldBackOff=!this.shouldPullAgain,this.changes=e.cursor&&e.cursor.length?function(){var n,o,i,s;for(i=e.entries,s=[],n=0,o=i.length;o>n;n++)r=i[n],s.push(t.PullChange.parse(r));return s}():[]}return e.parse=function(e){return e&&"object"==typeof e?new t.PulledChanges(e):e},e.prototype.blankSlate=void 0,e.prototype.cursorTag=void 0,e.prototype.changes=void 0,e.prototype.shouldPullAgain=void 0,e.prototype.shouldBackOff=void 0,e.prototype.cursor=function(){return this.cursorTag},e}(),t.PullChange=function(){function e(e){this.path=e[0],this.stat=t.Stat.parse(e[1]),this.stat?this.wasRemoved=!1:(this.stat=null,this.wasRemoved=!0)}return e.parse=function(e){return e&&"object"==typeof e?new t.PullChange(e):e},e.prototype.path=void 0,e.prototype.wasRemoved=void 0,e.prototype.stat=void 0,e}(),t.PublicUrl=function(){function e(t,e){this.url=t.url,this.expiresAt=new Date(Date.parse(t.expires)),this.isDirect=e===!0?!0:e===!1?!1:"direct"in t?t.direct:864e5>=Date.now()-this.expiresAt,this.isPreview=!this.isDirect,this._json=null}return e.parse=function(e,r){return e&&"object"==typeof e?new t.PublicUrl(e,r):e},e.prototype.url=null,e.prototype.expiresAt=null,e.prototype.isDirect=null,e.prototype.isPreview=null,e.prototype.json=function(){return this._json||(this._json={url:this.url,expires:""+this.expiresAt,direct:this.isDirect})},e}(),t.CopyReference=function(){function e(t){"object"==typeof t?(this.tag=t.copy_ref,this.expiresAt=new Date(Date.parse(t.expires)),this._json=t):(this.tag=t,this.expiresAt=new Date(1e3*Math.ceil(Date.now()/1e3)),this._json=null)}return e.parse=function(e){return!e||"object"!=typeof e&&"string"!=typeof e?e:new t.CopyReference(e)},e.prototype.tag=null,e.prototype.expiresAt=null,e.prototype.json=function(){return this._json||(this._json={copy_ref:this.tag,expires:""+this.expiresAt})},e}(),t.Stat=function(){function e(t){var e,r,n,o;switch(this._json=t,this.path=t.path,"/"!==this.path.substring(0,1)&&(this.path="/"+this.path),e=this.path.length-1,e>=0&&"/"===this.path.substring(e)&&(this.path=this.path.substring(0,e)),r=this.path.lastIndexOf("/"),this.name=this.path.substring(r+1),this.isFolder=t.is_dir||!1,this.isFile=!this.isFolder,this.isRemoved=t.is_deleted||!1,this.typeIcon=t.icon,this.modifiedAt=(null!=(n=t.modified)?n.length:void 0)?new Date(Date.parse(t.modified)):null,this.clientModifiedAt=(null!=(o=t.client_mtime)?o.length:void 0)?new Date(Date.parse(t.client_mtime)):null,t.root){case"dropbox":this.inAppFolder=!1;break;case"app_folder":this.inAppFolder=!0;break;default:this.inAppFolder=null}this.size=t.bytes||0,this.humanSize=t.size||"",this.hasThumbnail=t.thumb_exists||!1,this.isFolder?(this.versionTag=t.hash,this.mimeType=t.mime_type||"inode/directory"):(this.versionTag=t.rev,this.mimeType=t.mime_type||"application/octet-stream")}return e.parse=function(e){return e&&"object"==typeof e?new t.Stat(e):e},e.prototype.path=null,e.prototype.name=null,e.prototype.inAppFolder=null,e.prototype.isFolder=null,e.prototype.isFile=null,e.prototype.isRemoved=null,e.prototype.typeIcon=null,e.prototype.versionTag=null,e.prototype.mimeType=null,e.prototype.size=null,e.prototype.humanSize=null,e.prototype.hasThumbnail=null,e.prototype.modifiedAt=null,e.prototype.clientModifiedAt=null,e.prototype.json=function(){return this._json
-},e}(),t.UploadCursor=function(){function e(t){this.replace(t)}return e.parse=function(e){return!e||"object"!=typeof e&&"string"!=typeof e?e:new t.UploadCursor(e)},e.prototype.tag=null,e.prototype.offset=null,e.prototype.expiresAt=null,e.prototype.json=function(){return this._json||(this._json={upload_id:this.tag,offset:this.offset,expires:""+this.expiresAt})},e.prototype.replace=function(t){return"object"==typeof t?(this.tag=t.upload_id||null,this.offset=t.offset||0,this.expiresAt=new Date(Date.parse(t.expires)||Date.now()),this._json=t):(this.tag=t||null,this.offset=0,this.expiresAt=new Date(1e3*Math.floor(Date.now()/1e3)),this._json=null),this},e}(),t.UserInfo=function(){function e(t){var e;this._json=t,this.name=t.display_name,this.email=t.email,this.countryCode=t.country||null,this.uid=""+t.uid,t.public_app_url?(this.publicAppUrl=t.public_app_url,e=this.publicAppUrl.length-1,e>=0&&"/"===this.publicAppUrl.substring(e)&&(this.publicAppUrl=this.publicAppUrl.substring(0,e))):this.publicAppUrl=null,this.referralUrl=t.referral_link,this.quota=t.quota_info.quota,this.privateBytes=t.quota_info.normal||0,this.sharedBytes=t.quota_info.shared||0,this.usedQuota=this.privateBytes+this.sharedBytes}return e.parse=function(e){return e&&"object"==typeof e?new t.UserInfo(e):e},e.prototype.name=null,e.prototype.email=null,e.prototype.countryCode=null,e.prototype.uid=null,e.prototype.referralUrl=null,e.prototype.publicAppUrl=null,e.prototype.quota=null,e.prototype.usedQuota=null,e.prototype.privateBytes=null,e.prototype.sharedBytes=null,e.prototype.json=function(){return this._json},e}(),"undefined"!=typeof window&&null!==window?(!window.XDomainRequest||"withCredentials"in new XMLHttpRequest?(s=window.XMLHttpRequest,i=!1,n=-1===window.navigator.userAgent.indexOf("Firefox")):(s=window.XDomainRequest,i=!0,n=!1),o=!0):(s=require("xmlhttprequest").XMLHttpRequest,i=!1,n=!1,o=!1),"undefined"==typeof Uint8Array?r=null:Object.getPrototypeOf?r=Object.getPrototypeOf(Object.getPrototypeOf(new Uint8Array(0))).constructor:Object.__proto__&&(r=new Uint8Array(0).__proto__.__proto__.constructor),t.Xhr=function(){function e(t,e){this.method=t,this.isGet="GET"===this.method,this.url=e,this.headers={},this.params=null,this.body=null,this.preflight=!(this.isGet||"POST"===this.method),this.signed=!1,this.responseType=null,this.callback=null,this.xhr=null,this.onError=null}return e.Request=s,e.ieXdr=i,e.canSendForms=n,e.doesPreflight=o,e.ArrayBufferView=r,e.prototype.xhr=null,e.prototype.onError=null,e.prototype.setParams=function(t){if(this.signed)throw Error("setParams called after addOauthParams or addOauthHeader");if(this.params)throw Error("setParams cannot be called twice");return this.params=t,this},e.prototype.setCallback=function(t){return this.callback=t,this},e.prototype.signWithOauth=function(e){return t.Xhr.ieXdr||t.Xhr.doesPreflight&&!this.preflight?this.addOauthParams(e):this.addOauthHeader(e)},e.prototype.addOauthParams=function(t){if(this.signed)throw Error("Request already has an OAuth signature");return this.params||(this.params={}),t.addAuthParams(this.method,this.url,this.params),this.signed=!0,this},e.prototype.addOauthHeader=function(t){if(this.signed)throw Error("Request already has an OAuth signature");return this.params||(this.params={}),this.signed=!0,this.setHeader("Authorization",t.authHeader(this.method,this.url,this.params))},e.prototype.setBody=function(t){if(this.isGet)throw Error("setBody cannot be called on GET requests");if(null!==this.body)throw Error("Request already has a body");return this.preflight||"undefined"!=typeof FormData&&t instanceof FormData||(this.preflight=!0),this.body=t,this},e.prototype.setResponseType=function(t){return this.responseType=t,this},e.prototype.setHeader=function(t,e){var r;if(this.headers[t])throw r=this.headers[t],Error("HTTP header "+t+" already set to "+r);if("Content-Type"===t)throw Error("Content-Type is automatically computed based on setBody");return this.preflight=!0,this.headers[t]=e,this},e.prototype.setFileField=function(e,r,n,o){var i,s;if(null!==this.body)throw Error("Request already has a body");if(this.isGet)throw Error("setFileField cannot be called on GET requests");return"object"==typeof n&&"undefined"!=typeof Blob?("undefined"!=typeof ArrayBuffer&&null!==ArrayBuffer&&n instanceof ArrayBuffer&&(n=new Uint8Array(n)),t.Xhr.ArrayBufferView&&n instanceof t.Xhr.ArrayBufferView&&(o||(o="application/octet-stream"),n=new Blob([n],{type:o})),"undefined"!=typeof File&&n instanceof File&&(n=new Blob([n],{type:n.type})),s=n instanceof Blob):s=!1,s?(this.body=new FormData,this.body.append(e,n,r)):(o||(o="application/octet-stream"),i=this.multipartBoundary(),this.headers["Content-Type"]="multipart/form-data; boundary="+i,this.body=["--",i,"\r\n",'Content-Disposition: form-data; name="',e,'"; filename="',r,'"\r\n',"Content-Type: ",o,"\r\n","Content-Transfer-Encoding: binary\r\n\r\n",n,"\r\n","--",i,"--","\r\n"].join(""))},e.prototype.multipartBoundary=function(){return[Date.now().toString(36),Math.random().toString(36)].join("----")},e.prototype.paramsToUrl=function(){var e;return this.params&&(e=t.Xhr.urlEncode(this.params),0!==e.length&&(this.url=[this.url,"?",e].join("")),this.params=null),this},e.prototype.paramsToBody=function(){if(this.params){if(null!==this.body)throw Error("Request already has a body");if(this.isGet)throw Error("paramsToBody cannot be called on GET requests");this.headers["Content-Type"]="application/x-www-form-urlencoded",this.body=t.Xhr.urlEncode(this.params),this.params=null}return this},e.prototype.prepare=function(){var e,r,n,o,i=this;if(r=t.Xhr.ieXdr,this.isGet||null!==this.body||r?(this.paramsToUrl(),null!==this.body&&"string"==typeof this.body&&(this.headers["Content-Type"]="text/plain; charset=utf8")):this.paramsToBody(),this.xhr=new t.Xhr.Request,r?(this.xhr.onload=function(){return i.onXdrLoad()},this.xhr.onerror=function(){return i.onXdrError()},this.xhr.ontimeout=function(){return i.onXdrError()},this.xhr.onprogress=function(){}):this.xhr.onreadystatechange=function(){return i.onReadyStateChange()},this.xhr.open(this.method,this.url,!0),!r){o=this.headers;for(e in o)E.call(o,e)&&(n=o[e],this.xhr.setRequestHeader(e,n))}return this.responseType&&("b"===this.responseType?this.xhr.overrideMimeType&&this.xhr.overrideMimeType("text/plain; charset=x-user-defined"):this.xhr.responseType=this.responseType),this},e.prototype.send=function(e){var r;if(this.callback=e||this.callback,null!==this.body){r=this.body,t.Xhr.ArrayBufferView&&r instanceof ArrayBuffer&&(r=new Uint8Array(r));try{this.xhr.send(r)}catch(n){if(!("undefined"!=typeof Blob&&t.Xhr.ArrayBufferView&&r instanceof t.Xhr.ArrayBufferView))throw n;r=new Blob([r],{type:"application/octet-stream"}),this.xhr.send(r)}}else this.xhr.send();return this},e.urlEncode=function(t){var e,r,n;e=[];for(r in t)n=t[r],e.push(this.urlEncodeValue(r)+"="+this.urlEncodeValue(n));return e.sort().join("&")},e.urlEncodeValue=function(t){return encodeURIComponent(""+t).replace(/\!/g,"%21").replace(/'/g,"%27").replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/\*/g,"%2A")},e.urlDecode=function(t){var e,r,n,o,i,s;for(r={},s=t.split("&"),o=0,i=s.length;i>o;o++)n=s[o],e=n.split("="),r[decodeURIComponent(e[0])]=decodeURIComponent(e[1]);return r},e.prototype.onReadyStateChange=function(){var e,r,n,o,i,s,a,h,u;if(4!==this.xhr.readyState)return!0;if(200>this.xhr.status||this.xhr.status>=300)return e=new t.ApiError(this.xhr,this.method,this.url),this.onError&&this.onError.dispatch(e),this.callback(e),!0;if(s=this.xhr.getResponseHeader("x-dropbox-metadata"),null!=s?s.length:void 0)try{i=JSON.parse(s)}catch(l){i=void 0}else i=void 0;if(this.responseType){if("b"===this.responseType){for(n=null!=this.xhr.responseText?this.xhr.responseText:this.xhr.response,r=[],o=h=0,u=n.length;u>=0?u>h:h>u;o=u>=0?++h:--h)r.push(String.fromCharCode(255&n.charCodeAt(o)));a=r.join(""),this.callback(null,a,i)}else this.callback(null,this.xhr.response,i);return!0}switch(a=null!=this.xhr.responseText?this.xhr.responseText:this.xhr.response,this.xhr.getResponseHeader("Content-Type")){case"application/x-www-form-urlencoded":this.callback(null,t.Xhr.urlDecode(a),i);break;case"application/json":case"text/javascript":this.callback(null,JSON.parse(a),i);break;default:this.callback(null,a,i)}return!0},e.prototype.onXdrLoad=function(){var e;switch(e=this.xhr.responseText,this.xhr.contentType){case"application/x-www-form-urlencoded":this.callback(null,t.Xhr.urlDecode(e),void 0);break;case"application/json":case"text/javascript":this.callback(null,JSON.parse(e),void 0);break;default:this.callback(null,e,void 0)}return!0},e.prototype.onXdrError=function(){var e;return e=new t.ApiError(this.xhr,this.method,this.url),this.onError&&this.onError.dispatch(e),this.callback(e),!0},e}(),null!=("undefined"!=typeof module&&null!==module?module.exports:void 0))module.exports=t;else{if("undefined"==typeof window||null===window)throw Error("This library only supports node.js and modern browsers.");window.Dropbox=t}t.atob=u,t.btoa=f,t.hmac=c,t.sha1=d,t.encodeKey=m}).call(this);
\ No newline at end of file
diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/lib/jquery.js b/lib/client/storage/dropbox/samples/checkbox.js/public/lib/jquery.js
deleted file mode 100644
index 83589daa..00000000
--- a/lib/client/storage/dropbox/samples/checkbox.js/public/lib/jquery.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! jQuery v1.8.3 jquery.com | jquery.org/license */
-(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write(""),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t a ",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="
",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;ti.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML=" ",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML=" ";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="
",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="
",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r ",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="
",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML=" ",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t0)for(i=r;i=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/ ]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*\s*$/g,Nt={option:[1,""," "],legend:[1,""," "],thead:[1,""],tr:[2,""],td:[3,""],col:[2,""],area:[1,""," "],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X ","
"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1>$2>");try{for(;r1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1>$2>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]===""&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/
- Please close this window.
- """
- response.writeHead(200,
- {'Content-Length': closeHtml.length, 'Content-Type': 'text/html' })
- response.write closeHtml
- response.end
-
- # Renders the favicon file.
- sendFavicon: (response) ->
- @fs.readFile @faviconFile, (error, data) ->
- response.writeHead(200,
- { 'Content-Length': data.length, 'Content-Type': 'image/x-icon' })
- response.write data
- response.end
diff --git a/lib/client/storage/dropbox/src/drivers.coffee b/lib/client/storage/dropbox/src/drivers.coffee
deleted file mode 100644
index de555551..00000000
--- a/lib/client/storage/dropbox/src/drivers.coffee
+++ /dev/null
@@ -1,59 +0,0 @@
-# Documentation for the interface to a Dropbox OAuth driver.
-class Dropbox.AuthDriver
- # The callback URL that should be supplied to the OAuth /authorize call.
- #
- # The driver must be able to intercept redirects to the returned URL, in
- # order to know when a user has completed the authorization flow.
- #
- # @return {String} an absolute URL
- url: ->
- 'https://some.url'
-
- # Redirects users to /authorize and waits for them to complete the flow.
- #
- # This method is called when the OAuth process reaches the REQUEST state,
- # meaning the client has a request token that must be authorized by the user.
- #
- # @param {String} authUrl the URL that users should be sent to in order to
- # authorize the application's token; this points to a Web page on
- # Dropbox' servers
- # @param {String} token the OAuth token that the user is authorizing; this
- # will be provided by the Dropbox servers as a query parameter when the
- # user is redirected to the URL returned by the driver's url() method
- # @param {String} tokenSecret the secret associated with the given OAuth
- # token; the driver may store this together with the token
- # @param {function()} callback called when users have completed the
- # authorization flow; the driver should call this when Dropbox redirects
- # users to the URL returned by the url() method, and the 'token' query
- # parameter matches the value of the token parameter
- doAuthorize: (authUrl, token, tokenSecret, callback) ->
- callback 'oauth-token'
-
- # Called when there is some progress in the OAuth process.
- #
- # The OAuth process goes through the following states:
- #
- # * Dropbox.Client.RESET - the client has no OAuth token, and is about to
- # ask for a request token
- # * Dropbox.Client.REQUEST - the client has a request OAuth token, and the
- # user must go to an URL on the Dropbox servers to authorize the token
- # * Dropbox.Client.AUTHORIZED - the client has a request OAuth token that
- # was authorized by the user, and is about to exchange it for an access
- # token
- # * Dropbox.Client.DONE - the client has an access OAuth token that can be
- # used for all API calls; the OAuth process is complete, and the callback
- # passed to authorize is about to be called
- # * Dropbox.Client.SIGNED_OFF - the client's Dropbox.Client#signOut() was
- # called, and the client's OAuth token was invalidated
- # * Dropbox.Client.ERROR - the client encounered an error during the OAuth
- # process; the callback passed to authorize is about to be called with the
- # error information
- #
- # @param {Dropbox.Client} client the client performing the OAuth process
- # @param {function()} callback called when onAuthStateChange acknowledges the
- # state change
- onAuthStateChange: (client, callback) ->
- callback()
-
-# Namespace for authentication drivers.
-Dropbox.Drivers = {}
diff --git a/lib/client/storage/dropbox/src/event_source.coffee b/lib/client/storage/dropbox/src/event_source.coffee
deleted file mode 100644
index b87a3d3c..00000000
--- a/lib/client/storage/dropbox/src/event_source.coffee
+++ /dev/null
@@ -1,71 +0,0 @@
-# Event dispatch following a publisher-subscriber (PubSub) model.
-class Dropbox.EventSource
- # Sets up an event source (publisher).
- #
- # @param {?Object} options one or more of the options below
- # @option options {Boolean} cancelable if true,
- constructor: (options) ->
- @_cancelable = options and options.cancelable
- @_listeners = []
-
- # Registers a listener (subscriber) to events coming from this source.
- #
- # This is a simplified version of the addEventListener DOM API. Listeners
- # must be functions, and they can be removed by calling removeListener.
- #
- # This method is idempotent, so a function will not be added to the list of
- # listeners if was previously added.
- #
- # @param {function(Object)} listener called every time an event is fired; if
- # the event is cancelable, the function can return false to cancel the
- # event, or any other value to allow it to propagate; the return value is
- # ignored for non-cancelable events
- # @return {Dropbox.EventSource} this, for easy call chaining
- addListener: (listener) ->
- unless typeof listener is 'function'
- throw new TypeError 'Invalid listener type; expected function'
- unless listener in @_listeners
- @_listeners.push listener
- @
-
- # Un-registers a listener (subscriber) previously added by addListener.
- #
- # This is a simplified version of the removeEventListener DOM API. The
- # listener must be exactly the same object supplied to addListener.
- #
- # This method is idempotent, so it will fail silently if the given listener
- # is not registered as a subscriber.
- #
- # @param {function(Object)} listener function that was previously passed in
- # an addListener call
- # @return {Dropbox.EventSource} this, for easy call chaining
- removeListener: (listener) ->
- if @_listeners.indexOf
- # IE9+
- index = @_listeners.indexOf listener
- @_listeners.splice index, 1 if index isnt -1
- else
- # IE8 doesn't implement Array#indexOf in ES5.
- for subscriber, i in @_listeners
- if subscriber is listener
- @_listeners.splice i, 1
- break
- @
-
-
- # Informs the listeners (subscribers) that an event occurred.
- #
- # Event sources configured for non-cancelable events call all listeners in an
- # unspecified order. Sources configured for cancelable events stop calling
- # listeners as soon as one listener returns false value.
- #
- # @param {Object} event passed to all the registered listeners
- # @return {Boolean} sources of cancelable events return false if the event
- # was canceled and true otherwise; sources of non-cancelable events always
- # return true
- dispatch: (event) ->
- for listener in @_listeners
- returnValue = listener event
- if @_cancelable and returnValue is false
- return false
- true
diff --git a/lib/client/storage/dropbox/src/hmac.coffee b/lib/client/storage/dropbox/src/hmac.coffee
deleted file mode 100644
index b26be463..00000000
--- a/lib/client/storage/dropbox/src/hmac.coffee
+++ /dev/null
@@ -1,180 +0,0 @@
-# HMAC-SHA1 implementation heavily inspired from
-# http://pajhome.org.uk/crypt/md5/sha1.js
-
-# Base64-encoded HMAC-SHA1.
-#
-# @param {String} string the ASCII string to be signed
-# @param {String} key the HMAC key
-# @return {String} a base64-encoded HMAC of the given string and key
-base64HmacSha1 = (string, key) ->
- arrayToBase64 hmacSha1(stringToArray(string), stringToArray(key),
- string.length, key.length)
-
-# Base64-encoded SHA1.
-#
-# @param {String} string the ASCII string to be hashed
-# @return {String} a base64-encoded SHA1 hash of the given string
-base64Sha1 = (string) ->
- arrayToBase64 sha1(stringToArray(string), string.length)
-
-# SHA1 and HMAC-SHA1 versions that use the node.js builtin crypto.
-unless window?
- crypto = require 'crypto'
- base64HmacSha1 = (string, key) ->
- hmac = crypto.createHmac 'sha1', key
- hmac.update string
- hmac.digest 'base64'
- base64Sha1 = (string) ->
- hash = crypto.createHash 'sha1'
- hash.update string
- hash.digest 'base64'
-
-# HMAC-SHA1 implementation.
-#
-# @param {Array} string the HMAC input, as an array of 32-bit numbers
-# @param {Array} key the HMAC input, as an array of 32-bit numbers
-# @param {Number} length the length of the HMAC input, in bytes
-# @return {Array} the HMAC output, as an array of 32-bit numbers
-hmacSha1 = (string, key, length, keyLength) ->
- if key.length > 16
- key = sha1 key, keyLength
-
- ipad = (key[i] ^ 0x36363636 for i in [0...16])
- opad = (key[i] ^ 0x5C5C5C5C for i in [0...16])
-
- hash1 = sha1 ipad.concat(string), 64 + length
- sha1 opad.concat(hash1), 64 + 20
-
-# SHA1 implementation.
-#
-# @param {Array} string the SHA1 input, as an array of 32-bit numbers; the
-# computation trashes the array
-# @param {Number} length the number of bytes in the SHA1 input; used in the
-# SHA1 padding algorithm
-# @return {Array} the SHA1 output, as an array of 32-bit numbers
-sha1 = (string, length) ->
- string[length >> 2] |= 1 << (31 - ((length & 0x03) << 3))
- string[(((length + 8) >> 6) << 4) + 15] = length << 3
-
- state = Array 80
- a = 1732584193 # 0x67452301
- b = -271733879 # 0xefcdab89
- c = -1732584194 # 0x98badcfe
- d = 271733878 # 0x10325476
- e = -1009589776 # 0xc3d2e1f0
-
- i = 0
- limit = string.length
- # Uncomment the line below to debug packing.
- # console.log string.map(xxx)
- while i < limit
- a0 = a
- b0 = b
- c0 = c
- d0 = d
- e0 = e
-
- for j in [0...80]
- if j < 16
- state[j] = string[i + j]
- else
- state[j] = rotateLeft32 state[j - 3] ^ state[j - 8] ^ state[j - 14] ^
- state[j - 16], 1
- if j < 20
- ft = (b & c) | ((~b) & d)
- kt = 1518500249 # 0x5a827999
- else if j < 40
- ft = b ^ c ^ d
- kt = 1859775393 # 0x6ed9eba1
- else if j < 60
- ft = (b & c) | (b & d) | (c & d)
- kt = -1894007588 # 0x8f1bbcdc
- else
- ft = b ^ c ^ d
- kt = -899497514 # 0xca62c1d6
- t = add32 add32(rotateLeft32(a, 5), ft), add32(add32(e, state[j]), kt)
- e = d
- d = c
- c = rotateLeft32 b, 30
- b = a
- a = t
- # Uncomment the line below to debug block computation.
- # console.log [xxx(a), xxx(b), xxx(c), xxx(d), xxx(e)]
- a = add32 a, a0
- b = add32 b, b0
- c = add32 c, c0
- d = add32 d, d0
- e = add32 e, e0
- i += 16
- # Uncomment the line below to see the input to the base64 encoder.
- # console.log [xxx(a), xxx(b), xxx(c), xxx(d), xxx(e)]
- [a, b, c, d, e]
-
-###
-# Uncomment the definition below for debugging.
-#
-# Returns the hexadecimal representation of a 32-bit number.
-xxx = (n) ->
- if n < 0
- n = (1 << 30) * 4 + n
- n.toString 16
-###
-
-# Rotates a 32-bit word.
-#
-# @param {Number} value the 32-bit number to be rotated
-# @param {Number} count the number of bits (0..31) to rotate by
-# @return {Number} the rotated value
-rotateLeft32 = (value, count) ->
- (value << count) | (value >>> (32 - count))
-
-# 32-bit unsigned addition.
-#
-# @param {Number} a, b the 32-bit numbers to be added modulo 2^32
-# @return {Number} the 32-bit representation of a + b
-add32 = (a, b) ->
- low = (a & 0xFFFF) + (b & 0xFFFF)
- high = (a >> 16) + (b >> 16) + (low >> 16)
- (high << 16) | (low & 0xFFFF)
-
-# Converts a 32-bit number array into a base64-encoded string.
-#
-# @param {Array} an array of big-endian 32-bit numbers
-# @return {String} base64 encoding of the given array of numbers
-arrayToBase64 = (array) ->
- string = ""
- i = 0
- limit = array.length * 4
- while i < limit
- i2 = i
- trit = ((array[i2 >> 2] >> ((3 - (i2 & 3)) << 3)) & 0xFF) << 16
- i2 += 1
- trit |= ((array[i2 >> 2] >> ((3 - (i2 & 3)) << 3)) & 0xFF) << 8
- i2 += 1
- trit |= (array[i2 >> 2] >> ((3 - (i2 & 3)) << 3)) & 0xFF
-
- string += _base64Digits[(trit >> 18) & 0x3F]
- string += _base64Digits[(trit >> 12) & 0x3F]
- i += 1
- if i >= limit
- string += '='
- else
- string += _base64Digits[(trit >> 6) & 0x3F]
- i += 1
- if i >= limit
- string += '='
- else
- string += _base64Digits[trit & 0x3F]
- i += 1
- string
-
-_base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-# Converts an ASCII string into array of 32-bit numbers.
-stringToArray = (string) ->
- array = []
- mask = 0xFF
- for i in [0...string.length]
- array[i >> 2] |= (string.charCodeAt(i) & mask) << ((3 - (i & 3)) << 3)
- array
-
diff --git a/lib/client/storage/dropbox/src/oauth.coffee b/lib/client/storage/dropbox/src/oauth.coffee
deleted file mode 100644
index 823f90a5..00000000
--- a/lib/client/storage/dropbox/src/oauth.coffee
+++ /dev/null
@@ -1,162 +0,0 @@
-# Stripped-down OAuth implementation that works with the Dropbox API server.
-class Dropbox.Oauth
- # Creates an Oauth instance that manages an application's keys and token.
- #
- # @param {Object} options the following properties
- # @option options {String} key the Dropbox application's key (consumer key,
- # in OAuth vocabulary); browser-side applications should use
- # Dropbox.encodeKey to obtain an encoded key string, and pass it as the
- # key option
- # @option options {String} secret the Dropbox application's secret (consumer
- # secret, in OAuth vocabulary); browser-side applications should not use
- # the secret option; instead, they should pass the result of
- # Dropbox.encodeKey as the key option
- constructor: (options) ->
- @key = @k = null
- @secret = @s = null
- @token = null
- @tokenSecret = null
- @_appHash = null
- @reset options
-
- # Creates an Oauth instance that manages an application's keys and token.
- #
- # @see Dropbox.Oauth#constructor for options
- reset: (options) ->
- if options.secret
- @k = @key = options.key
- @s = @secret = options.secret
- @_appHash = null
- else if options.key
- @key = options.key
- @secret = null
- secret = atob dropboxEncodeKey(@key).split('|', 2)[1]
- [k, s] = secret.split '?', 2
- @k = decodeURIComponent k
- @s = decodeURIComponent s
- @_appHash = null
- else
- unless @k
- throw new Error('No API key supplied')
-
- if options.token
- @setToken options.token, options.tokenSecret
- else
- @setToken null, ''
-
- # Sets the OAuth token to be used for future requests.
- setToken: (token, tokenSecret) ->
- if token and (not tokenSecret)
- throw new Error('No secret supplied with the user token')
-
- @token = token
- @tokenSecret = tokenSecret || ''
-
- # This is part of signing, but it's set here so it can be cached.
- @hmacKey = Dropbox.Xhr.urlEncodeValue(@s) + '&' +
- Dropbox.Xhr.urlEncodeValue(tokenSecret)
- null
-
- # Computes the value of the Authorization HTTP header.
- #
- # This method mutates the params object, and removes all the OAuth-related
- # parameters from it.
- #
- # @param {String} method the HTTP method used to make the request ('GET',
- # 'POST', etc)
- # @param {String} url the HTTP URL (e.g. "http://www.example.com/photos")
- # that receives the request
- # @param {Object} params an associative array (hash) containing the HTTP
- # request parameters; the parameters should include the oauth_
- # parameters generated by calling {Dropbox.Oauth#boilerplateParams}
- # @return {String} the value to be used for the Authorization HTTP header
- authHeader: (method, url, params) ->
- @addAuthParams method, url, params
-
- # Collect all the OAuth parameters.
- oauth_params = []
- for param, value of params
- if param.substring(0, 6) == 'oauth_'
- oauth_params.push param
- oauth_params.sort()
-
- # Remove the parameters from the params hash and add them to the header.
- header = []
- for param in oauth_params
- header.push Dropbox.Xhr.urlEncodeValue(param) + '="' +
- Dropbox.Xhr.urlEncodeValue(params[param]) + '"'
- delete params[param]
-
- # NOTE: the space after the comma is optional in the OAuth spec, so we'll
- # skip it to save some bandwidth
- 'OAuth ' + header.join(',')
-
- # Generates OAuth-required HTTP parameters.
- #
- # This method mutates the params object, and adds the OAuth-related
- # parameters to it.
- #
- # @param {String} method the HTTP method used to make the request ('GET',
- # 'POST', etc)
- # @param {String} url the HTTP URL (e.g. "http://www.example.com/photos")
- # that receives the request
- # @param {Object} params an associative array (hash) containing the HTTP
- # request parameters; the parameters should include the oauth_
- # parameters generated by calling {Dropbox.Oauth#boilerplateParams}
- # @return {String} the value to be used for the Authorization HTTP header
- addAuthParams: (method, url, params) ->
- # Augment params with OAuth parameters.
- @boilerplateParams params
- params.oauth_signature = @signature method, url, params
- params
-
- # Adds boilerplate OAuth parameters to a request's parameter list.
- #
- # This should be called right before signing a request, to maximize the
- # chances that the OAuth timestamp will be fresh.
- #
- # @param {Object} params an associative array (hash) containing the
- # parameters for an OAuth request; the boilerplate parameters will be
- # added to this hash
- # @return {Object} params
- boilerplateParams: (params) ->
- params.oauth_consumer_key = @k
- params.oauth_nonce = @nonce()
- params.oauth_signature_method = 'HMAC-SHA1'
- params.oauth_token = @token if @token
- params.oauth_timestamp = Math.floor(Date.now() / 1000)
- params.oauth_version = '1.0'
- params
-
- # Generates a nonce for an OAuth request.
- #
- # @return {String} the nonce to be used as the oauth_nonce parameter
- nonce: ->
- Date.now().toString(36) + Math.random().toString(36)
-
- # Computes the signature for an OAuth request.
- #
- # @param {String} method the HTTP method used to make the request ('GET',
- # 'POST', etc)
- # @param {String} url the HTTP URL (e.g. "http://www.example.com/photos")
- # that receives the request
- # @param {Object} params an associative array (hash) containing the HTTP
- # request parameters; the parameters should include the oauth_
- # parameters generated by calling {Dropbox.Oauth#boilerplateParams}
- # @return {String} the signature, ready to be used as the oauth_signature
- # OAuth parameter
- signature: (method, url, params) ->
- string = method.toUpperCase() + '&' + Dropbox.Xhr.urlEncodeValue(url) +
- '&' + Dropbox.Xhr.urlEncodeValue(Dropbox.Xhr.urlEncode(params))
- base64HmacSha1 string, @hmacKey
-
- # @return {String} a string that uniquely identifies the OAuth application
- appHash: ->
- return @_appHash if @_appHash
- @_appHash = base64Sha1(@k).replace(/\=/g, '')
-
-
-# Polyfill for Internet Explorer 8.
-unless Date.now?
- Date.now = () ->
- (new Date()).getTime()
diff --git a/lib/client/storage/dropbox/src/prod.coffee b/lib/client/storage/dropbox/src/prod.coffee
deleted file mode 100644
index 3cc177b9..00000000
--- a/lib/client/storage/dropbox/src/prod.coffee
+++ /dev/null
@@ -1,36 +0,0 @@
-# Necessary bits to get a browser-side app in production.
-
-# Packs up a key and secret into a string, to bring script kiddies some pain.
-#
-# @param {String} key the application's API key
-# @param {String} secret the application's API secret
-# @return {String} encoded key string that can be passed as the key option to
-# the Dropbox.Client constructor
-dropboxEncodeKey = (key, secret) ->
- if secret
- secret = [encodeURIComponent(key), encodeURIComponent(secret)].join('?')
- key = for i in [0...(key.length / 2)]
- ((key.charCodeAt(i * 2) & 15) * 16) + (key.charCodeAt(i * 2 + 1) & 15)
- else
- [key, secret] = key.split '|', 2
- key = atob key
- key = (key.charCodeAt(i) for i in [0...key.length])
- secret = atob secret
-
- s = [0...256]
- y = 0
- for x in [0...256]
- y = (y + s[i] + key[x % key.length]) % 256
- [s[x], s[y]] = [s[y], s[x]]
-
- x = y = 0
- result = for z in [0...secret.length]
- x = (x + 1) % 256
- y = (y + s[x]) % 256
- [s[x], s[y]] = [s[y], s[x]]
- k = s[(s[x] + s[y]) % 256]
- String.fromCharCode((k ^ secret.charCodeAt(z)) % 256)
-
- key = (String.fromCharCode(key[i]) for i in [0...key.length])
- [btoa(key.join('')), btoa(result.join(''))].join '|'
-
diff --git a/lib/client/storage/dropbox/src/pulled_changes.coffee b/lib/client/storage/dropbox/src/pulled_changes.coffee
deleted file mode 100644
index 6bf7ebcd..00000000
--- a/lib/client/storage/dropbox/src/pulled_changes.coffee
+++ /dev/null
@@ -1,106 +0,0 @@
-# Wraps the result of pullChanges, describing the changes in a user's Dropbox.
-class Dropbox.PulledChanges
- # Creates a new Dropbox.PulledChanges instance from a /delta API call result.
- #
- # @param {?Object} deltaInfo the parsed JSON of a /delta API call result
- # @return {?Dropbox.PulledChanges} a Dropbox.PulledChanges instance wrapping
- # the given information; if the parameter does not look like parsed JSON,
- # it is returned as is
- @parse: (deltaInfo) ->
- if deltaInfo and typeof deltaInfo is 'object'
- new Dropbox.PulledChanges deltaInfo
- else
- deltaInfo
-
- # @property {Boolean} if true, the application should reset its copy of the
- # user's Dropbox before applying the changes described by this instance
- blankSlate: undefined
-
- # @property {String} encodes a cursor in the list of changes to a user's
- # Dropbox; a pullChanges call returns some changes at the cursor, and then
- # advance the cursor to account for the returned changes; the new cursor is
- # returned by pullChanges, and meant to be used by a subsequent pullChanges
- # call
- cursorTag: undefined
-
- # @property {Array an array with one entry for each
- # change to the user's Dropbox returned by a pullChanges call.
- changes: undefined
-
- # @property {Boolean} if true, the pullChanges call returned a subset of the
- # available changes, and the application should repeat the call
- # immediately to get more changes
- shouldPullAgain: undefined
-
- # @property {Boolean} if true, the API call will not have any more changes
- # available in the nearby future, so the application should wait for at
- # least 5 miuntes before issuing another pullChanges request
- shouldBackOff: undefined
-
- # Serializable representation of the pull cursor inside this object.
- #
- # @return {String} an ASCII string that can be passed to pullChanges instead
- # of this PulledChanges instance
- cursor: -> @cursorTag
-
- # Creates a new Dropbox.PulledChanges instance from a /delta API call result.
- #
- # @private
- # This constructor is used by Dropbox.PulledChanges, and should not be called
- # directly.
- #
- # @param {Object} deltaInfo the parsed JSON of a /delta API call result
- constructor: (deltaInfo) ->
- @blankSlate = deltaInfo.reset or false
- @cursorTag = deltaInfo.cursor
- @shouldPullAgain = deltaInfo.has_more
- @shouldBackOff = not @shouldPullAgain
- if deltaInfo.cursor and deltaInfo.cursor.length
- @changes = (Dropbox.PullChange.parse entry for entry in deltaInfo.entries)
- else
- @changes = []
-
-# Wraps a single change in a pullChanges result.
-class Dropbox.PullChange
- # Creates a Dropbox.PullChange instance wrapping an entry in a /delta result.
- #
- # @param {?Object} entry the parsed JSON of a single entry in a /delta API
- # call result
- # @return {?Dropbox.PullChange} a Dropbox.PullChange instance wrapping the
- # given entry of a /delta API call; if the parameter does not look like
- # parsed JSON, it is returned as is
- @parse: (entry) ->
- if entry and typeof entry is 'object'
- new Dropbox.PullChange entry
- else
- entry
-
- # @property {String} the path of the changed file or folder
- path: undefined
-
- # @property {Boolean} if true, this change is a deletion of the file or folder
- # at the change's path; if a folder is deleted, all its contents (files
- # and sub-folders) were also be deleted; pullChanges might not return
- # separate changes expressing for the files or sub-folders
- wasRemoved: undefined
-
- # @property {?Dropbox.Stat} a Stat instance containing updated information for
- # the file or folder; this is null if the change is a deletion
- stat: undefined
-
- # Creates a Dropbox.PullChange instance wrapping an entry in a /delta result.
- #
- # @private
- # This constructor is used by Dropbox.PullChange.parse, and should not be
- # called directly.
- #
- # @param {Object} entry the parsed JSON of a single entry in a /delta API
- # call result
- constructor: (entry) ->
- @path = entry[0]
- @stat = Dropbox.Stat.parse entry[1]
- if @stat
- @wasRemoved = false
- else
- @stat = null
- @wasRemoved = true
diff --git a/lib/client/storage/dropbox/src/references.coffee b/lib/client/storage/dropbox/src/references.coffee
deleted file mode 100644
index d7602c5f..00000000
--- a/lib/client/storage/dropbox/src/references.coffee
+++ /dev/null
@@ -1,119 +0,0 @@
-# Wraps an URL to a Dropbox file or folder that can be publicly shared.
-class Dropbox.PublicUrl
- # Creates a PublicUrl instance from a raw API response.
- #
- # @param {?Object, ?String} urlData the parsed JSON describing a public URL
- # @param {?Boolean} isDirect true if this is a direct download link, false if
- # is a file / folder preview link
- # @return {?Dropbox.PublicUrl} a PublicUrl instance wrapping the given public
- # link info; parameters that don't look like parsed JSON are returned as
- # they are
- @parse: (urlData, isDirect) ->
- if urlData and typeof urlData is 'object'
- new Dropbox.PublicUrl urlData, isDirect
- else
- urlData
-
- # @property {String} the public URL
- url: null
-
- # @property {Date} after this time, the URL is not usable
- expiresAt: null
-
- # @property {Boolean} true if this is a direct download URL, false for URLs to
- # preview pages in the Dropbox web app; folders do not have direct link
- #
- isDirect: null
-
- # @property {Boolean} true if this is URL points to a file's preview page in
- # Dropbox, false for direct links
- isPreview: null
-
- # JSON representation of this file / folder's metadata
- #
- # @return {Object} conforms to the JSON restrictions; can be passed to
- # Dropbox.PublicUrl#parse to obtain an identical PublicUrl instance
- json: ->
- # HACK: this can break if the Dropbox API ever decides to use 'direct' in
- # its link info
- @_json ||= url: @url, expires: @expiresAt.toString(), direct: @isDirect
-
- # Creates a PublicUrl instance from a raw API response.
- #
- # @private
- # This constructor is used by Dropbox.PublicUrl.parse, and should not be
- # called directly.
- #
- # @param {?Object} urlData the parsed JSON describing a public URL
- # @param {Boolean} isDirect true if this is a direct download link, false if
- # is a file / folder preview link
- constructor: (urlData, isDirect) ->
- @url = urlData.url
- @expiresAt = new Date Date.parse(urlData.expires)
-
- if isDirect is true
- @isDirect = true
- else if isDirect is false
- @isDirect = false
- else
- # HACK: this can break if the Dropbox API ever decides to use 'direct' in
- # its link info; unfortunately, there's no elegant way to guess
- # between direct download URLs and preview URLs
- if 'direct' of urlData
- @isDirect = urlData.direct
- else
- @isDirect = Date.now() - @expiresAt <= 86400000 # 1 day
- @isPreview = !@isDirect
-
- # The JSON representation is created on-demand, to avoid unnecessary object
- # creation.
- # We can't use the original JSON object because we add a 'direct' field.
- @_json = null
-
-# Reference to a file that can be used to make a copy across users' Dropboxes.
-class Dropbox.CopyReference
- # Creates a CopyReference instance from a raw reference or API response.
- #
- # @param {?Object, ?String} refData the parsed JSON describing a copy
- # reference, or the reference string
- @parse: (refData) ->
- if refData and (typeof refData is 'object' or typeof refData is 'string')
- new Dropbox.CopyReference refData
- else
- refData
-
- # @property {String} the raw reference, for use with Dropbox APIs
- tag: null
-
- # @property {Date} deadline for using the reference in a copy operation
- expiresAt: null
-
- # JSON representation of this file / folder's metadata
- #
- # @return {Object} conforms to the JSON restrictions; can be passed to
- # Dropbox.CopyReference#parse to obtain an identical CopyReference instance
- json: ->
- # NOTE: the assignment only occurs if the CopyReference was built around a
- # string; CopyReferences parsed from API responses hold onto the
- # original JSON
- @_json ||= copy_ref: @tag, expires: @expiresAt.toString()
-
- # Creates a CopyReference instance from a raw reference or API response.
- #
- # @private
- # This constructor is used by Dropbox.CopyReference.parse, and should not be
- # called directly.
- #
- # @param {Object, String} refData the parsed JSON describing a copy
- # reference, or the reference string
- constructor: (refData) ->
- if typeof refData is 'object'
- @tag = refData.copy_ref
- @expiresAt = new Date Date.parse(refData.expires)
- @_json = refData
- else
- @tag = refData
- @expiresAt = new Date Math.ceil(Date.now() / 1000) * 1000
- # The JSON representation is created on-demand, to avoid unnecessary
- # object creation.
- @_json = null
diff --git a/lib/client/storage/dropbox/src/stat.coffee b/lib/client/storage/dropbox/src/stat.coffee
deleted file mode 100644
index ea3db318..00000000
--- a/lib/client/storage/dropbox/src/stat.coffee
+++ /dev/null
@@ -1,135 +0,0 @@
-# The result of stat-ing a file or directory in a user's Dropbox.
-class Dropbox.Stat
- # Creates a Stat instance from a raw "metadata" response.
- #
- # @param {?Object} metadata the result of parsing JSON API responses that are
- # called "metadata" in the API documentation
- # @return {?Dropbox.Stat} a Stat instance wrapping the given API response;
- # parameters that aren't parsed JSON objects are returned as they are
- @parse: (metadata) ->
- if metadata and typeof metadata is 'object'
- new Dropbox.Stat metadata
- else
- metadata
-
- # @property {String} the path of this file or folder, relative to the user's
- # Dropbox or to the application's folder
- path: null
-
- # @property {String} the name of this file or folder
- name: null
-
- # @property {Boolean} if true, the file or folder's path is relative to the
- # application's folder; otherwise, the path is relative to the user's
- # Dropbox
- inAppFolder: null
-
- # @property {Boolean} if true, this Stat instance describes a folder
- isFolder: null
-
- # @property {Boolean} if true, this Stat instance describes a file
- isFile: null
-
- # @property {Boolean} if true, the file or folder described by this Stat
- # instance was from the user's Dropbox, and was obtained by an API call
- # that returns deleted items
- isRemoved: null
-
- # @property {String} name of an icon in Dropbox's icon library that most
- # accurately represents this file or folder
- #
- # See the Dropbox API documentation to obtain the Dropbox icon library.
- # https://www.dropbox.com/developers/reference/api#metadata
- typeIcon: null
-
- # @property {String} an identifier for the contents of the described file or
- # directories; this can used to be restored a file's contents to a
- # previous version, or to save bandwidth by not retrieving the same
- # folder contents twice
- versionTag: null
-
- # @property {String} a guess of the MIME type representing the file or
- # folder's contents
- mimeType: null
-
- # @property {Number} the size of the file, in bytes; null for folders
- size: null
-
- # @property {String} the size of the file, in a human-readable format, such
- # as "225.4KB"; the format of this string is influenced by the API client's
- # locale
- humanSize: null
-
- # @property {Boolean} if false, the URL generated by thumbnailUrl does not
- # point to a valid image, and should not be used
- hasThumbnail: null
-
- # @property {Date} the file or folder's last modification time
- modifiedAt: null
-
- # @property {?Date} the file or folder's last modification time, as reported
- # by the Dropbox client that uploaded the file; this time should not be
- # trusted, but can be used for UI (display, sorting); null if the server
- # does not report any time
- clientModifiedAt: null
-
- # JSON representation of this file / folder's metadata
- #
- # @return {Object} conforms to the JSON restrictions; can be passed to
- # Dropbox.Stat#parse to obtain an identical Stat instance
- json: ->
- @_json
-
- # Creates a Stat instance from a raw "metadata" response.
- #
- # @private
- # This constructor is used by Dropbox.Stat.parse, and should not be called
- # directly.
- #
- # @param {Object} metadata the result of parsing JSON API responses that are
- # called "metadata" in the API documentation
- constructor: (metadata) ->
- @_json = metadata
- @path = metadata.path
- # Ensure there is a trailing /, to make path processing reliable.
- @path = '/' + @path if @path.substring(0, 1) isnt '/'
- # Strip any trailing /, to make path joining predictable.
- lastIndex = @path.length - 1
- if lastIndex >= 0 and @path.substring(lastIndex) is '/'
- @path = @path.substring 0, lastIndex
-
- nameSlash = @path.lastIndexOf '/'
- @name = @path.substring nameSlash + 1
-
- @isFolder = metadata.is_dir || false
- @isFile = !@isFolder
- @isRemoved = metadata.is_deleted || false
- @typeIcon = metadata.icon
- if metadata.modified?.length
- @modifiedAt = new Date Date.parse(metadata.modified)
- else
- @modifiedAt = null
- if metadata.client_mtime?.length
- @clientModifiedAt = new Date Date.parse(metadata.client_mtime)
- else
- @clientModifiedAt = null
-
- switch metadata.root
- when 'dropbox'
- @inAppFolder = false
- when 'app_folder'
- @inAppFolder = true
- else
- # New "root" value that we're not aware of.
- @inAppFolder = null
-
- @size = metadata.bytes or 0
- @humanSize = metadata.size or ''
- @hasThumbnail = metadata.thumb_exists or false
-
- if @isFolder
- @versionTag = metadata.hash
- @mimeType = metadata.mime_type || 'inode/directory'
- else
- @versionTag = metadata.rev
- @mimeType = metadata.mime_type || 'application/octet-stream'
diff --git a/lib/client/storage/dropbox/src/upload_cursor.coffee b/lib/client/storage/dropbox/src/upload_cursor.coffee
deleted file mode 100644
index 5e660102..00000000
--- a/lib/client/storage/dropbox/src/upload_cursor.coffee
+++ /dev/null
@@ -1,59 +0,0 @@
-# Tracks the progress of a resumable upload.
-class Dropbox.UploadCursor
- # Creates an UploadCursor instance from an API response.
- #
- # @param {?Object, ?String} cursorData the parsed JSON describing the status
- # of a partial upload, or the upload ID string
- @parse: (cursorData) ->
- if cursorData and (typeof cursorData is 'object' or
- typeof cursorData is 'string')
- new Dropbox.UploadCursor cursorData
- else
- cursorData
-
- # @property {String} the server-generated ID for this upload
- tag: null
-
- # @property {Number} number of bytes that have already been uploaded
- offset: null
-
- # @property {Date} deadline for finishing the upload
- expiresAt: null
-
- # JSON representation of this cursor.
- #
- # @return {Object} conforms to the JSON restrictions; can be passed to
- # Dropbox.UploadCursor#parse to obtain an identical UploadCursor instance
- json: ->
- # NOTE: the assignment only occurs if
- @_json ||= upload_id: @tag, offset: @offset, expires: @expiresAt.toString()
-
- # Creates an UploadCursor instance from a raw reference or API response.
- #
- # This constructor should only be called directly to obtain a cursor for a
- # new file upload. Dropbox.UploadCursor#parse should be called instead
- #
- # @param {?Object, ?String} cursorData the parsed JSON describing a copy
- # reference, or the reference string
- constructor: (cursorData) ->
- @replace cursorData
-
- # Replaces the current
- #
- # @private Called by Dropbox.Client#resumableUploadStep.
- #
- # @param {?Object, ?String} cursorData the parsed JSON describing a copy
- # reference, or the reference string
- # @return {Dropbox.UploadCursor} this
- replace: (cursorData) ->
- if typeof cursorData is 'object'
- @tag = cursorData.upload_id or null
- @offset = cursorData.offset or 0
- @expiresAt = new Date(Date.parse(cursorData.expires) or Date.now())
- @_json = cursorData
- else
- @tag = cursorData or null
- @offset = 0
- @expiresAt = new Date Math.floor(Date.now() / 1000) * 1000
- @_json = null
- @
diff --git a/lib/client/storage/dropbox/src/user_info.coffee b/lib/client/storage/dropbox/src/user_info.coffee
deleted file mode 100644
index ba6dbea2..00000000
--- a/lib/client/storage/dropbox/src/user_info.coffee
+++ /dev/null
@@ -1,88 +0,0 @@
-# Information about a Dropbox user.
-class Dropbox.UserInfo
- # Creates a UserInfo instance from a raw API response.
- #
- # @param {?Object} userInfo the result of parsing a JSON API response that
- # describes a user
- # @return {Dropbox.UserInfo} a UserInfo instance wrapping the given API
- # response; parameters that aren't parsed JSON objects are returned as
- # the are
- @parse: (userInfo) ->
- if userInfo and typeof userInfo is 'object'
- new Dropbox.UserInfo userInfo
- else
- userInfo
-
- # @property {String} the user's name, in a form that is fit for display
- name: null
-
- # @property {?String} the user's email; this is not in the official API
- # documentation, so it might not be supported
- email: null
-
- # @property {?String} two-letter country code, or null if unavailable
- countryCode: null
-
- # @property {String} unique ID for the user; this ID matches the unique ID
- # returned by the authentication process
- uid: null
-
- # @property {String} the user's referral link; the user might benefit if
- # others use the link to sign up for Dropbox
- referralUrl: null
-
- # Specific to applications whose access type is "public app folder".
- #
- # @property {String} prefix for URLs to the application's files
- publicAppUrl: null
-
- # @property {Number} the maximum amount of bytes that the user can store
- quota: null
-
- # @property {Number} the number of bytes taken up by the user's data
- usedQuota: null
-
- # @property {Number} the number of bytes taken up by the user's data that is
- # not shared with other users
- privateBytes: null
-
- # @property {Number} the number of bytes taken up by the user's data that is
- # shared with other users
- sharedBytes: null
-
- # JSON representation of this user's information.
- #
- # @return {Object} conforms to the JSON restrictions; can be passed to
- # Dropbox.UserInfo#parse to obtain an identical UserInfo instance
- json: ->
- @_json
-
- # Creates a UserInfo instance from a raw API response.
- #
- # @private
- # This constructor is used by Dropbox.UserInfo.parse, and should not be
- # called directly.
- #
- # @param {Object} userInfo the result of parsing a JSON API response that
- # describes a user
- constructor: (userInfo) ->
- @_json = userInfo
- @name = userInfo.display_name
- @email = userInfo.email
- @countryCode = userInfo.country or null
- @uid = userInfo.uid.toString()
- if userInfo.public_app_url
- @publicAppUrl = userInfo.public_app_url
- lastIndex = @publicAppUrl.length - 1
- # Strip any trailing /, to make path joining predictable.
- if lastIndex >= 0 and @publicAppUrl.substring(lastIndex) is '/'
- @publicAppUrl = @publicAppUrl.substring 0, lastIndex
- else
- @publicAppUrl = null
-
- @referralUrl = userInfo.referral_link
- @quota = userInfo.quota_info.quota
- @privateBytes = userInfo.quota_info.normal or 0
- @sharedBytes = userInfo.quota_info.shared or 0
- @usedQuota = @privateBytes + @sharedBytes
-
diff --git a/lib/client/storage/dropbox/src/xhr.coffee b/lib/client/storage/dropbox/src/xhr.coffee
deleted file mode 100644
index 63051828..00000000
--- a/lib/client/storage/dropbox/src/xhr.coffee
+++ /dev/null
@@ -1,505 +0,0 @@
-if window?
- if window.XDomainRequest and not ('withCredentials' of new XMLHttpRequest())
- DropboxXhrRequest = window.XDomainRequest
- DropboxXhrIeMode = true
- # IE's XDR doesn't allow setting requests' Content-Type to anything other
- # than text/plain, so it can't send _any_ forms.
- DropboxXhrCanSendForms = false
- else
- DropboxXhrRequest = window.XMLHttpRequest
- DropboxXhrIeMode = false
- # Firefox doesn't support adding named files to FormData.
- # https://bugzilla.mozilla.org/show_bug.cgi?id=690659
- DropboxXhrCanSendForms =
- window.navigator.userAgent.indexOf('Firefox') is -1
- DropboxXhrDoesPreflight = true
-else
- # Node.js needs an adapter for the XHR API.
- DropboxXhrRequest = require('xmlhttprequest').XMLHttpRequest
- DropboxXhrIeMode = false
- # Node.js doesn't have FormData. We wouldn't want to bother putting together
- # upload forms in node.js anyway, because it doesn't do CORS preflight
- # checks, so we can use PUT requests without a performance hit.
- DropboxXhrCanSendForms = false
- # Node.js is a server so it doesn't do annoying browser checks.
- DropboxXhrDoesPreflight = false
-
-# ArrayBufferView isn't available in the global namespce.
-#
-# Using the hack suggested in
-# https://code.google.com/p/chromium/issues/detail?id=60449
-if typeof Uint8Array is 'undefined'
- DropboxXhrArrayBufferView = null
- DropboxXhrSendArrayBufferView = false
-else
- if Object.getPrototypeOf
- DropboxXhrArrayBufferView = Object.getPrototypeOf(
- Object.getPrototypeOf(new Uint8Array(0))).constructor
- else if Object.__proto__
- DropboxXhrArrayBufferView =
- (new Uint8Array(0)).__proto__.__proto__.constructor
-
- # Browsers that haven't implemented XHR#send(ArrayBufferView) also don't
- # have a real ArrayBufferView prototype. (Safari, Firefox)
- DropboxXhrSendArrayBufferView = DropboxXhrArrayBufferView isnt Object
-
-# Dispatches low-level AJAX calls (XMLHttpRequests).
-class Dropbox.Xhr
- # The object used to perform AJAX requests (XMLHttpRequest).
- @Request = DropboxXhrRequest
- # Set to true when using the XDomainRequest API.
- @ieXdr = DropboxXhrIeMode
- # Set to true if the platform has proper support for FormData.
- @canSendForms = DropboxXhrCanSendForms
- # Set to true if the platform performs CORS preflight checks.
- @doesPreflight = DropboxXhrDoesPreflight
- # Superclass for all ArrayBufferView objects.
- @ArrayBufferView = DropboxXhrArrayBufferView
- # Set to true if we think we can send ArrayBufferView objects via XHR.
- @sendArrayBufferView = DropboxXhrSendArrayBufferView
-
-
- # Sets up an AJAX request.
- #
- # @param {String} method the HTTP method used to make the request ('GET',
- # 'POST', 'PUT', etc.)
- # @param {String} baseUrl the URL that receives the request; this URL might
- # be modified, e.g. by appending parameters for GET requests
- constructor: (@method, baseUrl) ->
- @isGet = @method is 'GET'
- @url = baseUrl
- @headers = {}
- @params = null
- @body = null
- @preflight = not (@isGet or (@method is 'POST'))
- @signed = false
- @responseType = null
- @callback = null
- @xhr = null
- @onError = null
-
- # @property {?XMLHttpRequest} the raw XMLHttpRequest object used to make the
- # request; null until Dropbox.Xhr#prepare is called
- xhr: null
-
- # @property {?Dropbox.EventSource} if the XHR fails and
- # this property is set, the Dropbox.ApiError instance that will be passed
- # to the callback will be dispatched through the Dropbox.EventSource; the
- # EventSource should be configured for non-cancelable events
- onError: null
-
- # Sets the parameters (form field values) that will be sent with the request.
- #
- # @param {?Object} params an associative array (hash) containing the HTTP
- # request parameters
- # @return {Dropbox.Xhr} this, for easy call chaining
- setParams: (params) ->
- if @signed
- throw new Error 'setParams called after addOauthParams or addOauthHeader'
- if @params
- throw new Error 'setParams cannot be called twice'
- @params = params
- @
-
- # Sets the function called when the XHR completes.
- #
- # This function can also be set when calling Dropbox.Xhr#send.
- #
- # @param {function(?Dropbox.ApiError, ?Object, ?Object)} callback called when
- # the XHR completes; if an error occurs, the first parameter will be a
- # Dropbox.ApiError instance; otherwise, the second parameter will be an
- # instance of the required response type (e.g., String, Blob), and the
- # third parameter will be the JSON-parsed 'x-dropbox-metadata' header
- # @return {Dropbox.Xhr} this, for easy call chaining
- setCallback: (@callback) ->
- @
-
- # Ammends the request parameters to include an OAuth signature.
- #
- # The OAuth signature will become invalid if the parameters are changed after
- # the signing process.
- #
- # This method automatically decides the best way to add the OAuth signature
- # to the current request. Modifying the request in any way (e.g., by adding
- # headers) might result in a valid signature that is applied in a sub-optimal
- # fashion. For best results, call this right before Dropbox.Xhr#prepare.
- #
- # @param {Dropbox.Oauth} oauth OAuth instance whose key and secret will be
- # used to sign the request
- # @param {Boolean} cacheFriendly if true, the signing process choice will be
- # biased towards allowing the HTTP cache to work; by default, the choice
- # attempts to avoid the CORS preflight request whenever possible
- # @return {Dropbox.Xhr} this, for easy call chaining
- signWithOauth: (oauth, cacheFriendly) ->
- if Dropbox.Xhr.ieXdr
- @addOauthParams oauth
- else if @preflight or !Dropbox.Xhr.doesPreflight
- @addOauthHeader oauth
- else
- if @isGet and cacheFriendly
- @addOauthHeader oauth
- else
- @addOauthParams oauth
-
- # Ammends the request parameters to include an OAuth signature.
- #
- # The OAuth signature will become invalid if the parameters are changed after
- # the signing process.
- #
- # @param {Dropbox.Oauth} oauth OAuth instance whose key and secret will be
- # used to sign the request
- # @return {Dropbox.Xhr} this, for easy call chaining
- addOauthParams: (oauth) ->
- if @signed
- throw new Error 'Request already has an OAuth signature'
-
- @params or= {}
- oauth.addAuthParams @method, @url, @params
- @signed = true
- @
-
- # Adds an Authorize header containing an OAuth signature.
- #
- # The OAuth signature will become invalid if the parameters are changed after
- # the signing process.
- #
- # @param {Dropbox.Oauth} oauth OAuth instance whose key and secret will be
- # used to sign the request
- # @return {Dropbox.Xhr} this, for easy call chaining
- addOauthHeader: (oauth) ->
- if @signed
- throw new Error 'Request already has an OAuth signature'
-
- @params or= {}
- @signed = true
- @setHeader 'Authorization', oauth.authHeader(@method, @url, @params)
-
- # Sets the body (piece of data) that will be sent with the request.
- #
- # @param {String, Blob, ArrayBuffer} body the body to be sent in a request;
- # GET requests cannot have a body
- # @return {Dropbox.Xhr} this, for easy call chaining
- setBody: (body) ->
- if @isGet
- throw new Error 'setBody cannot be called on GET requests'
- if @body isnt null
- throw new Error 'Request already has a body'
-
- if typeof body is 'string'
- # Content-Type will be set automatically.
- else if (typeof FormData isnt 'undefined') and (body instanceof FormData)
- # Content-Type will be set automatically.
- else
- @headers['Content-Type'] = 'application/octet-stream'
- @preflight = true
-
- @body = body
- @
-
- # Sends off an AJAX request and requests a custom response type.
- #
- # This method requires XHR Level 2 support, which is not available in IE
- # versions <= 9. If these browsers must be supported, it is recommended to
- # check whether window.Blob is truthy.
- #
- # @param {String} responseType the value that will be assigned to the XHR's
- # responseType property
- # @return {Dropbox.Xhr} this, for easy call chaining
- setResponseType: (@responseType) ->
- @
-
- # Sets the value of a custom HTTP header.
- #
- # Custom HTTP headers require a CORS preflight in browsers, so requests that
- # use them will take more time to complete, especially on high-latency mobile
- # connections.
- #
- # @param {String} headerName the name of the HTTP header
- # @param {String} value the value that the header will be set to
- # @return {Dropbox.Xhr} this, for easy call chaining
- setHeader: (headerName, value) ->
- if @headers[headerName]
- oldValue = @headers[headerName]
- throw new Error "HTTP header #{headerName} already set to #{oldValue}"
- if headerName is 'Content-Type'
- throw new Error 'Content-Type is automatically computed based on setBody'
- @preflight = true
- @headers[headerName] = value
- @
-
- # Simulates having an being sent with the request.
- #
- # @param {String} fieldName the name of the form field / parameter (not of
- # the uploaded file)
- # @param {String} fileName the name of the uploaded file (not the name of the
- # form field / parameter)
- # @param {String, Blob, File} fileData contents of the file to be uploaded
- # @param {?String} contentType the MIME type of the file to be uploaded; if
- # fileData is a Blob or File, its MIME type is used instead
- setFileField: (fieldName, fileName, fileData, contentType) ->
- if @body isnt null
- throw new Error 'Request already has a body'
-
- if @isGet
- throw new Error 'setFileField cannot be called on GET requests'
-
- if typeof(fileData) is 'object' and typeof Blob isnt 'undefined'
- if typeof ArrayBuffer isnt 'undefined'
- if fileData instanceof ArrayBuffer
- # Convert ArrayBuffer -> ArrayBufferView on standard-compliant
- # browsers, to avoid warnings from the Blob constructor.
- if Dropbox.Xhr.sendArrayBufferView
- fileData = new Uint8Array fileData
- else
- # Convert ArrayBufferView -> ArrayBuffer on older browsers, to avoid
- # having a Blob that contains "[object Uint8Array]" instead of the
- # actual data.
- if !Dropbox.Xhr.sendArrayBufferView and fileData.byteOffset is 0 and
- fileData.buffer instanceof ArrayBuffer
- fileData = fileData.buffer
-
- contentType or= 'application/octet-stream'
- fileData = new Blob [fileData], type: contentType
-
- # Workaround for http://crbug.com/165095
- if typeof File isnt 'undefined' and fileData instanceof File
- fileData = new Blob [fileData], type: fileData.type
- #fileData = fileData
- useFormData = fileData instanceof Blob
- else
- useFormData = false
-
- if useFormData
- @body = new FormData()
- @body.append fieldName, fileData, fileName
- else
- contentType or= 'application/octet-stream'
- boundary = @multipartBoundary()
- @headers['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
- @body = ['--', boundary, "\r\n",
- 'Content-Disposition: form-data; name="', fieldName,
- '"; filename="', fileName, "\"\r\n",
- 'Content-Type: ', contentType, "\r\n",
- "Content-Transfer-Encoding: binary\r\n\r\n",
- fileData,
- "\r\n", '--', boundary, '--', "\r\n"].join ''
-
- # @private
- # @return {String} a nonce suitable for use as a part boundary in a multipart
- # MIME message
- multipartBoundary: ->
- [Date.now().toString(36), Math.random().toString(36)].join '----'
-
- # Moves this request's parameters to its URL.
- #
- # @private
- # @return {Dropbox.Xhr} this, for easy call chaining
- paramsToUrl: ->
- if @params
- queryString = Dropbox.Xhr.urlEncode @params
- if queryString.length isnt 0
- @url = [@url, '?', queryString].join ''
- @params = null
- @
-
- # Moves this request's parameters to its body.
- #
- # @private
- # @return {Dropbox.Xhr} this, for easy call chaining
- paramsToBody: ->
- if @params
- if @body isnt null
- throw new Error 'Request already has a body'
- if @isGet
- throw new Error 'paramsToBody cannot be called on GET requests'
- @headers['Content-Type'] = 'application/x-www-form-urlencoded'
- @body = Dropbox.Xhr.urlEncode @params
- @params = null
- @
-
- # Sets up an XHR request.
- #
- # This method completely sets up a native XHR object and stops short of
- # calling its send() method, so the API client has a chance of customizing
- # the XHR. After customizing the XHR, Dropbox.Xhr#send should be called.
- #
- #
- # @return {Dropbox.Xhr} this, for easy call chaining
- prepare: ->
- ieXdr = Dropbox.Xhr.ieXdr
- if @isGet or @body isnt null or ieXdr
- @paramsToUrl()
- if @body isnt null and typeof @body is 'string'
- @headers['Content-Type'] = 'text/plain; charset=utf8'
- else
- @paramsToBody()
-
- @xhr = new Dropbox.Xhr.Request()
- if ieXdr
- @xhr.onload = => @onXdrLoad()
- @xhr.onerror = => @onXdrError()
- @xhr.ontimeout = => @onXdrError()
- # NOTE: there are reports that XHR somtimes fails if onprogress doesn't
- # have any handler
- @xhr.onprogress = ->
- else
- @xhr.onreadystatechange = => @onReadyStateChange()
- @xhr.open @method, @url, true
-
- unless ieXdr
- for own header, value of @headers
- @xhr.setRequestHeader header, value
-
- if @responseType
- if @responseType is 'b'
- if @xhr.overrideMimeType
- @xhr.overrideMimeType 'text/plain; charset=x-user-defined'
- else
- @xhr.responseType = @responseType
-
- @
-
- # Fires off the prepared XHR request.
- #
- # Dropbox.Xhr#prepare should be called exactly once before this method.
- #
- # @param {function(?Dropbox.ApiError, ?Object, ?Object)} callback called when
- # the XHR completes; if an error occurs, the first parameter will be a
- # Dropbox.ApiError instance; otherwise, the second parameter will be an
- # instance of the required response type (e.g., String, Blob), and the
- # third parameter will be the JSON-parsed 'x-dropbox-metadata' header
- # @return {Dropbox.Xhr} this, for easy call chaining
- send: (callback) ->
- @callback = callback or @callback
-
- if @body isnt null
- body = @body
- # send() in XHR doesn't like naked ArrayBuffers
- if Dropbox.Xhr.sendArrayBufferView and body instanceof ArrayBuffer
- body = new Uint8Array body
-
- try
- @xhr.send body
- catch e
- # Node.js doesn't implement Blob.
- if !Dropbox.Xhr.sendArrayBufferView and typeof Blob isnt 'undefined'
- # Firefox doesn't support sending ArrayBufferViews.
- body = new Blob [body], type: 'application/octet-stream'
- @xhr.send body
- else
- throw e
- else
- @xhr.send()
- @
-
- # Encodes an associative array (hash) into a x-www-form-urlencoded String.
- #
- # For consistency, the keys are sorted in alphabetical order in the encoded
- # output.
- #
- # @param {Object} object the JavaScript object whose keys will be encoded
- # @return {String} the object's keys and values, encoded using
- # x-www-form-urlencoded
- @urlEncode: (object) ->
- chunks = []
- for key, value of object
- chunks.push @urlEncodeValue(key) + '=' + @urlEncodeValue(value)
- chunks.sort().join '&'
-
- # Encodes an object into a x-www-form-urlencoded key or value.
- #
- # @param {Object} object the object to be encoded; the encoding calls
- # toString() on the object to obtain its string representation
- # @return {String} encoded string, suitable for use as a key or value in an
- # x-www-form-urlencoded string
- @urlEncodeValue: (object) ->
- encodeURIComponent(object.toString()).replace(/\!/g, '%21').
- replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').
- replace(/\*/g, '%2A')
-
- # Decodes an x-www-form-urlencoded String into an associative array (hash).
- #
- # @param {String} string the x-www-form-urlencoded String to be decoded
- # @return {Object} an associative array whose keys and values are all strings
- @urlDecode: (string) ->
- result = {}
- for token in string.split '&'
- kvp = token.split '='
- result[decodeURIComponent(kvp[0])] = decodeURIComponent kvp[1]
- result
-
- # Handles the XHR readystate event.
- onReadyStateChange: ->
- return true if @xhr.readyState isnt 4 # XMLHttpRequest.DONE is 4
-
- if @xhr.status < 200 or @xhr.status >= 300
- apiError = new Dropbox.ApiError @xhr, @method, @url
- @onError.dispatch apiError if @onError
- @callback apiError
- return true
-
- metadataJson = @xhr.getResponseHeader 'x-dropbox-metadata'
- if metadataJson?.length
- try
- metadata = JSON.parse metadataJson
- catch e
- # Make sure the app doesn't crash if the server goes crazy.
- metadata = undefined
- else
- metadata = undefined
-
- if @responseType
- if @responseType is 'b'
- dirtyText = if @xhr.responseText?
- @xhr.responseText
- else
- @xhr.response
- ###
- jsString = ['["']
- for i in [0...dirtyText.length]
- hexByte = (dirtyText.charCodeAt(i) & 0xFF).toString(16)
- if hexByte.length is 2
- jsString.push "\\u00#{hexByte}"
- else
- jsString.push "\\u000#{hexByte}"
- jsString.push '"]'
- console.log jsString
- text = JSON.parse(jsString.join(''))[0]
- ###
- bytes = []
- for i in [0...dirtyText.length]
- bytes.push String.fromCharCode(dirtyText.charCodeAt(i) & 0xFF)
- text = bytes.join ''
- @callback null, text, metadata
- else
- @callback null, @xhr.response, metadata
- return true
-
- text = if @xhr.responseText? then @xhr.responseText else @xhr.response
- switch @xhr.getResponseHeader('Content-Type')
- when 'application/x-www-form-urlencoded'
- @callback null, Dropbox.Xhr.urlDecode(text), metadata
- when 'application/json', 'text/javascript'
- @callback null, JSON.parse(text), metadata
- else
- @callback null, text, metadata
- true
-
- # Handles the XDomainRequest onload event. (IE 8, 9)
- onXdrLoad: ->
- text = @xhr.responseText
- switch @xhr.contentType
- when 'application/x-www-form-urlencoded'
- @callback null, Dropbox.Xhr.urlDecode(text), undefined
- when 'application/json', 'text/javascript'
- @callback null, JSON.parse(text), undefined
- else
- @callback null, text, undefined
- true
-
- # Handles the XDomainRequest onload event. (IE 8, 9)
- onXdrError: ->
- apiError = new Dropbox.ApiError @xhr, @method, @url
- @onError.dispatch apiError if @onError
- @callback apiError
- return true
diff --git a/lib/client/storage/dropbox/src/zzz-export.coffee b/lib/client/storage/dropbox/src/zzz-export.coffee
deleted file mode 100644
index 45e47036..00000000
--- a/lib/client/storage/dropbox/src/zzz-export.coffee
+++ /dev/null
@@ -1,21 +0,0 @@
-# All changes to the global namespace happen here.
-
-# This file's name is set up in such a way that it will always show up last in
-# the source directory. This makes coffee --join work as intended.
-
-if module?.exports?
- # We're a node.js module, so export the Dropbox class.
- module.exports = Dropbox
-else if window?
- # We're in a browser, so add Dropbox to the global namespace.
- window.Dropbox = Dropbox
-else
- throw new Error('This library only supports node.js and modern browsers.')
-
-# These are mostly useful for testing. Clients shouldn't use internal stuff.
-Dropbox.atob = atob
-Dropbox.btoa = btoa
-Dropbox.hmac = base64HmacSha1
-Dropbox.sha1 = base64Sha1
-Dropbox.encodeKey = dropboxEncodeKey
-
diff --git a/lib/client/storage/dropbox/test/app_icon/hazard.svg b/lib/client/storage/dropbox/test/app_icon/hazard.svg
deleted file mode 100644
index 1c9542c1..00000000
--- a/lib/client/storage/dropbox/test/app_icon/hazard.svg
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/client/storage/dropbox/test/app_icon/hazard128.png b/lib/client/storage/dropbox/test/app_icon/hazard128.png
deleted file mode 100644
index 92e78693..00000000
Binary files a/lib/client/storage/dropbox/test/app_icon/hazard128.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/app_icon/hazard16.png b/lib/client/storage/dropbox/test/app_icon/hazard16.png
deleted file mode 100644
index 847d67dc..00000000
Binary files a/lib/client/storage/dropbox/test/app_icon/hazard16.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/app_icon/hazard64.png b/lib/client/storage/dropbox/test/app_icon/hazard64.png
deleted file mode 100644
index afdd91e7..00000000
Binary files a/lib/client/storage/dropbox/test/app_icon/hazard64.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/app_icon/radiation.svg b/lib/client/storage/dropbox/test/app_icon/radiation.svg
deleted file mode 100644
index f21963e2..00000000
--- a/lib/client/storage/dropbox/test/app_icon/radiation.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/lib/client/storage/dropbox/test/app_icon/radiation128.png b/lib/client/storage/dropbox/test/app_icon/radiation128.png
deleted file mode 100644
index eefcc148..00000000
Binary files a/lib/client/storage/dropbox/test/app_icon/radiation128.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/app_icon/radiation16.png b/lib/client/storage/dropbox/test/app_icon/radiation16.png
deleted file mode 100644
index 4626e76c..00000000
Binary files a/lib/client/storage/dropbox/test/app_icon/radiation16.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/app_icon/radiation64.png b/lib/client/storage/dropbox/test/app_icon/radiation64.png
deleted file mode 100644
index 8abe6bc4..00000000
Binary files a/lib/client/storage/dropbox/test/app_icon/radiation64.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/binary/dropbox.png b/lib/client/storage/dropbox/test/binary/dropbox.png
deleted file mode 100644
index 1442d90c..00000000
Binary files a/lib/client/storage/dropbox/test/binary/dropbox.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/chrome_app/images/icon.svg b/lib/client/storage/dropbox/test/chrome_app/images/icon.svg
deleted file mode 100644
index b074aab1..00000000
--- a/lib/client/storage/dropbox/test/chrome_app/images/icon.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/lib/client/storage/dropbox/test/chrome_app/images/icon128.png b/lib/client/storage/dropbox/test/chrome_app/images/icon128.png
deleted file mode 100644
index 82d61dbc..00000000
Binary files a/lib/client/storage/dropbox/test/chrome_app/images/icon128.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/chrome_app/images/icon16.png b/lib/client/storage/dropbox/test/chrome_app/images/icon16.png
deleted file mode 100644
index 86c7e8b7..00000000
Binary files a/lib/client/storage/dropbox/test/chrome_app/images/icon16.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/chrome_app/images/icon48.png b/lib/client/storage/dropbox/test/chrome_app/images/icon48.png
deleted file mode 100644
index 529cf14f..00000000
Binary files a/lib/client/storage/dropbox/test/chrome_app/images/icon48.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/chrome_app/manifests/app_v1.json b/lib/client/storage/dropbox/test/chrome_app/manifests/app_v1.json
deleted file mode 100644
index 5e369ae0..00000000
--- a/lib/client/storage/dropbox/test/chrome_app/manifests/app_v1.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "name": "dropbox.js Test Suite",
- "version": "1.0",
- "manifest_version": 2,
- "description": "Test suite for Chrome applications and extensions.",
- "icons": {
- "16": "images/icon16.png",
- "48": "images/icon48.png",
- "128": "images/icon128.png"
- },
- "permissions": [
- "storage",
- "unlimitedStorage"
- ],
- "app": {
- "launch": {
- "local_path": "test/html/browser_test.html"
- }
- }
-}
diff --git a/lib/client/storage/dropbox/test/chrome_app/manifests/app_v2.json b/lib/client/storage/dropbox/test/chrome_app/manifests/app_v2.json
deleted file mode 100644
index a41b4611..00000000
--- a/lib/client/storage/dropbox/test/chrome_app/manifests/app_v2.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "name": "dropbox.js Test Suite",
- "version": "1.0",
- "manifest_version": 2,
- "description": "Test suite for Chrome applications and extensions.",
- "icons": {
- "16": "images/icon16.png",
- "48": "images/icon48.png",
- "128": "images/icon128.png"
- },
- "permissions": [
- "storage",
- "unlimitedStorage"
- ],
- "app": {
- "background": {
- "scripts": [
- "test/js/chrome_app_background.js"
- ]
- }
- }
-}
diff --git a/lib/client/storage/dropbox/test/chrome_extension/README.md b/lib/client/storage/dropbox/test/chrome_extension/README.md
deleted file mode 100644
index 34c15033..00000000
--- a/lib/client/storage/dropbox/test/chrome_extension/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# dropbox.js Test Automator
-
-This is a Google Chrome extension that fully automates the dropbox.js test
-suite. Read the
-[dropbox.js development guide](https://github.com/dropbox/dropbox-js/tree/master/doc)
-to learn how the extension fits into the testing process.
-
-You're welcome to reuse the code to automate the testing of your own
-application's integration with Dropbox.
-
diff --git a/lib/client/storage/dropbox/test/chrome_extension/background.coffee b/lib/client/storage/dropbox/test/chrome_extension/background.coffee
deleted file mode 100644
index b29393ba..00000000
--- a/lib/client/storage/dropbox/test/chrome_extension/background.coffee
+++ /dev/null
@@ -1,84 +0,0 @@
-# Background script orchestrating the dropbox.js testing automation.
-
-class Automator
- constructor: ->
- @wired = false
- chrome.storage.sync.get 'enabled', (values) =>
- @lifeSwitch values.enabled is 'true'
-
- # Activates or deactivates the extension.
- # @param {Boolean} enabled if true, the extension's functionality is enabled
- lifeSwitch: (enabled) ->
- if enabled
- chrome.browserAction.setIcon
- path:
- 19: 'images/action_on19.png'
- 38: 'images/action_on38.png'
- chrome.browserAction.setTitle title: '(on) dropbox.js Test Automator'
- @wire()
- else
- chrome.browserAction.setIcon
- path:
- 19: 'images/action_off19.png',
- 38: 'images/action_off38.png'
- chrome.browserAction.setTitle title: '(off) dropbox.js Test Automator'
- @unwire()
-
- # Checks if Dropbox's authorization dialog should be auto-clicked.
- # @param {String} url the URL of the Dropbox authorization dialog
- # @return {Boolean} true if the "Authorize" button should be auto-clicked
- shouldAutomateAuth: (url) ->
- return false unless @wired
- !!(/(\?|&)oauth_callback=https?%3A%2F%2Flocalhost%3A891[12]%2F/.exec(url))
-
- # Checks if an OAuth receiver window should be auto-closed.
- # @param {String} url the URL of the OAuth receiver window
- # @return {Boolean} true if the "Authorize" button should be auto-clicked
- shouldAutomateClose: (url) ->
- return false unless @wired
- !!(/^https?:\/\/localhost:8912\/oauth_callback\?/.exec(url))
-
- # Sets up all the features that make dropbox.js testing easier.
- wire: ->
- return if @wired
- chrome.contentSettings.popups.set(
- primaryPattern: 'http://localhost:8911/*', setting: 'allow')
- @wired = true
- @
-
- # Disables the features that automate dropbox.js testing.
- unwire: ->
- return unless @wired
- chrome.contentSettings.popups.clear({})
- @wired = false
- @
-
-# Global Automator instance.
-automator = new Automator()
-
-# Current extension id, used to validate incoming messages.
-extensionId = chrome.i18n.getMessage "@@extension_id"
-
-# Communicates with content scripts.
-chrome.extension.onMessage.addListener (message, sender, sendResponse) ->
- return unless sender.id is extensionId
- switch message.type
- when 'auth'
- sendResponse automate: automator.shouldAutomateAuth(message.url)
- when 'close'
- if automator.shouldAutomateClose(message.url) and sender.tab
- chrome.tabs.remove sender.tab.id
-
-# Listen to pref changes and activate / deactivate the extension.
-chrome.storage.onChanged.addListener (changes, namespace) ->
- return unless namespace is 'sync'
- for name, change of changes
- continue unless name is 'enabled'
- automator.lifeSwitch change.newValue is 'true'
-
-# The browser action item flips the switch that activates the extension.
-chrome.browserAction.onClicked.addListener ->
- chrome.storage.sync.get 'enabled', (values) ->
- enabled = values.enabled is 'true'
- chrome.storage.sync.set enabled: (!enabled).toString()
-
diff --git a/lib/client/storage/dropbox/test/chrome_extension/content_auth.coffee b/lib/client/storage/dropbox/test/chrome_extension/content_auth.coffee
deleted file mode 100644
index 1fb6ca89..00000000
--- a/lib/client/storage/dropbox/test/chrome_extension/content_auth.coffee
+++ /dev/null
@@ -1,18 +0,0 @@
-# Content script for Dropbox authorization pages.
-
-message = type: 'auth', url: window.location.href
-chrome.extension.sendMessage message, (response) ->
- return unless response.automate
-
- button = document.querySelector('[name=allow_access]') or
- document.querySelector '.freshbutton-blue'
- event = document.createEvent 'MouseEvents'
-
- clientX = button.clientWidth / 2
- clientY = button.clientHeight / 2
- screenX = window.screenX + button.offsetLeft + clientX
- screenY = window.screenY + button.offsetTop + clientY
- event.initMouseEvent 'click', true, true, window, 1,
- screenX, screenY, clientX, clientY, false, false, false, false, 0, null
- button.dispatchEvent event
-
diff --git a/lib/client/storage/dropbox/test/chrome_extension/content_close.coffee b/lib/client/storage/dropbox/test/chrome_extension/content_close.coffee
deleted file mode 100644
index 0ca6febd..00000000
--- a/lib/client/storage/dropbox/test/chrome_extension/content_close.coffee
+++ /dev/null
@@ -1,4 +0,0 @@
-# Content script for Dropbox OAuth receiver pages.
-
-message = type: 'close', url: window.location.href
-chrome.extension.sendMessage message
diff --git a/lib/client/storage/dropbox/test/chrome_extension/images/action_off19.png b/lib/client/storage/dropbox/test/chrome_extension/images/action_off19.png
deleted file mode 100644
index 734c470d..00000000
Binary files a/lib/client/storage/dropbox/test/chrome_extension/images/action_off19.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/chrome_extension/images/action_off38.png b/lib/client/storage/dropbox/test/chrome_extension/images/action_off38.png
deleted file mode 100644
index c6e96cd1..00000000
Binary files a/lib/client/storage/dropbox/test/chrome_extension/images/action_off38.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/chrome_extension/images/action_on19.png b/lib/client/storage/dropbox/test/chrome_extension/images/action_on19.png
deleted file mode 100644
index 290b36b6..00000000
Binary files a/lib/client/storage/dropbox/test/chrome_extension/images/action_on19.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/chrome_extension/images/action_on38.png b/lib/client/storage/dropbox/test/chrome_extension/images/action_on38.png
deleted file mode 100644
index 86dfb268..00000000
Binary files a/lib/client/storage/dropbox/test/chrome_extension/images/action_on38.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/chrome_extension/images/icon.svg b/lib/client/storage/dropbox/test/chrome_extension/images/icon.svg
deleted file mode 100644
index 4a99e835..00000000
--- a/lib/client/storage/dropbox/test/chrome_extension/images/icon.svg
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-image/svg+xml
\ No newline at end of file
diff --git a/lib/client/storage/dropbox/test/chrome_extension/images/icon128.png b/lib/client/storage/dropbox/test/chrome_extension/images/icon128.png
deleted file mode 100644
index 6a6c2e11..00000000
Binary files a/lib/client/storage/dropbox/test/chrome_extension/images/icon128.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/chrome_extension/images/icon16.png b/lib/client/storage/dropbox/test/chrome_extension/images/icon16.png
deleted file mode 100644
index 3374631a..00000000
Binary files a/lib/client/storage/dropbox/test/chrome_extension/images/icon16.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/chrome_extension/images/icon48.png b/lib/client/storage/dropbox/test/chrome_extension/images/icon48.png
deleted file mode 100644
index 360607b2..00000000
Binary files a/lib/client/storage/dropbox/test/chrome_extension/images/icon48.png and /dev/null differ
diff --git a/lib/client/storage/dropbox/test/chrome_extension/manifest.json b/lib/client/storage/dropbox/test/chrome_extension/manifest.json
deleted file mode 100644
index f6fe0e57..00000000
--- a/lib/client/storage/dropbox/test/chrome_extension/manifest.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "name": "dropbox.js Test Automator",
- "version": "1.0",
- "manifest_version": 2,
- "description": "Automatically clicks buttons and closes windows, so you can spend more time coding.",
- "icons": {
- "16": "images/icon16.png",
- "48": "images/icon48.png",
- "128": "images/icon128.png"
- },
- "permissions": [
- "http://localhost/*",
- "https://localhost/*",
- "https://www.dropbox.com/1/oauth/authorize*",
- "contentSettings",
- "storage"
- ],
- "browser_action": {
- "default_icon": {
- "19": "images/action_off19.png",
- "38": "images/action_off38.png"
- },
- "default_title": "dropbox.js Test Automator"
- },
- "background": {
- "scripts": ["background.js"]
- },
- "content_scripts": [
- {
- "matches": ["https://www.dropbox.com/1/oauth/authorize*"],
- "js": ["content_auth.js"],
- "run_at": "document_idle"
- },
- {
- "matches": [
- "http://localhost/*",
- "https://localhost/*"
- ],
- "include_globs": ["http*://localhost:8912/oauth_callback*"],
- "js": ["content_close.js"],
- "run_at": "document_idle"
- }
- ]
-}
diff --git a/lib/client/storage/dropbox/test/html/browser_test.html b/lib/client/storage/dropbox/test/html/browser_test.html
deleted file mode 100644
index 21bb0cec..00000000
--- a/lib/client/storage/dropbox/test/html/browser_test.html
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
- dropbox.js browser tests
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/client/storage/dropbox/test/html/chrome_oauth_receiver.html b/lib/client/storage/dropbox/test/html/chrome_oauth_receiver.html
deleted file mode 100644
index 0f0db938..00000000
--- a/lib/client/storage/dropbox/test/html/chrome_oauth_receiver.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
- Dropbox sign-in successful
-
- Please close this window.
-
-
diff --git a/lib/client/storage/dropbox/test/html/oauth_receiver.html b/lib/client/storage/dropbox/test/html/oauth_receiver.html
deleted file mode 100644
index 54a70562..00000000
--- a/lib/client/storage/dropbox/test/html/oauth_receiver.html
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
- Dropbox sign-in successful
-
- Please close this window.
-
-
diff --git a/lib/client/storage/dropbox/test/html/redirect_driver_test.html b/lib/client/storage/dropbox/test/html/redirect_driver_test.html
deleted file mode 100644
index 8e5e2410..00000000
--- a/lib/client/storage/dropbox/test/html/redirect_driver_test.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
- Please close this window.
-
-
diff --git a/lib/client/storage/dropbox/test/src/base64_test.coffee b/lib/client/storage/dropbox/test/src/base64_test.coffee
deleted file mode 100644
index 975169f2..00000000
--- a/lib/client/storage/dropbox/test/src/base64_test.coffee
+++ /dev/null
@@ -1,11 +0,0 @@
-describe 'Dropbox.atob', ->
- it 'decodes an ASCII string', ->
- expect(Dropbox.atob('YTFiMmMz')).to.equal 'a1b2c3'
- it 'decodes a non-ASCII character', ->
- expect(Dropbox.atob('/A==')).to.equal String.fromCharCode(252)
-
-describe 'Dropbox.btoa', ->
- it 'encodes an ASCII string', ->
- expect(Dropbox.btoa('a1b2c3')).to.equal 'YTFiMmMz'
- it 'encodes a non-ASCII character', ->
- expect(Dropbox.btoa(String.fromCharCode(252))).to.equal '/A=='
diff --git a/lib/client/storage/dropbox/test/src/browser_mocha_runner.coffee b/lib/client/storage/dropbox/test/src/browser_mocha_runner.coffee
deleted file mode 100644
index e538dce8..00000000
--- a/lib/client/storage/dropbox/test/src/browser_mocha_runner.coffee
+++ /dev/null
@@ -1,9 +0,0 @@
-window.addEventListener 'load', ->
- runner = mocha.run ->
- failures = runner.failures || 0
- total = runner.total || 0
- image = new Image()
- image.src = "/diediedie?failed=#{failures}&total=#{total}";
- image.onload = ->
- null
-
diff --git a/lib/client/storage/dropbox/test/src/browser_mocha_setup.coffee b/lib/client/storage/dropbox/test/src/browser_mocha_setup.coffee
deleted file mode 100644
index 70a2f3b7..00000000
--- a/lib/client/storage/dropbox/test/src/browser_mocha_setup.coffee
+++ /dev/null
@@ -1 +0,0 @@
-mocha.setup ui: 'bdd', slow: 150, timeout: 10000
diff --git a/lib/client/storage/dropbox/test/src/chrome_app_background.coffee b/lib/client/storage/dropbox/test/src/chrome_app_background.coffee
deleted file mode 100644
index 634d0199..00000000
--- a/lib/client/storage/dropbox/test/src/chrome_app_background.coffee
+++ /dev/null
@@ -1,3 +0,0 @@
-chrome.app.runtime.onLaunched.addListener ->
- chrome.app.window.create 'test/html/browser_test.html',
- type: 'shell', frame: 'chrome', id: 'test_suite'
diff --git a/lib/client/storage/dropbox/test/src/chrome_oauth_receiver.coffee b/lib/client/storage/dropbox/test/src/chrome_oauth_receiver.coffee
deleted file mode 100644
index de601b08..00000000
--- a/lib/client/storage/dropbox/test/src/chrome_oauth_receiver.coffee
+++ /dev/null
@@ -1 +0,0 @@
-Dropbox.Drivers.Chrome.oauthReceiver()
diff --git a/lib/client/storage/dropbox/test/src/client_test.coffee b/lib/client/storage/dropbox/test/src/client_test.coffee
deleted file mode 100644
index 47d57185..00000000
--- a/lib/client/storage/dropbox/test/src/client_test.coffee
+++ /dev/null
@@ -1,1492 +0,0 @@
-buildClientTests = (clientKeys) ->
- # Creates the global client.
- setupClient = (test, done) ->
- # Should only be used for fixture teardown.
- test.__client = new Dropbox.Client clientKeys
- done()
-
- # Creates the test directory.
- setupDirectory = (test, done) ->
- # True if running on node.js
- test.node_js = module? and module?.exports? and require?
-
- # All test data should go here.
- test.testFolder = '/js tests.' + Math.random().toString(36)
- test.__client.mkdir test.testFolder, (error, stat) ->
- expect(error).to.equal null
- done()
-
- # Creates the binary image file in the test directory.
- setupImageFile = (test, done) ->
- test.imageFile = "#{test.testFolder}/test-binary-image.png"
- test.imageFileData = testImageBytes
-
- setupImageFileUsingArrayBuffer test, (success) ->
- if success
- return done()
- setupImageFileUsingBlob test, (success) ->
- if success
- return done()
- setupImageFileUsingString test, done
-
- # Standard-compliant browsers write via XHR#send(ArrayBufferView).
- setupImageFileUsingArrayBuffer = (test, done) ->
- if Uint8Array? and (not test.node_js)
- testImageServerOn()
- xhr = new Dropbox.Xhr 'GET', testImageUrl
- xhr.setResponseType('arraybuffer').prepare().send (error, buffer) =>
- testImageServerOff()
- expect(error).to.equal null
- test.__client.writeFile test.imageFile, buffer, (error, stat) ->
- expect(error).to.equal null
- # Some browsers will send the '[object Uint8Array]' string instead of
- # the ArrayBufferView.
- if stat.size is buffer.byteLength
- test.imageFileTag = stat.versionTag
- done true
- else
- done false
- else
- done false
-
- # Fallback to XHR#send(Blob).
- setupImageFileUsingBlob = (test, done) ->
- if Blob? and (not test.node_js)
- testImageServerOn()
- xhr = new Dropbox.Xhr 'GET', testImageUrl
- xhr.setResponseType('arraybuffer').prepare().send (error, buffer) =>
- testImageServerOff()
- expect(error).to.equal null
- blob = new Blob [buffer], type: 'image/png'
- test.__client.writeFile test.imageFile, blob, (error, stat) ->
- expect(error).to.equal null
- if stat.size is blob.size
- test.imageFileTag = stat.versionTag
- done true
- else
- done false
- else
- done false
-
- # Last resort: send a string that will get crushed by encoding errors.
- setupImageFileUsingString = (test, done) ->
- test.__client.writeFile(test.imageFile, test.imageFileData,
- { binary: true },
- (error, stat) ->
- expect(error).to.equal null
- test.imageFileTag = stat.versionTag
- done()
- )
-
- # Creates the plaintext file in the test directory.
- setupTextFile = (test, done) ->
- test.textFile = "#{test.testFolder}/test-file.txt"
- test.textFileData = "Plaintext test file #{Math.random().toString(36)}.\n"
- test.__client.writeFile(test.textFile, test.textFileData,
- (error, stat) ->
- expect(error).to.equal null
- test.textFileTag = stat.versionTag
- done()
- )
-
- # Global (expensive) fixtures.
- before (done) ->
- @timeout 10 * 1000
- setupClient this, =>
- setupDirectory this, =>
- setupImageFile this, =>
- setupTextFile this, ->
- done()
-
- # Teardown for global fixtures.
- after (done) ->
- @__client.remove @testFolder, (error, stat) =>
- @test.error(new Error(error)) if error
- done()
-
- # Per-test (cheap) fixtures.
- beforeEach ->
- @client = new Dropbox.Client clientKeys
-
- describe 'URLs for custom API server', ->
- it 'computes the other URLs correctly', ->
- client = new Dropbox.Client
- key: clientKeys.key,
- secret: clientKeys.secret,
- server: 'https://api.sandbox.dropbox-proxy.com'
-
- expect(client.apiServer).to.equal(
- 'https://api.sandbox.dropbox-proxy.com')
- expect(client.authServer).to.equal(
- 'https://www.sandbox.dropbox-proxy.com')
- expect(client.fileServer).to.equal(
- 'https://api-content.sandbox.dropbox-proxy.com')
-
- describe '#normalizePath', ->
- it "doesn't touch relative paths", ->
- expect(@client.normalizePath('aa/b/cc/dd')).to.equal 'aa/b/cc/dd'
-
- it 'removes the leading / from absolute paths', ->
- expect(@client.normalizePath('/aaa/b/cc/dd')).to.equal 'aaa/b/cc/dd'
-
- it 'removes multiple leading /s from absolute paths', ->
- expect(@client.normalizePath('///aa/b/ccc/dd')).to.equal 'aa/b/ccc/dd'
-
- describe '#urlEncodePath', ->
- it 'encodes each segment separately', ->
- expect(@client.urlEncodePath('a b+c/d?e"f/g&h')).to.
- equal "a%20b%2Bc/d%3Fe%22f/g%26h"
- it 'normalizes paths', ->
- expect(@client.urlEncodePath('///a b+c/g&h')).to.
- equal "a%20b%2Bc/g%26h"
-
- describe '#dropboxUid', ->
- it 'matches the uid in the credentials', ->
- expect(@client.dropboxUid()).to.equal clientKeys.uid
-
- describe '#getUserInfo', ->
- it 'returns reasonable information', (done) ->
- @client.getUserInfo (error, userInfo, rawUserInfo) ->
- expect(error).to.equal null
- expect(userInfo).to.be.instanceOf Dropbox.UserInfo
- expect(userInfo.uid).to.equal clientKeys.uid
- expect(rawUserInfo).not.to.be.instanceOf Dropbox.UserInfo
- expect(rawUserInfo).to.have.property 'uid'
- done()
-
- describe 'with httpCache', ->
- beforeEach ->
- @xhr = null
- @client.onXhr.addListener (xhr) =>
- @xhr = xhr
-
- it 'uses Authorization headers', (done) ->
- @client.getUserInfo httpCache: true, (error, userInfo, rawUserInfo) =>
- if Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers
- expect(@xhr.url).to.contain 'oauth_nonce'
- else
- expect(@xhr.headers).to.have.key 'Authorization'
-
- expect(error).to.equal null
- expect(userInfo).to.be.instanceOf Dropbox.UserInfo
- expect(userInfo.uid).to.equal clientKeys.uid
- expect(rawUserInfo).not.to.be.instanceOf Dropbox.UserInfo
- expect(rawUserInfo).to.have.property 'uid'
- done()
-
- describe '#mkdir', ->
- afterEach (done) ->
- return done() unless @newFolder
- @client.remove @newFolder, (error, stat) -> done()
-
- it 'creates a folder in the test folder', (done) ->
- @newFolder = "#{@testFolder}/test'folder"
- @client.mkdir @newFolder, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFolder
- expect(stat.isFolder).to.equal true
- @client.stat @newFolder, (error, stat) =>
- expect(error).to.equal null
- expect(stat.isFolder).to.equal true
- done()
-
- describe '#readFile', ->
- it 'reads a text file', (done) ->
- @client.readFile @textFile, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal @textFileData
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @textFile
- expect(stat.isFile).to.equal true
- done()
-
- it 'reads the beginning of a text file', (done) ->
- return done() if Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
-
- @client.readFile @textFile, start: 0, length: 10, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal @textFileData.substring(0, 10)
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @textFile
- expect(stat.isFile).to.equal true
- done()
-
- it 'reads the middle of a text file', (done) ->
- return done() if Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
-
- @client.readFile @textFile, start: 8, length: 10, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal @textFileData.substring(8, 18)
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @textFile
- expect(stat.isFile).to.equal true
- done()
-
- it 'reads the end of a text file via the start: option', (done) ->
- return done() if Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
-
- @client.readFile @textFile, start: 10, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal @textFileData.substring(10)
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @textFile
- expect(stat.isFile).to.equal true
- done()
-
- it 'reads the end of a text file via the length: option', (done) ->
- return done() if Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
-
- @client.readFile @textFile, length: 10, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.
- equal @textFileData.substring(@textFileData.length - 10)
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @textFile
- expect(stat.isFile).to.equal true
- done()
-
- it 'reads a binary file into a string', (done) ->
- @client.readFile @imageFile, binary: true, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal @imageFileData
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @imageFile
- expect(stat.isFile).to.equal true
- done()
-
- it 'reads a binary file into a Blob', (done) ->
- return done() unless Blob?
- @client.readFile @imageFile, blob: true, (error, blob, stat) =>
- expect(error).to.equal null
- expect(blob).to.be.instanceOf Blob
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @imageFile
- expect(stat.isFile).to.equal true
- reader = new FileReader
- reader.onloadend = =>
- return unless reader.readyState == FileReader.DONE
- buffer = reader.result
- view = new Uint8Array buffer
- length = buffer.byteLength
- bytes = (String.fromCharCode view[i] for i in [0...length]).
- join('')
- expect(bytes).to.equal @imageFileData
- done()
- reader.readAsArrayBuffer blob
-
- it 'reads a binary file into an ArrayBuffer', (done) ->
- return done() unless ArrayBuffer?
- @client.readFile @imageFile, arrayBuffer: true, (error, buffer, stat) =>
- expect(error).to.equal null
- expect(buffer).to.be.instanceOf ArrayBuffer
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @imageFile
- expect(stat.isFile).to.equal true
- view = new Uint8Array buffer
- length = buffer.byteLength
- bytes = (String.fromCharCode view[i] for i in [0...length]).
- join('')
- expect(bytes).to.equal @imageFileData
- done()
-
- describe 'with an onXhr listener', ->
- beforeEach ->
- @listenerXhr = null
- @callbackCalled = false
-
- it 'calls the listener with a Dropbox.Xhr argument', (done) ->
- @client.onXhr.addListener (xhr) =>
- expect(xhr).to.be.instanceOf Dropbox.Xhr
- @listenerXhr = xhr
- true
-
- @client.readFile @textFile, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal @textFileData
- done() if @listenerXhr
-
- it 'calls the listener before firing the XHR', (done) ->
- @client.onXhr.addListener (xhr) =>
- unless Dropbox.Xhr.ieXdr # IE's XHR doesn't have readyState
- expect(xhr.xhr.readyState).to.equal 1
- expect(@callbackCalled).to.equal false
- @listenerXhr = xhr
- true
-
- @client.readFile @textFile, (error, data, stat) =>
- @callbackCalled = true
- expect(@listenerXhr).to.be.instanceOf Dropbox.Xhr
- expect(error).to.equal null
- expect(data).to.equal @textFileData
- done() if @listenerXhr
-
- it 'does not send the XHR if the listener cancels the event', (done) ->
- @client.onXhr.addListener (xhr) =>
- expect(@callbackCalled).to.equal false
- @listenerXhr = xhr
- # NOTE: if the client calls send(), a DOM error will fail the test
- xhr.send()
- false
-
- @client.readFile @textFile, (error, data, stat) =>
- @callbackCalled = true
- expect(@listenerXhr).to.be.instanceOf Dropbox.Xhr
- done() if @listenerXhr
-
- describe 'with httpCache', ->
- beforeEach ->
- @xhr = null
- @client.onXhr.addListener (xhr) =>
- @xhr = xhr
-
- it 'reads a text file using Authorization headers', (done) ->
- @client.readFile @textFile, httpCache: true, (error, data, stat) =>
- if Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers
- expect(@xhr.url).to.contain 'oauth_nonce'
- else
- expect(@xhr.headers).to.have.key 'Authorization'
-
- expect(error).to.equal null
- expect(data).to.equal @textFileData
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @textFile
- expect(stat.isFile).to.equal true
- done()
-
- describe '#writeFile', ->
- afterEach (done) ->
- return done() unless @newFile
- @client.remove @newFile, (error, stat) -> done()
-
- it 'writes a new text file', (done) ->
- @newFile = "#{@testFolder}/another text file.txt"
- @newFileData = "Another plaintext file #{Math.random().toString(36)}."
- @client.writeFile @newFile, @newFileData, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- @client.readFile @newFile, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal @newFileData
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- done()
-
- it 'writes a new empty file', (done) ->
- @newFile = "#{@testFolder}/another text file.txt"
- @newFileData = ''
- @client.writeFile @newFile, @newFileData, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- @client.readFile @newFile, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal @newFileData
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- done()
-
- it 'writes a Blob to a binary file', (done) ->
- return done() unless Blob? and ArrayBuffer?
- @newFile = "#{@testFolder}/test image from blob.png"
- newBuffer = new ArrayBuffer @imageFileData.length
- newBytes = new Uint8Array newBuffer
- for i in [0...@imageFileData.length]
- newBytes[i] = @imageFileData.charCodeAt i
- @newBlob = new Blob [newBytes], type: 'image/png'
- if @newBlob.size isnt newBuffer.byteLength
- @newBlob = new Blob [newBuffer], type: 'image/png'
- @client.writeFile @newFile, @newBlob, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
-
- @client.readFile @newFile, arrayBuffer: true,
- (error, buffer, stat) =>
- expect(error).to.equal null
- expect(buffer).to.be.instanceOf ArrayBuffer
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- view = new Uint8Array buffer
- length = buffer.byteLength
- bytes = (String.fromCharCode view[i] for i in [0...length]).
- join('')
- expect(bytes).to.equal @imageFileData
- done()
-
- it 'writes a File to a binary file', (done) ->
- return done() unless File? and Blob? and ArrayBuffer?
- @newFile = "#{@testFolder}/test image from blob.png"
- newBuffer = new ArrayBuffer @imageFileData.length
- newBytes = new Uint8Array newBuffer
- for i in [0...@imageFileData.length]
- newBytes[i] = @imageFileData.charCodeAt i
- newBlob = new Blob [newBytes], type: 'image/png'
-
- # Called when we have a File wrapping newBlob.
- actualTestCase = (file) =>
- @newFileObject = file
- @client.writeFile @newFile, @newFileObject, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
-
- @client.readFile @newFile, arrayBuffer: true,
- (error, buffer, stat) =>
- expect(error).to.equal null
- expect(buffer).to.be.instanceOf ArrayBuffer
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- view = new Uint8Array buffer
- length = buffer.byteLength
- bytes = (String.fromCharCode view[i] for i in [0...length]).
- join('')
- expect(bytes).to.equal @imageFileData
- done()
-
- # TODO(pwnall): use lighter method of constructing a File, when available
- # http://crbug.com/164933
- return done() if typeof webkitRequestFileSystem is 'undefined'
- webkitRequestFileSystem window.TEMPORARY, 1024 * 1024, (fileSystem) ->
- # NOTE: the File name is different from the uploaded file name, to
- # catch bugs such as http://crbug.com/165095
- fileSystem.root.getFile 'test image file.png',
- create: true, exclusive: false, (fileEntry) ->
- fileEntry.createWriter (fileWriter) ->
- fileWriter.onwriteend = ->
- fileEntry.file (file) ->
- actualTestCase file
- fileWriter.write newBlob
-
- it 'writes an ArrayBuffer to a binary file', (done) ->
- return done() unless ArrayBuffer?
- @newFile = "#{@testFolder}/test image from arraybuffer.png"
- @newBuffer = new ArrayBuffer @imageFileData.length
- newBytes = new Uint8Array @newBuffer
- for i in [0...@imageFileData.length]
- newBytes[i] = @imageFileData.charCodeAt i
- @client.writeFile @newFile, @newBuffer, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
-
- @client.readFile @newFile, arrayBuffer: true,
- (error, buffer, stat) =>
- expect(error).to.equal null
- expect(buffer).to.be.instanceOf ArrayBuffer
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- view = new Uint8Array buffer
- length = buffer.byteLength
- bytes = (String.fromCharCode view[i] for i in [0...length]).
- join('')
- expect(bytes).to.equal @imageFileData
- done()
-
- it 'writes an ArrayBufferView to a binary file', (done) ->
- return done() unless ArrayBuffer?
- @newFile = "#{@testFolder}/test image from arraybufferview.png"
- @newBytes = new Uint8Array @imageFileData.length
- for i in [0...@imageFileData.length]
- @newBytes[i] = @imageFileData.charCodeAt i
- @client.writeFile @newFile, @newBytes, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
-
- @client.readFile @newFile, arrayBuffer: true,
- (error, buffer, stat) =>
- expect(error).to.equal null
- expect(buffer).to.be.instanceOf ArrayBuffer
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- view = new Uint8Array buffer
- length = buffer.byteLength
- bytes = (String.fromCharCode view[i] for i in [0...length]).
- join('')
- expect(bytes).to.equal @imageFileData
- done()
-
- describe '#resumableUploadStep + #resumableUploadFinish', ->
- beforeEach ->
- if ArrayBuffer? # IE9 and below doesn't have ArrayBuffer
- @length1 = Math.ceil @imageFileData.length / 3
- @length2 = @imageFileData.length - @length1
- @buffer1 = new ArrayBuffer @length1
-
- @view1 = new Uint8Array @buffer1
- for i in [0...@length1]
- @view1[i] = @imageFileData.charCodeAt i
- @buffer2 = new ArrayBuffer @length2
- @view2 = new Uint8Array @buffer2
- for i in [0...@length2]
- @view2[i] = @imageFileData.charCodeAt @length1 + i
-
- if Blob? # node.js and IE9 and below don't have Blob
- @blob1 = new Blob [@view1], type: 'image/png'
- if @blob1.size isnt @buffer1.byteLength
- @blob1 = new Blob [@buffer1], type: 'image/png'
- @blob2 = new Blob [@view2], type: 'image/png'
- if @blob2.size isnt @buffer2.byteLength
- @blob2 = new Blob [@buffer2], type: 'image/png'
-
- afterEach (done) ->
- @timeout 20 * 1000 # This sequence is slow on the current API server.
- return done() unless @newFile
- @client.remove @newFile, (error, stat) -> done()
-
- it 'writes a text file in two stages', (done) ->
- @timeout 20 * 1000 # This sequence is slow on the current API server.
-
- @newFile = "#{@testFolder}/test resumable upload.txt"
- line1 = "This is the first fragment\n"
- line2 = "This is the second fragment\n"
- @client.resumableUploadStep line1, null, (error, cursor1) =>
- expect(error).to.equal null
- expect(cursor1).to.be.instanceOf Dropbox.UploadCursor
- expect(cursor1.offset).to.equal line1.length
- @client.resumableUploadStep line2, cursor1, (error, cursor2) =>
- expect(error).to.equal null
- expect(cursor2).to.be.instanceOf Dropbox.UploadCursor
- expect(cursor2.offset).to.equal line1.length + line2.length
- expect(cursor2.tag).to.equal cursor1.tag
- @client.resumableUploadFinish @newFile, cursor2, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- @client.readFile @newFile, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal line1 + line2
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- done()
-
- it 'writes a binary file using two ArrayBuffers', (done) ->
- return done() unless @buffer1
- @timeout 20 * 1000 # This sequence is slow on the current API server.
-
- @newFile = "#{@testFolder}/test resumable arraybuffer upload.png"
- @client.resumableUploadStep @buffer1, null, (error, cursor1) =>
- expect(error).to.equal null
- expect(cursor1).to.be.instanceOf Dropbox.UploadCursor
- expect(cursor1.offset).to.equal @length1
- @client.resumableUploadStep @buffer2, cursor1, (error, cursor2) =>
- expect(error).to.equal null
- expect(cursor2).to.be.instanceOf Dropbox.UploadCursor
- expect(cursor2.offset).to.equal @length1 + @length2
- expect(cursor2.tag).to.equal cursor1.tag
- @client.resumableUploadFinish @newFile, cursor2, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- @client.readFile @newFile, arrayBuffer: true,
- (error, buffer, stat) =>
- expect(error).to.equal null
- expect(buffer).to.be.instanceOf ArrayBuffer
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- view = new Uint8Array buffer
- length = buffer.byteLength
- bytes = (String.fromCharCode view[i] for i in [0...length]).
- join('')
- expect(bytes).to.equal @imageFileData
- done()
-
- it 'writes a binary file using two ArrayBufferViews', (done) ->
- return done() unless @view1
- @timeout 20 * 1000 # This sequence is slow on the current API server.
-
- @newFile = "#{@testFolder}/test resumable arraybuffer upload.png"
- @client.resumableUploadStep @buffer1, null, (error, cursor1) =>
- expect(error).to.equal null
- expect(cursor1).to.be.instanceOf Dropbox.UploadCursor
- expect(cursor1.offset).to.equal @length1
- @client.resumableUploadStep @buffer2, cursor1, (error, cursor2) =>
- expect(error).to.equal null
- expect(cursor2).to.be.instanceOf Dropbox.UploadCursor
- expect(cursor2.offset).to.equal @length1 + @length2
- expect(cursor2.tag).to.equal cursor1.tag
- @client.resumableUploadFinish @newFile, cursor2, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- @client.readFile @newFile, arrayBuffer: true,
- (error, buffer, stat) =>
- expect(error).to.equal null
- expect(buffer).to.be.instanceOf ArrayBuffer
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- view = new Uint8Array buffer
- length = buffer.byteLength
- bytes = (String.fromCharCode view[i] for i in [0...length]).
- join('')
- expect(bytes).to.equal @imageFileData
- done()
-
-
- it 'writes a binary file using two Blobs', (done) ->
- return done() unless @blob1
- @timeout 20 * 1000 # This sequence is slow on the current API server.
-
- @newFile = "#{@testFolder}/test resumable blob upload.png"
- @client.resumableUploadStep @blob1, null, (error, cursor1) =>
- expect(error).to.equal null
- expect(cursor1).to.be.instanceOf Dropbox.UploadCursor
- expect(cursor1.offset).to.equal @length1
- @client.resumableUploadStep @blob2, cursor1, (error, cursor2) =>
- expect(error).to.equal null
- expect(cursor2).to.be.instanceOf Dropbox.UploadCursor
- expect(cursor2.offset).to.equal @length1 + @length2
- expect(cursor2.tag).to.equal cursor1.tag
- @client.resumableUploadFinish @newFile, cursor2, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- @client.readFile @newFile, arrayBuffer: true,
- (error, buffer, stat) =>
- expect(error).to.equal null
- expect(buffer).to.be.instanceOf ArrayBuffer
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- view = new Uint8Array buffer
- length = buffer.byteLength
- bytes = (String.fromCharCode view[i] for i in [0...length]).
- join('')
- expect(bytes).to.equal @imageFileData
- done()
-
- it 'recovers from out-of-sync correctly', (done) ->
- # IE's XDR doesn't return anything on errors, so we can't do recovery.
- return done() if Dropbox.Xhr.ieXdr
- @timeout 20 * 1000 # This sequence is slow on the current API server.
-
- @newFile = "#{@testFolder}/test resumable upload out of sync.txt"
- line1 = "This is the first fragment\n"
- line2 = "This is the second fragment\n"
- @client.resumableUploadStep line1, null, (error, cursor1) =>
- expect(error).to.equal null
- expect(cursor1).to.be.instanceOf Dropbox.UploadCursor
- expect(cursor1.offset).to.equal line1.length
- cursor1.offset += 10
- @client.resumableUploadStep line2, cursor1, (error, cursor2) =>
- expect(error).to.equal null
- expect(cursor2).to.be.instanceOf Dropbox.UploadCursor
- expect(cursor2.offset).to.equal line1.length
- expect(cursor2.tag).to.equal cursor1.tag
- @client.resumableUploadStep line2, cursor2, (error, cursor3) =>
- expect(error).to.equal null
- expect(cursor3).to.be.instanceOf Dropbox.UploadCursor
- expect(cursor3.offset).to.equal line1.length + line2.length
- expect(cursor3.tag).to.equal cursor1.tag
- @client.resumableUploadFinish @newFile, cursor3, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- @client.readFile @newFile, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal line1 + line2
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- done()
-
- it 'reports errors correctly', (done) ->
- @newFile = "#{@testFolder}/test resumable upload error.txt"
- badCursor = new Dropbox.UploadCursor 'trollcursor'
- badCursor.offset = 42
- @client.resumableUploadStep @textFileData, badCursor, (error, cursor) =>
- expect(cursor).to.equal undefined
- expect(error).to.be.instanceOf Dropbox.ApiError
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do status codes.
- expect(error.status).to.equal 404
- done()
-
- describe '#stat', ->
- it 'retrieves a Stat for a file', (done) ->
- @client.stat @textFile, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @textFile
- expect(stat.isFile).to.equal true
- expect(stat.versionTag).to.equal @textFileTag
- expect(stat.size).to.equal @textFileData.length
- if clientKeys.sandbox
- expect(stat.inAppFolder).to.equal true
- else
- expect(stat.inAppFolder).to.equal false
- done()
-
- it 'retrieves a Stat for a folder', (done) ->
- @client.stat @testFolder, (error, stat, entries) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @testFolder
- expect(stat.isFolder).to.equal true
- expect(stat.size).to.equal 0
- if clientKeys.sandbox
- expect(stat.inAppFolder).to.equal true
- else
- expect(stat.inAppFolder).to.equal false
- expect(entries).to.equal undefined
- done()
-
- it 'retrieves a Stat and entries for a folder', (done) ->
- @client.stat @testFolder, { readDir: true }, (error, stat, entries) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @testFolder
- expect(stat.isFolder).to.equal true
- expect(entries).to.be.ok
- expect(entries).to.have.length 2
- expect(entries[0]).to.be.instanceOf Dropbox.Stat
- expect(entries[0].path).not.to.equal @testFolder
- expect(entries[0].path).to.have.string @testFolder
- done()
-
- it 'fails cleanly for a non-existing path', (done) ->
- listenerError = null
- @client.onError.addListener (error) -> listenerError = error
-
- @client.stat @testFolder + '/should_404.txt', (error, stat, entries) =>
- expect(stat).to.equal undefined
- expect(entries).to.equal.null
- expect(error).to.be.instanceOf Dropbox.ApiError
- expect(listenerError).to.equal error
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do status codes.
- expect(error).to.have.property 'status'
- expect(error.status).to.equal 404
- done()
-
- describe 'with httpCache', ->
- beforeEach ->
- @xhr = null
- @client.onXhr.addListener (xhr) =>
- @xhr = xhr
-
- it 'retrieves a Stat for a file using Authorization headers', (done) ->
- @client.stat @textFile, httpCache: true, (error, stat) =>
- if Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers
- expect(@xhr.url).to.contain 'oauth_nonce'
- else
- expect(@xhr.headers).to.have.key 'Authorization'
-
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @textFile
- expect(stat.isFile).to.equal true
- expect(stat.versionTag).to.equal @textFileTag
- expect(stat.size).to.equal @textFileData.length
- if clientKeys.sandbox
- expect(stat.inAppFolder).to.equal true
- else
- expect(stat.inAppFolder).to.equal false
- done()
-
- describe '#readdir', ->
- it 'retrieves a Stat and entries for a folder', (done) ->
- @client.readdir @testFolder, (error, entries, dir_stat, entry_stats) =>
- expect(error).to.equal null
- expect(entries).to.be.ok
- expect(entries).to.have.length 2
- expect(entries[0]).to.be.a 'string'
- expect(entries[0]).not.to.have.string '/'
- expect(entries[0]).to.match /^(test-binary-image.png)|(test-file.txt)$/
- expect(dir_stat).to.be.instanceOf Dropbox.Stat
- expect(dir_stat.path).to.equal @testFolder
- expect(dir_stat.isFolder).to.equal true
- expect(entry_stats).to.be.ok
- expect(entry_stats).to.have.length 2
- expect(entry_stats[0]).to.be.instanceOf Dropbox.Stat
- expect(entry_stats[0].path).not.to.equal @testFolder
- expect(entry_stats[0].path).to.have.string @testFolder
- done()
-
- describe 'with httpCache', ->
- beforeEach ->
- @xhr = null
- @client.onXhr.addListener (xhr) =>
- @xhr = xhr
-
- it 'retrieves a folder Stat and entries using Authorization', (done) ->
- @client.readdir @testFolder, httpCache: true,
- (error, entries, dir_stat, entry_stats) =>
- if Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers
- expect(@xhr.url).to.contain 'oauth_nonce'
- else
- expect(@xhr.headers).to.have.key 'Authorization'
-
- expect(error).to.equal null
- expect(entries).to.be.ok
- expect(entries).to.have.length 2
- expect(entries[0]).to.be.a 'string'
- expect(entries[0]).not.to.have.string '/'
- expect(entries[0]).to.match(
- /^(test-binary-image.png)|(test-file.txt)$/)
- expect(dir_stat).to.be.instanceOf Dropbox.Stat
- expect(dir_stat.path).to.equal @testFolder
- expect(dir_stat.isFolder).to.equal true
- expect(entry_stats).to.be.ok
- expect(entry_stats).to.have.length 2
- expect(entry_stats[0]).to.be.instanceOf Dropbox.Stat
- expect(entry_stats[0].path).not.to.equal @testFolder
- expect(entry_stats[0].path).to.have.string @testFolder
- done()
-
- describe '#history', ->
- it 'gets a list of revisions', (done) ->
- @client.history @textFile, (error, versions) =>
- expect(error).to.equal null
- expect(versions).to.have.length 1
- expect(versions[0]).to.be.instanceOf Dropbox.Stat
- expect(versions[0].path).to.equal @textFile
- expect(versions[0].size).to.equal @textFileData.length
- expect(versions[0].versionTag).to.equal @textFileTag
- done()
-
- it 'returns 40x if the limit is set to 0', (done) ->
- listenerError = null
- @client.onError.addListener (error) -> listenerError = error
-
- @client.history @textFile, limit: 0, (error, versions) =>
- expect(error).to.be.instanceOf Dropbox.ApiError
- expect(listenerError).to.equal error
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do status codes.
- expect(error.status).to.be.within 400, 499
- expect(versions).not.to.be.ok
- done()
-
- describe 'with httpCache', ->
- beforeEach ->
- @xhr = null
- @client.onXhr.addListener (xhr) =>
- @xhr = xhr
-
- it 'gets a list of revisions using Authorization headers', (done) ->
- @client.history @textFile, httpCache: true, (error, versions) =>
- if Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers
- expect(@xhr.url).to.contain 'oauth_nonce'
- else
- expect(@xhr.headers).to.have.key 'Authorization'
-
- expect(error).to.equal null
- expect(versions).to.have.length 1
- expect(versions[0]).to.be.instanceOf Dropbox.Stat
- expect(versions[0].path).to.equal @textFile
- expect(versions[0].size).to.equal @textFileData.length
- expect(versions[0].versionTag).to.equal @textFileTag
- done()
-
- describe '#copy', ->
- afterEach (done) ->
- return done() unless @newFile
- @client.remove @newFile, (error, stat) -> done()
-
- it 'copies a file given by path', (done) ->
- @timeout 12 * 1000 # This sequence is slow on the current API server.
-
- @newFile = "#{@testFolder}/copy of test-file.txt"
- @client.copy @textFile, @newFile, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- @client.readFile @newFile, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal @textFileData
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- @client.readFile @textFile, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal @textFileData
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @textFile
- expect(stat.versionTag).to.equal @textFileTag
- done()
-
- describe '#makeCopyReference', ->
- afterEach (done) ->
- return done() unless @newFile
- @client.remove @newFile, (error, stat) -> done()
-
- it 'creates a Dropbox.CopyReference that copies the file', (done) ->
- @timeout 12 * 1000 # This sequence is slow on the current API server.
- @newFile = "#{@testFolder}/ref copy of test-file.txt"
-
- @client.makeCopyReference @textFile, (error, copyRef) =>
- expect(error).to.equal null
- expect(copyRef).to.be.instanceOf Dropbox.CopyReference
- @client.copy copyRef, @newFile, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isFile).to.equal true
- @client.readFile @newFile, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal @textFileData
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- done()
-
- describe '#move', ->
- beforeEach (done) ->
- @timeout 10 * 1000 # This sequence is slow on the current API server.
- @moveFrom = "#{@testFolder}/move source of test-file.txt"
- @client.copy @textFile, @moveFrom, (error, stat) ->
- expect(error).to.equal null
- done()
-
- afterEach (done) ->
- @client.remove @moveFrom, (error, stat) =>
- return done() unless @moveTo
- @client.remove @moveTo, (error, stat) -> done()
-
- it 'moves a file', (done) ->
- @timeout 15 * 1000 # This sequence is slow on the current API server.
- @moveTo = "#{@testFolder}/moved test-file.txt"
- @client.move @moveFrom, @moveTo, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @moveTo
- expect(stat.isFile).to.equal true
- @client.readFile @moveTo, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal @textFileData
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @moveTo
- @client.readFile @moveFrom, (error, data, stat) ->
- expect(error).to.be.ok
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do status codes.
- expect(error).to.have.property 'status'
- expect(error.status).to.equal 404
- expect(data).to.equal undefined
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.equal undefined
- done()
-
- describe '#remove', ->
- beforeEach (done) ->
- @newFolder = "#{@testFolder}/folder delete test"
- @client.mkdir @newFolder, (error, stat) =>
- expect(error).to.equal null
- done()
-
- afterEach (done) ->
- return done() unless @newFolder
- @client.remove @newFolder, (error, stat) -> done()
-
- it 'deletes a folder', (done) ->
- @client.remove @newFolder, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFolder
- @client.stat @newFolder, { removed: true }, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.isRemoved).to.equal true
- done()
-
- it 'deletes a folder when called as unlink', (done) ->
- @client.unlink @newFolder, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFolder
- @client.stat @newFolder, { removed: true }, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.isRemoved).to.equal true
- done()
-
- describe '#revertFile', ->
- describe 'on a removed file', ->
- beforeEach (done) ->
- @timeout 12 * 1000 # This sequence seems to be quite slow.
-
- @newFile = "#{@testFolder}/file revert test.txt"
- @client.copy @textFile, @newFile, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- @versionTag = stat.versionTag
- @client.remove @newFile, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- done()
-
- afterEach (done) ->
- return done() unless @newFile
- @client.remove @newFile, (error, stat) -> done()
-
- it 'reverts the file to a previous version', (done) ->
- @timeout 12 * 1000 # This sequence seems to be quite slow.
-
- @client.revertFile @newFile, @versionTag, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isRemoved).to.equal false
- @client.readFile @newFile, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.equal @textFileData
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @newFile
- expect(stat.isRemoved).to.equal false
- done()
-
- describe '#findByName', ->
- it 'locates the test folder given a partial name', (done) ->
- namePattern = @testFolder.substring 5
- @client.search '/', namePattern, (error, matches) =>
- expect(error).to.equal null
- expect(matches).to.have.length 1
- expect(matches[0]).to.be.instanceOf Dropbox.Stat
- expect(matches[0].path).to.equal @testFolder
- expect(matches[0].isFolder).to.equal true
- done()
-
- it 'lists the test folder files given the "test" pattern', (done) ->
- @client.search @testFolder, 'test', (error, matches) =>
- expect(error).to.equal null
- expect(matches).to.have.length 2
- done()
-
- it 'only lists one match when given limit 1', (done) ->
- @client.search @testFolder, 'test', limit: 1, (error, matches) =>
- expect(error).to.equal null
- expect(matches).to.have.length 1
- done()
-
- describe 'with httpCache', ->
- beforeEach ->
- @xhr = null
- @client.onXhr.addListener (xhr) =>
- @xhr = xhr
-
- it 'locates the test folder using Authorize headers', (done) ->
- namePattern = @testFolder.substring 5
- @client.search '/', namePattern, httpCache: true, (error, matches) =>
- if Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers
- expect(@xhr.url).to.contain 'oauth_nonce'
- else
- expect(@xhr.headers).to.have.key 'Authorization'
-
- expect(error).to.equal null
- expect(matches).to.have.length 1
- expect(matches[0]).to.be.instanceOf Dropbox.Stat
- expect(matches[0].path).to.equal @testFolder
- expect(matches[0].isFolder).to.equal true
- done()
-
- describe '#makeUrl', ->
- describe 'for a short Web URL', ->
- it 'returns a shortened Dropbox URL', (done) ->
- @client.makeUrl @textFile, (error, publicUrl) ->
- expect(error).to.equal null
- expect(publicUrl).to.be.instanceOf Dropbox.PublicUrl
- expect(publicUrl.isDirect).to.equal false
- expect(publicUrl.url).to.contain '//db.tt/'
- done()
-
- describe 'for a Web URL created with long: true', ->
- it 'returns an URL to a preview page', (done) ->
- @client.makeUrl @textFile, { long: true }, (error, publicUrl) =>
- expect(error).to.equal null
- expect(publicUrl).to.be.instanceOf Dropbox.PublicUrl
- expect(publicUrl.isDirect).to.equal false
- expect(publicUrl.url).not.to.contain '//db.tt/'
-
- # The cont/ents server does not return CORS headers.
- return done() unless @nodejs
- Dropbox.Xhr.request 'GET', publicUrl.url, {}, null, (error, data) ->
- expect(error).to.equal null
- expect(data).to.contain ''
- done()
-
- describe 'for a Web URL created with longUrl: true', ->
- it 'returns an URL to a preview page', (done) ->
- @client.makeUrl @textFile, { longUrl: true }, (error, publicUrl) =>
- expect(error).to.equal null
- expect(publicUrl).to.be.instanceOf Dropbox.PublicUrl
- expect(publicUrl.isDirect).to.equal false
- expect(publicUrl.url).not.to.contain '//db.tt/'
- done()
-
- describe 'for a direct download URL', ->
- it 'gets a direct download URL', (done) ->
- @client.makeUrl @textFile, { download: true }, (error, publicUrl) =>
- expect(error).to.equal null
- expect(publicUrl).to.be.instanceOf Dropbox.PublicUrl
- expect(publicUrl.isDirect).to.equal true
- expect(publicUrl.url).not.to.contain '//db.tt/'
-
- # The contents server does not return CORS headers.
- return done() unless @nodejs
- Dropbox.Xhr.request 'GET', publicUrl.url, {}, null, (error, data) =>
- expect(error).to.equal null
- expect(data).to.equal @textFileData
- done()
-
- describe 'for a direct download URL created with downloadHack: true', ->
- it 'gets a direct long-lived download URL', (done) ->
- @client.makeUrl @textFile, { downloadHack: true }, (error, publicUrl) =>
- expect(error).to.equal null
- expect(publicUrl).to.be.instanceOf Dropbox.PublicUrl
- expect(publicUrl.isDirect).to.equal true
- expect(publicUrl.url).not.to.contain '//db.tt/'
- expect(publicUrl.expiresAt - Date.now()).to.be.above 86400000
-
- # The download server does not return CORS headers.
- return done() unless @nodejs
- Dropbox.Xhr.request 'GET', publicUrl.url, {}, null, (error, data) =>
- expect(error).to.equal null
- expect(data).to.equal @textFileData
- done()
-
- describe '#pullChanges', ->
- beforeEach ->
- # Pulling an entire Dropbox can take a lot of time, so we need fancy
- # logic here.
- @timeoutValue = 60 * 1000
- @timeout @timeoutValue
-
- afterEach (done) ->
- @timeoutValue += 10 * 1000
- @timeout @timeoutValue
- return done() unless @newFile
- @client.remove @newFile, (error, stat) -> done()
-
- it 'gets a cursor, then it gets relevant changes', (done) ->
- @timeout @timeoutValue
-
- @client.pullChanges (error, changes) =>
- expect(error).to.equal null
- expect(changes).to.be.instanceOf Dropbox.PulledChanges
- expect(changes.blankSlate).to.equal true
-
- # Calls pullChanges until it's done listing the user's Dropbox.
- drainEntries = (client, callback) =>
- return callback() unless changes.shouldPullAgain
- @timeoutValue += 10 * 1000 # 10 extra seconds per call
- @timeout @timeoutValue
- client.pullChanges changes, (error, _changes) ->
- expect(error).to.equal null
- changes = _changes
- drainEntries client, callback
- drainEntries @client, =>
-
- @newFile = "#{@testFolder}/delta-test.txt"
- newFileData = "This file is used to test the pullChanges method.\n"
- @client.writeFile @newFile, newFileData, (error, stat) =>
- expect(error).to.equal null
- expect(stat).to.have.property 'path'
- expect(stat.path).to.equal @newFile
-
- @client.pullChanges changes, (error, changes) =>
- expect(error).to.equal null
- expect(changes).to.be.instanceof Dropbox.PulledChanges
- expect(changes.blankSlate).to.equal false
- expect(changes.changes).to.have.length.greaterThan 0
- change = changes.changes[changes.changes.length - 1]
- expect(change).to.be.instanceOf Dropbox.PullChange
- expect(change.path).to.equal @newFile
- expect(change.wasRemoved).to.equal false
- expect(change.stat.path).to.equal @newFile
- done()
-
- describe '#thumbnailUrl', ->
- it 'produces an URL that contains the file name', ->
- url = @client.thumbnailUrl @imageFile, { png: true, size: 'medium' }
- expect(url).to.contain 'tests' # Fragment of the file name.
- expect(url).to.contain 'png'
- expect(url).to.contain 'medium'
-
- describe '#readThumbnail', ->
- it 'reads the image into a string', (done) ->
- @timeout 12 * 1000 # Thumbnail generation is slow.
- @client.readThumbnail @imageFile, { png: true }, (error, data, stat) =>
- expect(error).to.equal null
- expect(data).to.be.a 'string'
- expect(data).to.contain 'PNG'
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @imageFile
- expect(stat.isFile).to.equal true
- done()
-
- it 'reads the image into a Blob', (done) ->
- return done() unless Blob?
- @timeout 12 * 1000 # Thumbnail generation is slow.
- options = { png: true, blob: true }
- @client.readThumbnail @imageFile, options, (error, blob, stat) =>
- expect(error).to.equal null
- expect(blob).to.be.instanceOf Blob
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do headers.
- expect(stat).to.be.instanceOf Dropbox.Stat
- expect(stat.path).to.equal @imageFile
- expect(stat.isFile).to.equal true
- reader = new FileReader
- reader.onloadend = =>
- return unless reader.readyState == FileReader.DONE
- buffer = reader.result
- view = new Uint8Array buffer
- length = buffer.byteLength
- bytes = (String.fromCharCode view[i] for i in [0...length]).
- join('')
- expect(bytes).to.contain 'PNG'
- done()
- reader.readAsArrayBuffer blob
-
- describe '#reset', ->
- beforeEach ->
- @authStates = []
- @client.onAuthStateChange.addListener (client) =>
- @authStates.push client.authState
- @client.reset()
-
- it 'gets the client into the RESET state', ->
- expect(@client.authState).to.equal Dropbox.Client.RESET
-
- it 'removes token and uid information', ->
- credentials = @client.credentials()
- expect(credentials).not.to.have.property 'token'
- expect(credentials).not.to.have.property 'tokenSecret'
- expect(credentials).not.to.have.property 'uid'
-
- it 'triggers onAuthStateChange', ->
- expect(@authStates).to.deep.equal [Dropbox.Client.RESET]
-
- it 'does not trigger onAuthState if already reset', ->
- @authStates = []
- @client.reset()
- expect(@authStates).to.deep.equal []
-
- describe '#credentials', ->
- it 'contains all the expected keys when DONE', ->
- credentials = @client.credentials()
- expect(credentials).to.have.property 'key'
- expect(credentials).to.have.property 'sandbox'
- expect(credentials).to.have.property 'token'
- expect(credentials).to.have.property 'tokenSecret'
- expect(credentials).to.have.property 'uid'
-
- it 'does not return an authState when DONE', ->
- credentials = @client.credentials()
- expect(credentials).not.to.have.property 'authState'
- expect(credentials).not.to.have.property 'secret'
-
- it 'contains all the expected keys when RESET', ->
- @client.reset()
- credentials = @client.credentials()
- expect(credentials).to.have.property 'key'
- expect(credentials).to.have.property 'sandbox'
-
- it 'does not return an authState when RESET', ->
- @client.reset()
- credentials = @client.credentials()
- expect(credentials).not.to.have.property 'authState'
- expect(credentials).not.to.have.property 'secret'
-
- describe 'for a client with raw keys', ->
- beforeEach ->
- @client.setCredentials(
- key: 'dpf43f3p2l4k3l03', secret: 'kd94hf93k423kf44',
- token: 'user-token', tokenSecret: 'user-secret', uid: '1234567')
-
- it 'contains all the expected keys when DONE', ->
- credentials = @client.credentials()
- expect(credentials).to.have.property 'key'
- expect(credentials).to.have.property 'secret'
- expect(credentials).to.have.property 'token'
- expect(credentials).to.have.property 'tokenSecret'
- expect(credentials).to.have.property 'uid'
-
- it 'contains all the expected keys when RESET', ->
- @client.reset()
- credentials = @client.credentials()
- expect(credentials).to.have.property 'key'
- expect(credentials).to.have.property 'sandbox'
- expect(credentials).to.have.property 'secret'
-
-
- describe '#setCredentials', ->
- it 'gets the client into the RESET state', ->
- @client.setCredentials key: 'app-key', secret: 'app-secret'
- expect(@client.authState).to.equal Dropbox.Client.RESET
- credentials = @client.credentials()
- expect(credentials.key).to.equal 'app-key'
- expect(credentials.secret).to.equal 'app-secret'
-
- it 'gets the client into the REQUEST state', ->
- @client.setCredentials(
- key: 'app-key', secret: 'app-secret', token: 'user-token',
- tokenSecret: 'user-secret', authState: Dropbox.Client.REQUEST)
- expect(@client.authState).to.equal Dropbox.Client.REQUEST
- credentials = @client.credentials()
- expect(credentials.key).to.equal 'app-key'
- expect(credentials.secret).to.equal 'app-secret'
- expect(credentials.token).to.equal 'user-token'
- expect(credentials.tokenSecret).to.equal 'user-secret'
-
- it 'gets the client into the DONE state', ->
- @client.setCredentials(
- key: 'app-key', secret: 'app-secret', token: 'user-token',
- tokenSecret: 'user-secret', uid: '3141592')
- expect(@client.authState).to.equal Dropbox.Client.DONE
- credentials = @client.credentials()
- expect(credentials.key).to.equal 'app-key'
- expect(credentials.secret).to.equal 'app-secret'
- expect(credentials.token).to.equal 'user-token'
- expect(credentials.tokenSecret).to.equal 'user-secret'
- expect(credentials.uid).to.equal '3141592'
-
- beforeEach ->
- @authStates = []
- @client.onAuthStateChange.addListener (client) =>
- @authStates.push client.authState
-
- it 'triggers onAuthStateChange when switching from DONE to RESET', ->
- @client.setCredentials key: 'app-key', secret: 'app-secret'
- expect(@authStates).to.deep.equal [Dropbox.Client.RESET]
-
- it 'does not trigger onAuthStateChange when not switching', ->
- @client.setCredentials key: 'app-key', secret: 'app-secret'
- @authStates = []
- @client.setCredentials key: 'app-key', secret: 'app-secret'
- expect(@authStates).to.deep.equal []
-
- describe '#appHash', ->
- it 'is consistent', ->
- client = new Dropbox.Client clientKeys
- expect(client.appHash()).to.equal @client.appHash()
-
- it 'is a non-trivial string', ->
- expect(@client.appHash()).to.be.a 'string'
- expect(@client.appHash().length).to.be.greaterThan 4
-
- describe '#isAuthenticated', ->
- it 'is true for a client with full tokens', ->
- expect(@client.isAuthenticated()).to.equal true
-
- it 'is false for a freshly reset client', ->
- @client.reset()
- expect(@client.isAuthenticated()).to.equal false
-
- describe '#authenticate', ->
- it 'fails to move from RESET without an OAuth driver', ->
- @client.reset()
- @client.authDriver null
- expect(=> @client.authenticate(->
- expect('authentication completed').to.equal false
- )).to.throw(Error, /authDriver/)
-
- it 'completes without an OAuth driver if already in DONE', (done) ->
- @client.authDriver null
- @client.authenticate (error, client) =>
- expect(error).to.equal null
- expect(client).to.equal @client
- done()
-
-describe 'Dropbox.Client', ->
- describe 'with full Dropbox access', ->
- buildClientTests testFullDropboxKeys
-
- describe 'with Folder access', ->
- buildClientTests testKeys
-
- describe '#authenticate + #signOut', ->
- # NOTE: we're not duplicating this test in the full Dropbox acess suite,
- # because it's annoying to the tester
- it 'completes the authenticate flow', (done) ->
- @timeout 45 * 1000 # Time-consuming because the user must click.
- @client.reset()
- @client.authDriver authDriver
- authStateChanges = ['authorize']
- @client.onAuthStateChange.addListener (client) ->
- authStateChanges.push client.authState
- @client.authenticate (error, client) =>
- expect(error).to.equal null
- expect(client).to.equal @client
- expect(client.authState).to.equal Dropbox.Client.DONE
- expect(client.isAuthenticated()).to.equal true
- expect(authStateChanges).to.deep.equal(['authorize',
- Dropbox.Client.REQUEST, Dropbox.Client.AUTHORIZED,
- Dropbox.Client.DONE])
- # Verify that we can do API calls.
- client.getUserInfo (error, userInfo) ->
- expect(error).to.equal null
- expect(userInfo).to.be.instanceOf Dropbox.UserInfo
- invalidCredentials = client.credentials()
- authStateChanges = ['signOff']
- client.signOut (error) ->
- expect(error).to.equal null
- expect(client.authState).to.equal Dropbox.Client.SIGNED_OFF
- expect(client.isAuthenticated()).to.equal false
- expect(authStateChanges).to.deep.equal(['signOff',
- Dropbox.Client.SIGNED_OFF])
- # Verify that we can't use the old token in API calls.
- invalidClient = new Dropbox.Client invalidCredentials
- invalidClient.getUserInfo (error, userInfo) ->
- expect(error).to.be.ok
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do error codes.
- expect(error.status).to.equal 401
- # Verify that the same client can be used for a 2nd signin.
- authStateChanges = ['authorize2']
- client.authenticate (error, client) ->
- expect(error).to.equal null
- expect(client.authState).to.equal Dropbox.Client.DONE
- expect(client.isAuthenticated()).to.equal true
- expect(authStateChanges).to.deep.equal(['authorize2',
- Dropbox.Client.RESET, Dropbox.Client.REQUEST,
- Dropbox.Client.AUTHORIZED, Dropbox.Client.DONE])
- # Verify that we can do API calls after the 2nd signin.
- client.getUserInfo (error, userInfo) ->
- expect(error).to.equal null
- expect(userInfo).to.be.instanceOf Dropbox.UserInfo
- done()
-
-
- describe '#appHash', ->
- it 'depends on the app key', ->
- client = new Dropbox.Client testFullDropboxKeys
- expect(client.appHash()).not.to.equal @client.appHash()
-
- describe '#constructor', ->
- it 'raises an Error if initialized without an API key / secret', ->
- expect(-> new Dropbox.Client(token: '123', tokenSecret: '456')).to.
- throw(Error, /no api key/i)
-
diff --git a/lib/client/storage/dropbox/test/src/drivers_test.coffee b/lib/client/storage/dropbox/test/src/drivers_test.coffee
deleted file mode 100644
index d35e8485..00000000
--- a/lib/client/storage/dropbox/test/src/drivers_test.coffee
+++ /dev/null
@@ -1,446 +0,0 @@
-describe 'Dropbox.Drivers.BrowserBase', ->
- beforeEach ->
- @node_js = module? and module?.exports? and require?
- @chrome_app = chrome? and (chrome.extension or chrome.app)
- @client = new Dropbox.Client testKeys
-
- describe 'with rememberUser: false', ->
- beforeEach (done) ->
- return done() if @node_js or @chrome_app
- @driver = new Dropbox.Drivers.BrowserBase
- @driver.setStorageKey @client
- @driver.forgetCredentials done
-
- afterEach (done) ->
- return done() if @node_js or @chrome_app
- @driver.forgetCredentials done
-
- describe '#loadCredentials', ->
- it 'produces the credentials passed to storeCredentials', (done) ->
- return done() if @node_js or @chrome_app
- goldCredentials = @client.credentials()
- @driver.storeCredentials goldCredentials, =>
- @driver.loadCredentials (credentials) ->
- expect(credentials).to.deep.equal goldCredentials
- done()
-
- it 'produces null after forgetCredentials was called', (done) ->
- return done() if @node_js or @chrome_app
- @driver.storeCredentials @client.credentials(), =>
- @driver.forgetCredentials =>
- @driver.loadCredentials (credentials) ->
- expect(credentials).to.equal null
- done()
-
- it 'produces null if a different scope is provided', (done) ->
- return done() if @node_js or @chrome_app
- @driver.setStorageKey @client
- @driver.storeCredentials @client.credentials(), =>
- @driver.forgetCredentials =>
- @driver.loadCredentials (credentials) ->
- expect(credentials).to.equal null
- done()
-
-
-describe 'Dropbox.Drivers.Redirect', ->
- describe '#url', ->
- beforeEach ->
- @stub = sinon.stub Dropbox.Drivers.BrowserBase, 'currentLocation'
- afterEach ->
- @stub.restore()
-
- it 'adds a query string to a static URL', ->
- @stub.returns 'http://test/file'
- driver = new Dropbox.Drivers.Redirect useQuery: true
- expect(driver.url()).to.
- equal 'http://test/file?_dropboxjs_scope=default'
-
- it 'adds a fragment to a static URL', ->
- @stub.returns 'http://test/file'
- driver = new Dropbox.Drivers.Redirect
- expect(driver.url()).to.
- equal 'http://test/file#?_dropboxjs_scope=default'
-
- it 'adds a query param to a URL with a query string', ->
- @stub.returns 'http://test/file?a=true'
- driver = new Dropbox.Drivers.Redirect useQuery: true
- expect(driver.url()).to.
- equal 'http://test/file?a=true&_dropboxjs_scope=default'
-
- it 'adds a fragment to a URL with a query string', ->
- @stub.returns 'http://test/file?a=true'
- driver = new Dropbox.Drivers.Redirect
- expect(driver.url()).to.
- equal 'http://test/file?a=true#?_dropboxjs_scope=default'
-
- it 'adds a query string to a static URL with a fragment', ->
- @stub.returns 'http://test/file#frag'
- driver = new Dropbox.Drivers.Redirect useQuery: true
- expect(driver.url()).to.
- equal 'http://test/file?_dropboxjs_scope=default#frag'
-
- it 'replaces the fragment in a static URL with a fragment', ->
- @stub.returns 'http://test/file#frag'
- driver = new Dropbox.Drivers.Redirect
- expect(driver.url()).to.
- equal 'http://test/file#?_dropboxjs_scope=default'
-
- it 'adds a query param to a URL with a query string and fragment', ->
- @stub.returns 'http://test/file?a=true#frag'
- driver = new Dropbox.Drivers.Redirect useQuery: true
- expect(driver.url()).to.
- equal 'http://test/file?a=true&_dropboxjs_scope=default#frag'
-
- it 'replaces the fragment in a URL with a query string and fragment', ->
- @stub.returns 'http://test/file?a=true#frag'
- driver = new Dropbox.Drivers.Redirect
- expect(driver.url()).to.
- equal 'http://test/file?a=true#?_dropboxjs_scope=default'
-
- it 'obeys the scope option', ->
- @stub.returns 'http://test/file'
- driver = new Dropbox.Drivers.Redirect(
- scope: 'not default', useQuery: true)
- expect(driver.url()).to.
- equal 'http://test/file?_dropboxjs_scope=not%20default'
-
- it 'obeys the scope option when adding a fragment', ->
- @stub.returns 'http://test/file'
- driver = new Dropbox.Drivers.Redirect scope: 'not default'
- expect(driver.url()).to.
- equal 'http://test/file#?_dropboxjs_scope=not%20default'
-
- describe '#locationToken', ->
- beforeEach ->
- @stub = sinon.stub Dropbox.Drivers.BrowserBase, 'currentLocation'
- afterEach ->
- @stub.restore()
-
- it 'returns null if the location does not contain the arg', ->
- @stub.returns 'http://test/file?_dropboxjs_scope=default& ' +
- 'another_token=ab%20cd&oauth_tok=en'
- driver = new Dropbox.Drivers.Redirect
- expect(driver.locationToken()).to.equal null
-
- it 'returns null if the location fragment does not contain the arg', ->
- @stub.returns 'http://test/file#?_dropboxjs_scope=default& ' +
- 'another_token=ab%20cd&oauth_tok=en'
- driver = new Dropbox.Drivers.Redirect
- expect(driver.locationToken()).to.equal null
-
- it "extracts the token successfully with default scope", ->
- @stub.returns 'http://test/file?_dropboxjs_scope=default&' +
- 'oauth_token=ab%20cd&other_param=true'
- driver = new Dropbox.Drivers.Redirect
- expect(driver.locationToken()).to.equal 'ab cd'
-
- it "extracts the token successfully with set scope", ->
- @stub.returns 'http://test/file?_dropboxjs_scope=not%20default&' +
- 'oauth_token=ab%20cd'
- driver = new Dropbox.Drivers.Redirect scope: 'not default'
- expect(driver.locationToken()).to.equal 'ab cd'
-
- it "extracts the token from fragment with default scope", ->
- @stub.returns 'http://test/file#?_dropboxjs_scope=default&' +
- 'oauth_token=ab%20cd&other_param=true'
- driver = new Dropbox.Drivers.Redirect
- expect(driver.locationToken()).to.equal 'ab cd'
-
- it "extracts the token from fragment with set scope", ->
- @stub.returns 'http://test/file#?_dropboxjs_scope=not%20default&' +
- 'oauth_token=ab%20cd'
- driver = new Dropbox.Drivers.Redirect scope: 'not default'
- expect(driver.locationToken()).to.equal 'ab cd'
-
- it "returns null if the location scope doesn't match", ->
- @stub.returns 'http://test/file?_dropboxjs_scope=defaultx&oauth_token=ab'
- driver = new Dropbox.Drivers.Redirect
- expect(driver.locationToken()).to.equal null
-
- it "returns null if the location fragment scope doesn't match", ->
- @stub.returns 'http://test/file#?_dropboxjs_scope=defaultx&oauth_token=a'
- driver = new Dropbox.Drivers.Redirect
- expect(driver.locationToken()).to.equal null
-
- describe '#loadCredentials', ->
- beforeEach ->
- @node_js = module? and module.exports? and require?
- @chrome_app = chrome? and (chrome.extension or chrome.app?.runtime)
- return if @node_js or @chrome_app
- @client = new Dropbox.Client testKeys
- @driver = new Dropbox.Drivers.Redirect scope: 'some_scope'
- @driver.setStorageKey @client
-
- it 'produces the credentials passed to storeCredentials', (done) ->
- return done() if @node_js or @chrome_app
- goldCredentials = @client.credentials()
- @driver.storeCredentials goldCredentials, =>
- @driver = new Dropbox.Drivers.Redirect scope: 'some_scope'
- @driver.setStorageKey @client
- @driver.loadCredentials (credentials) ->
- expect(credentials).to.deep.equal goldCredentials
- done()
-
- it 'produces null after forgetCredentials was called', (done) ->
- return done() if @node_js or @chrome_app
- @driver.storeCredentials @client.credentials(), =>
- @driver.forgetCredentials =>
- @driver = new Dropbox.Drivers.Redirect scope: 'some_scope'
- @driver.setStorageKey @client
- @driver.loadCredentials (credentials) ->
- expect(credentials).to.equal null
- done()
-
- it 'produces null if a different scope is provided', (done) ->
- return done() if @node_js or @chrome_app
- @driver.setStorageKey @client
- @driver.storeCredentials @client.credentials(), =>
- @driver = new Dropbox.Drivers.Redirect scope: 'other_scope'
- @driver.setStorageKey @client
- @driver.loadCredentials (credentials) ->
- expect(credentials).to.equal null
- done()
-
- describe 'integration', ->
- beforeEach ->
- @node_js = module? and module.exports? and require?
- @chrome_app = chrome? and (chrome.extension or chrome.app?.runtime)
-
- it 'should work', (done) ->
- return done() if @node_js or @chrome_app
- @timeout 30 * 1000 # Time-consuming because the user must click.
-
- listener = (event) ->
- expect(event.data).to.match(/^\[.*\]$/)
- [error, credentials] = JSON.parse event.data
- expect(error).to.equal null
- expect(credentials).to.have.property 'uid'
- expect(credentials.uid).to.be.a 'string'
- window.removeEventListener 'message', listener
- done()
-
- window.addEventListener 'message', listener
- (new Dropbox.Drivers.Popup()).openWindow(
- '/test/html/redirect_driver_test.html')
-
-describe 'Dropbox.Drivers.Popup', ->
- describe '#url', ->
- beforeEach ->
- @stub = sinon.stub Dropbox.Drivers.BrowserBase, 'currentLocation'
- @stub.returns 'http://test:123/a/path/file.htmx'
-
- afterEach ->
- @stub.restore()
-
- it 'reflects the current page when there are no options', ->
- driver = new Dropbox.Drivers.Popup
- expect(driver.url()).to.equal 'http://test:123/a/path/file.htmx'
-
- it 'replaces the current file correctly', ->
- driver = new Dropbox.Drivers.Popup receiverFile: 'another.file'
- expect(driver.url()).to.equal 'http://test:123/a/path/another.file#'
-
- it 'replaces the current file without a fragment correctly', ->
- driver = new Dropbox.Drivers.Popup
- receiverFile: 'another.file', noFragment: true
- expect(driver.url()).to.equal 'http://test:123/a/path/another.file'
-
- it 'replaces an entire URL without a fragment correctly', ->
- driver = new Dropbox.Drivers.Popup
- receiverUrl: 'https://something.com/filez'
- expect(driver.url()).to.equal 'https://something.com/filez#'
-
- it 'replaces an entire URL with a fragment correctly', ->
- driver = new Dropbox.Drivers.Popup
- receiverUrl: 'https://something.com/filez#frag'
- expect(driver.url()).to.equal 'https://something.com/filez#frag'
-
- it 'replaces an entire URL without a fragment and useQuery correctly', ->
- driver = new Dropbox.Drivers.Popup
- receiverUrl: 'https://something.com/filez', noFragment: true
- expect(driver.url()).to.equal 'https://something.com/filez'
-
- describe '#loadCredentials', ->
- beforeEach ->
- @node_js = module? and module.exports? and require?
- @chrome_app = chrome? and (chrome.extension or chrome.app?.runtime)
- return if @node_js or @chrome_app
- @client = new Dropbox.Client testKeys
- @driver = new Dropbox.Drivers.Popup scope: 'some_scope'
- @driver.setStorageKey @client
-
- it 'produces the credentials passed to storeCredentials', (done) ->
- return done() if @node_js or @chrome_app
- goldCredentials = @client.credentials()
- @driver.storeCredentials goldCredentials, =>
- @driver = new Dropbox.Drivers.Popup scope: 'some_scope'
- @driver.setStorageKey @client
- @driver.loadCredentials (credentials) ->
- expect(credentials).to.deep.equal goldCredentials
- done()
-
- it 'produces null after forgetCredentials was called', (done) ->
- return done() if @node_js or @chrome_app
- @driver.storeCredentials @client.credentials(), =>
- @driver.forgetCredentials =>
- @driver = new Dropbox.Drivers.Popup scope: 'some_scope'
- @driver.setStorageKey @client
- @driver.loadCredentials (credentials) ->
- expect(credentials).to.equal null
- done()
-
- it 'produces null if a different scope is provided', (done) ->
- return done() if @node_js or @chrome_app
- @driver.setStorageKey @client
- @driver.storeCredentials @client.credentials(), =>
- @driver = new Dropbox.Drivers.Popup scope: 'other_scope'
- @driver.setStorageKey @client
- @driver.loadCredentials (credentials) ->
- expect(credentials).to.equal null
- done()
-
- describe 'integration', ->
- beforeEach ->
- @node_js = module? and module.exports? and require?
- @chrome_app = chrome? and (chrome.extension or chrome.app?.runtime)
-
- it 'should work with a query string', (done) ->
- return done() if @node_js or @chrome_app
- @timeout 45 * 1000 # Time-consuming because the user must click.
-
- client = new Dropbox.Client testKeys
- client.reset()
- authDriver = new Dropbox.Drivers.Popup
- receiverFile: 'oauth_receiver.html', noFragment: true,
- scope: 'popup-integration', rememberUser: false
- client.authDriver authDriver
- client.authenticate (error, client) =>
- expect(error).to.equal null
- expect(client.authState).to.equal Dropbox.Client.DONE
- # Verify that we can do API calls.
- client.getUserInfo (error, userInfo) ->
- expect(error).to.equal null
- expect(userInfo).to.be.instanceOf Dropbox.UserInfo
-
- # Follow-up authenticate() should restart the process.
- client.reset()
- authDriver.doAuthorize = (authUrl, token, tokenSecret, callback) ->
- client.reset()
- done()
- client.authenticate ->
- assert false, 'The second authenticate() should not complete.'
-
- it 'should work with a URL fragment and rememberUser: true', (done) ->
- return done() if @node_js or @chrome_app
- @timeout 45 * 1000 # Time-consuming because the user must click.
-
- client = new Dropbox.Client testKeys
- client.reset()
- authDriver = new Dropbox.Drivers.Popup
- receiverFile: 'oauth_receiver.html', noFragment: false,
- scope: 'popup-integration', rememberUser: true
- client.authDriver authDriver
- authDriver.setStorageKey client
- authDriver.forgetCredentials ->
- client.authenticate (error, client) ->
- expect(error).to.equal null
- expect(client.authState).to.equal Dropbox.Client.DONE
- # Verify that we can do API calls.
- client.getUserInfo (error, userInfo) ->
- expect(error).to.equal null
- expect(userInfo).to.be.instanceOf Dropbox.UserInfo
-
- # Follow-up authenticate() should use stored credentials.
- client.reset()
- authDriver.doAuthorize = (authUrl, token, tokenSecret, callback) ->
- assert false,
- 'Stored credentials not used in second authenticate()'
- client.authenticate (error, client) ->
- # Verify that we can do API calls.
- client.getUserInfo (error, userInfo) ->
- expect(error).to.equal null
- expect(userInfo).to.be.instanceOf Dropbox.UserInfo
- done()
-
-describe 'Dropbox.Drivers.Chrome', ->
- beforeEach ->
- @chrome_app = chrome? and (chrome.extension or chrome.app?.runtime)
- @client = new Dropbox.Client testKeys
-
- describe '#url', ->
- beforeEach ->
- return unless @chrome_app
- @path = 'test/html/redirect_driver_test.html'
- @driver = new Dropbox.Drivers.Chrome receiverPath: @path
-
- it 'produces a chrome-extension:// url', ->
- return unless @chrome_app
- expect(@driver.url()).to.match(/^chrome-extension:\/\//)
-
- it 'produces an URL ending in redirectPath', ->
- return unless @chrome_app
- url = @driver.url()
- expect(url.substring(url.length - @path.length)).to.equal @path
-
- describe '#loadCredentials', ->
- beforeEach ->
- return unless @chrome_app
- @client = new Dropbox.Client testKeys
- @driver = new Dropbox.Drivers.Chrome scope: 'some_scope'
-
- it 'produces the credentials passed to storeCredentials', (done) ->
- return done() unless @chrome_app
- goldCredentials = @client.credentials()
- @driver.storeCredentials goldCredentials, =>
- @driver = new Dropbox.Drivers.Chrome scope: 'some_scope'
- @driver.loadCredentials (credentials) ->
- expect(credentials).to.deep.equal goldCredentials
- done()
-
- it 'produces null after forgetCredentials was called', (done) ->
- return done() unless @chrome_app
- @driver.storeCredentials @client.credentials(), =>
- @driver.forgetCredentials =>
- @driver = new Dropbox.Drivers.Chrome scope: 'some_scope'
- @driver.loadCredentials (credentials) ->
- expect(credentials).to.equal null
- done()
-
- it 'produces null if a different scope is provided', (done) ->
- return done() unless @chrome_app
- @driver.storeCredentials @client.credentials(), =>
- @driver = new Dropbox.Drivers.Chrome scope: 'other_scope'
- @driver.loadCredentials (credentials) ->
- expect(credentials).to.equal null
- done()
-
- describe 'integration', ->
- it 'should work', (done) ->
- return done() unless @chrome_app
- @timeout 45 * 1000 # Time-consuming because the user must click.
-
- client = new Dropbox.Client testKeys
- client.reset()
- authDriver = new Dropbox.Drivers.Chrome(
- receiverPath: 'test/html/chrome_oauth_receiver.html',
- scope: 'chrome_integration')
- client.authDriver authDriver
- authDriver.forgetCredentials ->
- client.authenticate (error, client) ->
- expect(error).to.equal null
- expect(client.authState).to.equal Dropbox.Client.DONE
- # Verify that we can do API calls.
- client.getUserInfo (error, userInfo) ->
- expect(error).to.equal null
- expect(userInfo).to.be.instanceOf Dropbox.UserInfo
- # Follow-up authenticate() should use stored credentials.
- client.reset()
- authDriver.doAuthorize = (authUrl, token, tokenSecret, callback) ->
- assert false,
- 'Stored credentials not used in second authenticate()'
- client.authenticate (error, client) ->
- # Verify that we can do API calls.
- client.getUserInfo (error, userInfo) ->
- expect(error).to.equal null
- expect(userInfo).to.be.instanceOf Dropbox.UserInfo
- done()
diff --git a/lib/client/storage/dropbox/test/src/event_source_test.coffee b/lib/client/storage/dropbox/test/src/event_source_test.coffee
deleted file mode 100644
index e7440b0f..00000000
--- a/lib/client/storage/dropbox/test/src/event_source_test.coffee
+++ /dev/null
@@ -1,144 +0,0 @@
-describe 'Dropbox.EventSource', ->
- beforeEach ->
- @source = new Dropbox.EventSource
- @cancelable = new Dropbox.EventSource cancelable: true
-
- # 3 listeners, 1 and 2 are already hooked up
- @event1 = null
- @return1 = true
- @listener1 = (event) =>
- @event1 = event
- @return1
- @source.addListener @listener1
- @cancelable.addListener @listener1
- @event2 = null
- @return2 = false
- @listener2 = (event) =>
- @event2 = event
- @return2
- @source.addListener @listener2
- @cancelable.addListener @listener2
- @event3 = null
- @return3 = true
- @listener3 = (event) =>
- @event3 = event
- @return3
-
- describe '#addListener', ->
- it 'adds a new listener', ->
- @source.addListener @listener3
- expect(@source._listeners).to.deep.
- equal [@listener1, @listener2, @listener3]
-
- it 'does not add an existing listener', ->
- @source.addListener @listener2
- expect(@source._listeners).to.deep.equal [@listener1, @listener2]
-
- it 'is idempotent', ->
- @source.addListener @listener3
- @source.addListener @listener3
- expect(@source._listeners).to.deep.
- equal [@listener1, @listener2, @listener3]
-
- it 'refuses to add non-functions', ->
- expect(=> @source.addListener 42).to.throw(TypeError, /listener type/)
-
- describe '#removeListener', ->
- it 'does nothing for a non-existing listener', ->
- @source.removeListener @listener3
- expect(@source._listeners).to.deep.equal [@listener1, @listener2]
-
- it 'removes a listener at the end of the queue', ->
- @source.removeListener @listener2
- expect(@source._listeners).to.deep.equal [@listener1]
-
- it 'removes a listener at the beginning of the queue', ->
- @source.removeListener @listener1
- expect(@source._listeners).to.deep.equal [@listener2]
-
- it 'removes a listener at the middle of the queue', ->
- @source.addListener @listener3
- @source.removeListener @listener2
- expect(@source._listeners).to.deep.equal [@listener1, @listener3]
-
- it 'removes all the listeners', ->
- @source.removeListener @listener1
- @source.removeListener @listener2
- expect(@source._listeners).to.deep.equal []
-
- describe 'without ES5 Array#indexOf', ->
- beforeEach ->
- @source._listeners.indexOf = null
-
- afterEach ->
- delete @source._listeners.indexOf
-
- assertArraysEqual = (array1, array2) ->
- expect(array1.length).to.equal(array2.length)
- for i in [0...array1.length]
- expect(array1[i]).to.equal(array2[i])
-
- it 'does nothing for a non-existing listener', ->
- @source.removeListener @listener3
- assertArraysEqual @source._listeners, [@listener1, @listener2]
-
- it 'removes a listener at the end of the queue', ->
- @source.removeListener @listener2
- assertArraysEqual @source._listeners, [@listener1]
-
- it 'removes a listener at the beginning of the queue', ->
- @source.removeListener @listener1
- assertArraysEqual @source._listeners, [@listener2]
-
- it 'removes a listener at the middle of the queue', ->
- @source.addListener @listener3
- @source.removeListener @listener2
- assertArraysEqual @source._listeners, [@listener1, @listener3]
-
- it 'removes all the listeners', ->
- @source.removeListener @listener1
- @source.removeListener @listener2
- assertArraysEqual @source._listeners, []
-
- describe '#dispatch', ->
- beforeEach ->
- @event = { answer: 42 }
-
- it 'passes event to all listeners', ->
- @source.dispatch @event
- expect(@event1).to.equal @event
- expect(@event2).to.equal @event
- expect(@event3).to.equal null
-
- describe 'on non-cancelable events', ->
- beforeEach ->
- @source.addListener @listener3
- @returnValue = @source.dispatch @event
-
- it 'calls all the listeners', ->
- expect(@event1).to.equal @event
- expect(@event2).to.equal @event
- expect(@event3).to.equal @event
-
- it 'ignores the listener return values', ->
- expect(@returnValue).to.equal true
-
- describe 'on cancelable events', ->
- beforeEach ->
- @cancelable.addListener @listener3
- @returnValue = @cancelable.dispatch @event
-
- it 'stops calling listeners after cancelation', ->
- expect(@event1).to.equal @event
- expect(@event2).to.equal @event
- expect(@event3).to.equal null
-
- it 'reports cancelation', ->
- expect(@returnValue).to.equal false
-
- it 'calls all listeners if no cancelation occurs', ->
- @return2 = true
- @returnValue = @cancelable.dispatch @event
-
- expect(@returnValue).to.equal true
- expect(@event3).to.equal @event
diff --git a/lib/client/storage/dropbox/test/src/helper.coffee b/lib/client/storage/dropbox/test/src/helper.coffee
deleted file mode 100644
index 2b42b86a..00000000
--- a/lib/client/storage/dropbox/test/src/helper.coffee
+++ /dev/null
@@ -1,55 +0,0 @@
-if global? and require? and module?
- # Node.JS
- exports = global
-
- exports.Dropbox = require '../../lib/dropbox'
- exports.chai = require 'chai'
- exports.sinon = require 'sinon'
- exports.sinonChai = require 'sinon-chai'
-
- exports.authDriver = new Dropbox.Drivers.NodeServer port: 8912
-
- TokenStash = require './token_stash.js'
- (new TokenStash()).get (credentials) ->
- exports.testKeys = credentials
- (new TokenStash(fullDropbox: true)).get (credentials) ->
- exports.testFullDropboxKeys = credentials
-
- testIconPath = './test/binary/dropbox.png'
- fs = require 'fs'
- buffer = fs.readFileSync testIconPath
- bytes = []
- for i in [0...buffer.length]
- bytes.push String.fromCharCode(buffer.readUInt8(i))
- exports.testImageBytes = bytes.join ''
- exports.testImageUrl = 'http://localhost:8913/favicon.ico'
- imageServer = null
- exports.testImageServerOn = ->
- imageServer =
- new Dropbox.Drivers.NodeServer port: 8913, favicon: testIconPath
- exports.testImageServerOff = ->
- imageServer.closeServer()
- imageServer = null
-else
- if chrome? and chrome.runtime
- # Chrome app
- exports = window
- exports.authDriver = new Dropbox.Drivers.Chrome(
- receiverPath: 'test/html/chrome_oauth_receiver.html',
- scope: 'helper-chrome')
- # Hack-implement "rememberUser: false" in the Chrome driver.
- exports.authDriver.storeCredentials = (credentials, callback) -> callback()
- exports.authDriver.loadCredentials = (callback) -> callback null
- else
- # Browser
- exports = window
- exports.authDriver = new Dropbox.Drivers.Popup(
- receiverFile: 'oauth_receiver.html', scope: 'helper-popup')
-
- exports.testImageUrl = '/test/binary/dropbox.png'
- exports.testImageServerOn = -> null
- exports.testImageServerOff = -> null
-
-# Shared setup.
-exports.assert = exports.chai.assert
-exports.expect = exports.chai.expect
diff --git a/lib/client/storage/dropbox/test/src/hmac_test.coffee b/lib/client/storage/dropbox/test/src/hmac_test.coffee
deleted file mode 100644
index b8fbafce..00000000
--- a/lib/client/storage/dropbox/test/src/hmac_test.coffee
+++ /dev/null
@@ -1,22 +0,0 @@
-describe 'Dropbox.hmac', ->
- it 'works for an empty message with an empty key', ->
- expect(Dropbox.hmac('', '')).to.equal '+9sdGxiqbAgyS31ktx+3Y3BpDh0='
-
- it 'works for the non-empty Wikipedia example', ->
- expect(Dropbox.hmac('The quick brown fox jumps over the lazy dog', 'key')).
- to.equal '3nybhbi3iqa8ino29wqQcBydtNk='
-
- it 'works for the Oauth example', ->
- key = 'kd94hf93k423kf44&pfkkdhi9sl3r4s00'
- string = 'GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal'
- expect(Dropbox.hmac(string, key)).to.equal 'tR3+Ty81lMeYAr/Fid0kMTYa/WM='
-
-describe 'Dropbox.sha1', ->
- it 'works for an empty message', ->
- expect(Dropbox.sha1('')).to.equal '2jmj7l5rSw0yVb/vlWAYkK/YBwk='
- it 'works for the FIPS-180 Appendix A sample', ->
- expect(Dropbox.sha1('abc')).to.equal 'qZk+NkcGgWq6PiVxeFDCbJzQ2J0='
- it 'works for the FIPS-180 Appendix B sample', ->
- string = 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'
- expect(Dropbox.sha1(string)).to.equal 'hJg+RBw70m66rkqh+VEp5eVGcPE='
-
diff --git a/lib/client/storage/dropbox/test/src/oauth_test.coffee b/lib/client/storage/dropbox/test/src/oauth_test.coffee
deleted file mode 100644
index 25dbc562..00000000
--- a/lib/client/storage/dropbox/test/src/oauth_test.coffee
+++ /dev/null
@@ -1,124 +0,0 @@
-describe 'Dropbox.Oauth', ->
- beforeEach ->
- @oauth = new Dropbox.Oauth
- key: 'dpf43f3p2l4k3l03',
- secret: 'kd94hf93k423kf44'
- @oauth.setToken 'nnch734d00sl2jdk', 'pfkkdhi9sl3r4s00'
-
- # The example in OAuth 1.0a Appendix A.
- @request =
- method: 'GET',
- url: 'http://photos.example.net/photos'
- params:
- file: 'vacation.jpg',
- size: 'original'
- @dateStub = sinon.stub Date, 'now'
- @dateStub.returns 1191242096999
-
- afterEach ->
- @dateStub.restore()
-
- describe '#boilerplateParams', ->
- it 'issues unique nonces', ->
- nonces = {}
- for i in [1..100]
- nonce = @oauth.boilerplateParams({}).oauth_nonce
- expect(nonces).not.to.have.property nonce
- nonces[nonce] = true
-
- it 'fills all the arguments', ->
- params = @oauth.boilerplateParams(@request.params)
- properties = ['oauth_consumer_key', 'oauth_nonce',
- 'oauth_signature_method', 'oauth_timestamp',
- 'oauth_version']
- for property in properties
- expect(params).to.have.property property
-
- describe '#signature', ->
- it 'works for the OAuth 1.0a example', ->
- @nonceStub = sinon.stub @oauth, 'nonce'
- @nonceStub.returns 'kllo9940pd9333jh'
-
- @oauth.boilerplateParams(@request.params)
- expect(@oauth.signature(@request.method, @request.url, @request.params)).
- to.equal 'tR3+Ty81lMeYAr/Fid0kMTYa/WM='
-
- @nonceStub.restore()
-
- it 'works with an encoded key', ->
- @oauth = new Dropbox.Oauth
- key: Dropbox.encodeKey(@oauth.key, @oauth.secret),
- token: @oauth.token, tokenSecret: @oauth.tokenSecret
-
- @nonceStub = sinon.stub @oauth, 'nonce'
- @nonceStub.returns 'kllo9940pd9333jh'
-
- @oauth.boilerplateParams(@request.params)
- expect(@oauth.signature(@request.method, @request.url, @request.params)).
- to.equal 'tR3+Ty81lMeYAr/Fid0kMTYa/WM='
-
- @nonceStub.restore()
-
- describe '#addAuthParams', ->
- it 'matches the OAuth 1.0a example', ->
- @nonceStub = sinon.stub @oauth, 'nonce'
- @nonceStub.returns 'kllo9940pd9333jh'
-
- goldenParams =
- file: 'vacation.jpg'
- oauth_consumer_key: 'dpf43f3p2l4k3l03'
- oauth_nonce: 'kllo9940pd9333jh'
- oauth_signature: 'tR3+Ty81lMeYAr/Fid0kMTYa/WM='
- oauth_signature_method: 'HMAC-SHA1'
- oauth_timestamp: '1191242096'
- oauth_token: 'nnch734d00sl2jdk'
- oauth_version: '1.0'
- size: 'original'
-
- @oauth.addAuthParams @request.method, @request.url, @request.params
- expect(Dropbox.Xhr.urlEncode(@request.params)).to.
- eql Dropbox.Xhr.urlEncode(goldenParams)
-
- @nonceStub.restore()
-
- it "doesn't leave any OAuth-related value in params", ->
- @oauth.authHeader(@request.method, @request.url, @request.params)
- expect(Dropbox.Xhr.urlEncode(@request.params)).to.
- equal "file=vacation.jpg&size=original"
-
- describe '#authHeader', ->
- it 'matches the OAuth 1.0a example', ->
- @nonceStub = sinon.stub @oauth, 'nonce'
- @nonceStub.returns 'kllo9940pd9333jh'
-
- goldenHeader = 'OAuth oauth_consumer_key="dpf43f3p2l4k3l03",oauth_nonce="kllo9940pd9333jh",oauth_signature="tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1191242096",oauth_token="nnch734d00sl2jdk",oauth_version="1.0"'
- header = @oauth.authHeader @request.method, @request.url, @request.params
- expect(header).to.equal goldenHeader
-
- @nonceStub.restore()
-
- it "doesn't leave any OAuth-related value in params", ->
- @oauth.authHeader(@request.method, @request.url, @request.params)
- expect(Dropbox.Xhr.urlEncode(@request.params)).to.
- equal "file=vacation.jpg&size=original"
-
- describe '#appHash', ->
- it 'is a non-trivial string', ->
- expect(@oauth.appHash()).to.be.a 'string'
- expect(@oauth.appHash().length).to.be.greaterThan 4
-
- it 'is consistent', ->
- oauth = new Dropbox.Oauth key: @oauth.key, secret: @oauth.secret
- expect(oauth.appHash()).to.equal @oauth.appHash()
-
- it 'depends on the app key', ->
- oauth = new Dropbox.Oauth key: @oauth.key + '0', secret: @oauth.secret
- expect(oauth.appHash()).not.to.equal @oauth.appHash()
- expect(oauth.appHash()).to.be.a 'string'
- expect(oauth.appHash().length).to.be.greaterThan 4
-
- describe '#constructor', ->
- it 'raises an Error if initialized without an API key / secret', ->
- expect(-> new Dropbox.Oauth(token: '123', tokenSecret: '456')).to.
- throw(Error, /no api key/i)
-
diff --git a/lib/client/storage/dropbox/test/src/pulled_changes_test.coffee b/lib/client/storage/dropbox/test/src/pulled_changes_test.coffee
deleted file mode 100644
index 4d2fe67d..00000000
--- a/lib/client/storage/dropbox/test/src/pulled_changes_test.coffee
+++ /dev/null
@@ -1,128 +0,0 @@
-describe 'Dropbox.PulledChanges', ->
- describe '.parse', ->
- describe 'on a sample response', ->
- beforeEach ->
- deltaInfo = {
- "reset": false,
- "cursor": "nTZYLOcTQnyB7-Wc72M-kEAcBQdk2EjLaJIRupQWgDXmRwKWzuG5V4se2mvU7yzXn4cZSJltoW4tpbqgy0Ezxh1b1p3ygp7wy-vdaYJusujnLAyEsKdYCHPZYZdZt7sQG0BopF2ufAuD56ijYbdX5DhMKe85MFqncnFDvNxSjsodEw-IkCfNZmagDmpOZCxmLqu71hLTApwhqO9-dhm-fk6KSYs-OZwRmVwOE2JAnJbWuifNiM8KwMz5sRBZ5FMJPDqXpOW5PqPCwbkAmKQACbNXFi0k1JuxulpDlQh3zMr3lyLMs-fmaDTTU355mY5xSAXK05Zgs5rPJ6lcaBOUmEBSXcPhxFDHk5NmAdA03Shq04t2_4bupzWX-txT84FmOLNncchl7ZDBCMwyrAzD2kCYOTu1_lhui0C-fiCZgZBKU4OyP6qrkdo4gZu3",
- "has_more": true,
- "entries": [
- [
- "/Getting_Started.pdf",
- {
- "size": "225.4KB",
- "rev": "35e97029684fe",
- "thumb_exists": true, # Changed to test hasThumbnail=true code.
- "bytes": 230783,
- "modified": "Tue, 19 Jul 2011 21:55:38 +0000",
- "client_mtime": "Mon, 18 Jul 2011 18:04:35 +0000",
- "path": "/Getting_Started.pdf",
- "is_dir": false,
- "icon": "page_white_acrobat",
- "root": "app_folder", # Changed to test app_folder code path.
- "mime_type": "application/pdf",
- "revision": 220823
- }
- ],
- [
- "/Public",
- null
- ]
- ]
- }
- @changes = Dropbox.PulledChanges.parse deltaInfo
-
- it 'parses blankSlate correctly', ->
- expect(@changes).to.have.property 'blankSlate'
- expect(@changes.blankSlate).to.equal false
-
- it 'parses cursorTag correctly', ->
- expect(@changes).to.have.property 'cursorTag'
- expect(@changes.cursorTag).to.equal 'nTZYLOcTQnyB7-Wc72M-kEAcBQdk2EjLaJIRupQWgDXmRwKWzuG5V4se2mvU7yzXn4cZSJltoW4tpbqgy0Ezxh1b1p3ygp7wy-vdaYJusujnLAyEsKdYCHPZYZdZt7sQG0BopF2ufAuD56ijYbdX5DhMKe85MFqncnFDvNxSjsodEw-IkCfNZmagDmpOZCxmLqu71hLTApwhqO9-dhm-fk6KSYs-OZwRmVwOE2JAnJbWuifNiM8KwMz5sRBZ5FMJPDqXpOW5PqPCwbkAmKQACbNXFi0k1JuxulpDlQh3zMr3lyLMs-fmaDTTU355mY5xSAXK05Zgs5rPJ6lcaBOUmEBSXcPhxFDHk5NmAdA03Shq04t2_4bupzWX-txT84FmOLNncchl7ZDBCMwyrAzD2kCYOTu1_lhui0C-fiCZgZBKU4OyP6qrkdo4gZu3'
-
- it 'parses shouldPullAgain correctly', ->
- expect(@changes).to.have.property 'shouldPullAgain'
- expect(@changes.shouldPullAgain).to.equal true
-
- it 'parses shouldBackOff correctly', ->
- expect(@changes).to.have.property 'shouldBackOff'
- expect(@changes.shouldBackOff).to.equal false
-
- it 'parses changes correctly', ->
- expect(@changes).to.have.property 'changes'
- expect(@changes.changes).to.have.length 2
- expect(@changes.changes[0]).to.be.instanceOf Dropbox.PullChange
- expect(@changes.changes[0].path).to.equal '/Getting_Started.pdf'
- expect(@changes.changes[1]).to.be.instanceOf Dropbox.PullChange
- expect(@changes.changes[1].path).to.equal '/Public'
-
- it 'passes null through', ->
- expect(Dropbox.PulledChanges.parse(null)).to.equal null
-
- it 'passes undefined through', ->
- expect(Dropbox.PulledChanges.parse(undefined)).to.equal undefined
-
-
-describe 'Dropbox.PullChange', ->
- describe '.parse', ->
- describe 'on a modification change', ->
- beforeEach ->
- entry = [
- "/Getting_Started.pdf",
- {
- "size": "225.4KB",
- "rev": "35e97029684fe",
- "thumb_exists": true, # Changed to test hasThumbnail=true code.
- "bytes": 230783,
- "modified": "Tue, 19 Jul 2011 21:55:38 +0000",
- "client_mtime": "Mon, 18 Jul 2011 18:04:35 +0000",
- "path": "/Getting_Started.pdf",
- "is_dir": false,
- "icon": "page_white_acrobat",
- "root": "app_folder", # Changed to test app_folder code path.
- "mime_type": "application/pdf",
- "revision": 220823
- }
- ]
- @changes = Dropbox.PullChange.parse entry
-
- it 'parses path correctly', ->
- expect(@changes).to.have.property 'path'
- expect(@changes.path).to.equal '/Getting_Started.pdf'
-
- it 'parses wasRemoved correctly', ->
- expect(@changes).to.have.property 'wasRemoved'
- expect(@changes.wasRemoved).to.equal false
-
- it 'parses stat correctly', ->
- expect(@changes).to.have.property 'stat'
- expect(@changes.stat).to.be.instanceOf Dropbox.Stat
- expect(@changes.stat.path).to.equal @changes.path
-
- describe 'on a deletion change', ->
- beforeEach ->
- entry = [
- "/Public",
- null
- ]
- @changes = Dropbox.PullChange.parse entry
-
- it 'parses path correctly', ->
- expect(@changes).to.have.property 'path'
- expect(@changes.path).to.equal '/Public'
-
- it 'parses wasRemoved correctly', ->
- expect(@changes).to.have.property 'wasRemoved'
- expect(@changes.wasRemoved).to.equal true
-
- it 'parses stat correctly', ->
- expect(@changes).to.have.property 'stat'
- expect(@changes.stat).to.equal null
-
- it 'passes null through', ->
- expect(Dropbox.PullChange.parse(null)).to.equal null
-
- it 'passes undefined through', ->
- expect(Dropbox.PullChange.parse(undefined)).to.equal undefined
-
-
diff --git a/lib/client/storage/dropbox/test/src/references_test.coffee b/lib/client/storage/dropbox/test/src/references_test.coffee
deleted file mode 100644
index ac03c567..00000000
--- a/lib/client/storage/dropbox/test/src/references_test.coffee
+++ /dev/null
@@ -1,92 +0,0 @@
-describe 'Dropbox.PublicUrl', ->
- describe '.parse', ->
- describe 'on the /shares API example', ->
- beforeEach ->
- urlData = {
- "url": "http://db.tt/APqhX1",
- "expires": "Tue, 01 Jan 2030 00:00:00 +0000"
- }
- @url = Dropbox.PublicUrl.parse urlData, false
-
- it 'parses url correctly', ->
- expect(@url).to.have.property 'url'
- expect(@url.url).to.equal 'http://db.tt/APqhX1'
-
- it 'parses expiresAt correctly', ->
- expect(@url).to.have.property 'expiresAt'
- expect(@url.expiresAt).to.be.instanceOf Date
- expect([
- 'Tue, 01 Jan 2030 00:00:00 GMT', # every sane JS platform
- 'Tue, 1 Jan 2030 00:00:00 UTC' # Internet Explorer
- ]).to.contain(@url.expiresAt.toUTCString())
-
- it 'parses isDirect correctly', ->
- expect(@url).to.have.property 'isDirect'
- expect(@url.isDirect).to.equal false
-
- it 'parses isPreview correctly', ->
- expect(@url).to.have.property 'isPreview'
- expect(@url.isPreview).to.equal true
-
- it 'round-trips through json / parse correctly', ->
- newUrl = Dropbox.PublicUrl.parse @url.json()
- newUrl.json() # Get _json populated for newUrl.
- expect(newUrl).to.deep.equal @url
-
- it 'passes null through', ->
- expect(Dropbox.PublicUrl.parse(null)).to.equal null
-
- it 'passes undefined through', ->
- expect(Dropbox.PublicUrl.parse(undefined)).to.equal undefined
-
-
-describe 'Dropbox.CopyReference', ->
- describe '.parse', ->
- describe 'on the API example', ->
- beforeEach ->
- refData = {
- "copy_ref": "z1X6ATl6aWtzOGq0c3g5Ng",
- "expires": "Fri, 31 Jan 2042 21:01:05 +0000"
- }
- @ref = Dropbox.CopyReference.parse refData
-
- it 'parses tag correctly', ->
- expect(@ref).to.have.property 'tag'
- expect(@ref.tag).to.equal 'z1X6ATl6aWtzOGq0c3g5Ng'
-
- it 'parses expiresAt correctly', ->
- expect(@ref).to.have.property 'expiresAt'
- expect(@ref.expiresAt).to.be.instanceOf Date
- expect([
- 'Fri, 31 Jan 2042 21:01:05 GMT', # every sane JS platform
- 'Fri, 31 Jan 2042 21:01:05 UTC' # Internet Explorer
- ]).to.contain(@ref.expiresAt.toUTCString())
-
- it 'round-trips through json / parse correctly', ->
- newRef = Dropbox.CopyReference.parse @ref.json()
- expect(newRef).to.deep.equal @ref
-
- describe 'on a reference string', ->
- beforeEach ->
- rawRef = 'z1X6ATl6aWtzOGq0c3g5Ng'
- @ref = Dropbox.CopyReference.parse rawRef
-
- it 'parses tag correctly', ->
- expect(@ref).to.have.property 'tag'
- expect(@ref.tag).to.equal 'z1X6ATl6aWtzOGq0c3g5Ng'
-
- it 'parses expiresAt correctly', ->
- expect(@ref).to.have.property 'expiresAt'
- expect(@ref.expiresAt).to.be.instanceOf Date
- expect(@ref.expiresAt - (new Date())).to.be.below 1000
-
- it 'round-trips through json / parse correctly', ->
- newRef = Dropbox.CopyReference.parse @ref.json()
- expect(newRef).to.deep.equal @ref
-
- it 'passes null through', ->
- expect(Dropbox.CopyReference.parse(null)).to.equal null
-
- it 'passes undefined through', ->
- expect(Dropbox.CopyReference.parse(undefined)).to.equal undefined
-
diff --git a/lib/client/storage/dropbox/test/src/stat_test.coffee b/lib/client/storage/dropbox/test/src/stat_test.coffee
deleted file mode 100644
index 2fecf635..00000000
--- a/lib/client/storage/dropbox/test/src/stat_test.coffee
+++ /dev/null
@@ -1,204 +0,0 @@
-describe 'Dropbox.Stat', ->
- describe '.parse', ->
- describe 'on the API file example', ->
- beforeEach ->
- # File example at
- # https://www.dropbox.com/developers/reference/api#metadata
- metadata = {
- "size": "225.4KB",
- "rev": "35e97029684fe",
- "thumb_exists": true, # Changed to test hasThumbnail=true code.
- "bytes": 230783,
- "modified": "Tue, 19 Jul 2011 21:55:38 +0000",
- "client_mtime": "Mon, 18 Jul 2011 18:04:35 +0000",
- "path": "/Getting_Started.pdf",
- "is_dir": false,
- "icon": "page_white_acrobat",
- "root": "app_folder", # Changed to test app_folder code path.
- "mime_type": "application/pdf",
- "revision": 220823
- }
- @stat = Dropbox.Stat.parse metadata
-
- it 'parses the path correctly', ->
- expect(@stat).to.have.property 'path'
- expect(@stat.path).to.equal '/Getting_Started.pdf'
-
- it 'parses name correctly', ->
- expect(@stat).to.have.property 'name'
- expect(@stat.name).to.equal 'Getting_Started.pdf'
-
- it 'parses inAppFolder corectly', ->
- expect(@stat).to.have.property 'inAppFolder'
- expect(@stat.inAppFolder).to.equal true
-
- it 'parses isFolder correctly', ->
- expect(@stat).to.have.property 'isFolder'
- expect(@stat.isFolder).to.equal false
- expect(@stat).to.have.property 'isFile'
- expect(@stat.isFile).to.equal true
-
- it 'parses isRemoved correctly', ->
- expect(@stat).to.have.property 'isRemoved'
- expect(@stat.isRemoved).to.equal false
-
- it 'parses typeIcon correctly', ->
- expect(@stat).to.have.property 'typeIcon'
- expect(@stat.typeIcon).to.equal 'page_white_acrobat'
-
- it 'parses versionTag correctly', ->
- expect(@stat).to.have.property 'versionTag'
- expect(@stat.versionTag).to.equal '35e97029684fe'
-
- it 'parses mimeType correctly', ->
- expect(@stat).to.have.property 'mimeType'
- expect(@stat.mimeType).to.equal 'application/pdf'
-
- it 'parses size correctly', ->
- expect(@stat).to.have.property 'size'
- expect(@stat.size).to.equal 230783
-
- it 'parses humanSize correctly', ->
- expect(@stat).to.have.property 'humanSize'
- expect(@stat.humanSize).to.equal "225.4KB"
-
- it 'parses hasThumbnail correctly', ->
- expect(@stat).to.have.property 'hasThumbnail'
- expect(@stat.hasThumbnail).to.equal true
-
- it 'parses modifiedAt correctly', ->
- expect(@stat).to.have.property 'modifiedAt'
- expect(@stat.modifiedAt).to.be.instanceOf Date
- expect([
- 'Tue, 19 Jul 2011 21:55:38 GMT', # every sane JS platform
- 'Tue, 19 Jul 2011 21:55:38 UTC' # Internet Explorer
- ]).to.contain(@stat.modifiedAt.toUTCString())
-
- it 'parses clientModifiedAt correctly', ->
- expect(@stat).to.have.property 'clientModifiedAt'
- expect(@stat.clientModifiedAt).to.be.instanceOf Date
- expect([
- 'Mon, 18 Jul 2011 18:04:35 GMT', # every sane JS platform
- 'Mon, 18 Jul 2011 18:04:35 UTC' # Internet Explorer
- ]).to.contain(@stat.clientModifiedAt.toUTCString())
-
- it 'round-trips through json / parse correctly', ->
- newStat = Dropbox.Stat.parse @stat.json()
- expect(newStat).to.deep.equal @stat
-
-
- describe 'on the API directory example', ->
- beforeEach ->
- # Folder example at
- # https://www.dropbox.com/developers/reference/api#metadata
- metadata = {
- "size": "0 bytes",
- "hash": "37eb1ba1849d4b0fb0b28caf7ef3af52",
- "bytes": 0,
- "thumb_exists": false,
- "rev": "714f029684fe",
- "modified": "Wed, 27 Apr 2011 22:18:51 +0000",
- "path": "/Public",
- "is_dir": true,
- "is_deleted": true, # Added to test isRemoved=true code path.
- "icon": "folder_public",
- "root": "dropbox",
- "revision": 29007
- }
- @stat = Dropbox.Stat.parse metadata
-
- it 'parses path correctly', ->
- expect(@stat).to.have.property 'path'
- expect(@stat.path).to.equal '/Public'
-
- it 'parses name correctly', ->
- expect(@stat).to.have.property 'name'
- expect(@stat.name).to.equal 'Public'
-
- it 'parses inAppFolder corectly', ->
- expect(@stat).to.have.property 'inAppFolder'
- expect(@stat.inAppFolder).to.equal false
-
- it 'parses isFolder correctly', ->
- expect(@stat).to.have.property 'isFolder'
- expect(@stat.isFolder).to.equal true
- expect(@stat).to.have.property 'isFile'
- expect(@stat.isFile).to.equal false
-
- it 'parses isRemoved correctly', ->
- expect(@stat).to.have.property 'isRemoved'
- expect(@stat.isRemoved).to.equal true
-
- it 'parses typeIcon correctly', ->
- expect(@stat).to.have.property 'typeIcon'
- expect(@stat.typeIcon).to.equal 'folder_public'
-
- it 'parses versionTag correctly', ->
- expect(@stat).to.have.property 'versionTag'
- expect(@stat.versionTag).to.equal '37eb1ba1849d4b0fb0b28caf7ef3af52'
-
- it 'parses mimeType correctly', ->
- expect(@stat).to.have.property 'mimeType'
- expect(@stat.mimeType).to.equal 'inode/directory'
-
- it 'parses size correctly', ->
- expect(@stat).to.have.property 'size'
- expect(@stat.size).to.equal 0
-
- it 'parses humanSize correctly', ->
- expect(@stat).to.have.property 'humanSize'
- expect(@stat.humanSize).to.equal '0 bytes'
-
- it 'parses hasThumbnail correctly', ->
- expect(@stat).to.have.property 'hasThumbnail'
- expect(@stat.hasThumbnail).to.equal false
-
- it 'parses modifiedAt correctly', ->
- expect(@stat).to.have.property 'modifiedAt'
- expect(@stat.modifiedAt).to.be.instanceOf Date
- expect([
- 'Wed, 27 Apr 2011 22:18:51 GMT', # every sane JS platform
- 'Wed, 27 Apr 2011 22:18:51 UTC' # Internet Explorer
- ]).to.contain(@stat.modifiedAt.toUTCString())
-
- it 'parses missing clientModifiedAt correctly', ->
- expect(@stat).to.have.property 'clientModifiedAt'
- expect(@stat.clientModifiedAt).to.equal null
-
- it 'round-trips through json / parse correctly', ->
- newStat = Dropbox.Stat.parse @stat.json()
- expect(newStat).to.deep.equal @stat
-
- it 'passes null through', ->
- expect(Dropbox.Stat.parse(null)).to.equal null
-
- it 'passes undefined through', ->
- expect(Dropbox.Stat.parse(undefined)).to.equal undefined
-
- describe 'on a contrived file/path example', ->
- beforeEach ->
- metadata = {
- "size": "225.4KB",
- "rev": "35e97029684fe",
- "thumb_exists": true, # Changed to test hasThumbnail=true code.
- "bytes": 230783,
- "modified": "Tue, 19 Jul 2011 21:55:38 +0000",
- "client_mtime": "Mon, 18 Jul 2011 18:04:35 +0000",
- "path": "path/to/a/file/named/Getting_Started.pdf/",
- "is_dir": false,
- "icon": "page_white_acrobat",
- "root": "app_folder", # Changed to test app_folder code path.
- "mime_type": "application/pdf",
- "revision": 220823
- }
- @stat = Dropbox.Stat.parse metadata
-
- it 'parses the path correctly', ->
- expect(@stat).to.have.property 'path'
- expect(@stat.path).to.equal '/path/to/a/file/named/Getting_Started.pdf'
-
- it 'parses name correctly', ->
- expect(@stat).to.have.property 'name'
- expect(@stat.name).to.equal 'Getting_Started.pdf'
-
-
diff --git a/lib/client/storage/dropbox/test/src/token_stash.coffee b/lib/client/storage/dropbox/test/src/token_stash.coffee
deleted file mode 100644
index 8dec2440..00000000
--- a/lib/client/storage/dropbox/test/src/token_stash.coffee
+++ /dev/null
@@ -1,105 +0,0 @@
-# Stashes Dropbox access credentials.
-class TokenStash
- # @param {Object} options the advanced options below
- # @option options {Boolean} fullDropbox if true, the returned credentials
- # will be good for full Dropbox access; otherwise, the credentials will
- # work for Folder access
- constructor: (options) ->
- @fs = require 'fs'
- # Node 0.6 hack.
- unless @fs.existsSync
- path = require 'path'
- @fs.existsSync = (filePath) -> path.existsSync filePath
- @getCache = null
- @sandbox = !options?.fullDropbox
- @setupFs()
-
- # Calls the supplied method with the Dropbox access credentials.
- get: (callback) ->
- @getCache or= @readStash()
- if @getCache
- callback @getCache
- return null
-
- @liveLogin (fullCredentials, sandboxCredentials) =>
- unless fullCredentials and sandboxCredentials
- throw new Error('Dropbox API authorization failed')
-
- @writeStash fullCredentials, sandboxCredentials
- @getCache = @readStash()
- callback @getCache
-
- # Obtains credentials by doing a login on the live site.
- liveLogin: (callback) ->
- Dropbox = require '../../lib/dropbox'
- sandboxClient = new Dropbox.Client @clientOptions().sandbox
- fullClient = new Dropbox.Client @clientOptions().full
- @setupAuth()
- sandboxClient.authDriver @authDriver
- sandboxClient.authenticate (error, data) =>
- if error
- @killAuth()
- callback null
- return
- fullClient.authDriver @authDriver
- fullClient.authenticate (error, data) =>
- @killAuth()
- if error
- callback null
- return
- credentials = @clientOptions()
- callback fullClient.credentials(), sandboxClient.credentials()
-
- # Returns the options used to create a Dropbox Client.
- clientOptions: ->
- {
- sandbox:
- sandbox: true
- key: 'gWJAiHNbmDA=|MJ3xAk3nLeByuOckISnHib+h+1zTCG3TKTOEFvAAZw=='
- full:
- key: 'OYaTsqx6IXA=|z8mRqmTRoSdCqvkTvHTZq4ZZNxa7I5wM8X5E33IwCA=='
- }
-
- # Reads the file containing the access credentials, if it is available.
- #
- # @return {Object?} parsed access credentials, or null if they haven't been
- # stashed
- readStash: ->
- unless @fs.existsSync @jsonPath
- return null
- stash = JSON.parse @fs.readFileSync @jsonPath
- if @sandbox then stash.sandbox else stash.full
-
- # Stashes the access credentials for future test use.
- writeStash: (fullCredentials, sandboxCredentials) ->
- json = JSON.stringify full: fullCredentials, sandbox: sandboxCredentials
- @fs.writeFileSync @jsonPath, json
-
- js = "window.testKeys = #{JSON.stringify sandboxCredentials};" +
- "window.testFullDropboxKeys = #{JSON.stringify fullCredentials};"
- @fs.writeFileSync @jsPath, js
-
- # Sets up a node.js server-based authentication driver.
- setupAuth: ->
- return if @authDriver
-
- Dropbox = require '../../lib/dropbox'
- @authDriver = new Dropbox.Drivers.NodeServer
-
- # Shuts down the node.js server behind the authentication server.
- killAuth: ->
- return unless @authDriver
-
- @authDriver.closeServer()
- @authDriver = null
-
- # Sets up the directory structure for the credential stash.
- setupFs: ->
- @dirPath = 'test/.token'
- @jsonPath = 'test/.token/token.json'
- @jsPath = 'test/.token/token.js'
-
- unless @fs.existsSync @dirPath
- @fs.mkdirSync @dirPath
-
-module.exports = TokenStash
diff --git a/lib/client/storage/dropbox/test/src/upload_cursor_test.coffee b/lib/client/storage/dropbox/test/src/upload_cursor_test.coffee
deleted file mode 100644
index 6997bda5..00000000
--- a/lib/client/storage/dropbox/test/src/upload_cursor_test.coffee
+++ /dev/null
@@ -1,114 +0,0 @@
-describe 'Dropbox.UploadCursor', ->
- describe '.parse', ->
- describe 'on the API example', ->
- beforeEach ->
- cursorData = {
- "upload_id": "v0k84B0AT9fYkfMUp0sBTA",
- "offset": 31337,
- "expires": "Tue, 19 Jul 2011 21:55:38 +0000"
- }
- @cursor = Dropbox.UploadCursor.parse cursorData
-
- it 'parses tag correctly', ->
- expect(@cursor).to.have.property 'tag'
- expect(@cursor.tag).to.equal 'v0k84B0AT9fYkfMUp0sBTA'
-
- it 'parses offset correctly', ->
- expect(@cursor).to.have.property 'offset'
- expect(@cursor.offset).to.equal 31337
-
- it 'parses expiresAt correctly', ->
- expect(@cursor).to.have.property 'expiresAt'
- expect(@cursor.expiresAt).to.be.instanceOf Date
- expect([
- 'Tue, 19 Jul 2011 21:55:38 GMT', # every sane JS platform
- 'Tue, 19 Jul 2011 21:55:38 UTC' # Internet Explorer
- ]).to.contain(@cursor.expiresAt.toUTCString())
-
- it 'round-trips through json / parse correctly', ->
- newCursor = Dropbox.UploadCursor.parse @cursor.json()
- expect(newCursor).to.deep.equal @cursor
-
- describe 'on a reference string', ->
- beforeEach ->
- rawRef = 'v0k84B0AT9fYkfMUp0sBTA'
- @cursor = Dropbox.UploadCursor.parse rawRef
-
- it 'parses tag correctly', ->
- expect(@cursor).to.have.property 'tag'
- expect(@cursor.tag).to.equal 'v0k84B0AT9fYkfMUp0sBTA'
-
- it 'parses offset correctly', ->
- expect(@cursor).to.have.property 'offset'
- expect(@cursor.offset).to.equal 0
-
- it 'parses expiresAt correctly', ->
- expect(@cursor).to.have.property 'expiresAt'
- expect(@cursor.expiresAt).to.be.instanceOf Date
- expect(@cursor.expiresAt - (new Date())).to.be.below 1000
-
- it 'round-trips through json / parse correctly', ->
- newCursor = Dropbox.UploadCursor.parse @cursor.json()
- newCursor.json() # Get _json populated for newCursor.
- expect(newCursor).to.deep.equal @cursor
-
- it 'passes null through', ->
- expect(Dropbox.CopyReference.parse(null)).to.equal null
-
- it 'passes undefined through', ->
- expect(Dropbox.CopyReference.parse(undefined)).to.equal undefined
-
- describe '.constructor', ->
- describe 'with no arguments', ->
- beforeEach ->
- @cursor = new Dropbox.UploadCursor
-
- it 'sets up tag correctly', ->
- expect(@cursor).to.have.property 'tag'
- expect(@cursor.tag).to.equal null
-
- it 'parses offset correctly', ->
- expect(@cursor).to.have.property 'offset'
- expect(@cursor.offset).to.equal 0
-
- it 'parses expiresAt correctly', ->
- expect(@cursor).to.have.property 'expiresAt'
- expect(@cursor.expiresAt - (new Date())).to.be.below 1000
-
- it 'round-trips through json / parse correctly', ->
- newCursor = Dropbox.UploadCursor.parse @cursor.json()
- newCursor.json() # Get _json populated for newCursor.
- expect(newCursor).to.deep.equal @cursor
-
- describe '.replace', ->
- beforeEach ->
- @cursor = new Dropbox.UploadCursor
-
- describe 'on the API example', ->
- beforeEach ->
- cursorData = {
- "upload_id": "v0k84B0AT9fYkfMUp0sBTA",
- "offset": 31337,
- "expires": "Tue, 19 Jul 2011 21:55:38 +0000"
- }
- @cursor.replace cursorData
-
- it 'parses tag correctly', ->
- expect(@cursor).to.have.property 'tag'
- expect(@cursor.tag).to.equal 'v0k84B0AT9fYkfMUp0sBTA'
-
- it 'parses offset correctly', ->
- expect(@cursor).to.have.property 'offset'
- expect(@cursor.offset).to.equal 31337
-
- it 'parses expiresAt correctly', ->
- expect(@cursor).to.have.property 'expiresAt'
- expect(@cursor.expiresAt).to.be.instanceOf Date
- expect([
- 'Tue, 19 Jul 2011 21:55:38 GMT', # every sane JS platform
- 'Tue, 19 Jul 2011 21:55:38 UTC' # Internet Explorer
- ]).to.contain(@cursor.expiresAt.toUTCString())
-
- it 'round-trips through json / parse correctly', ->
- newCursor = Dropbox.UploadCursor.parse @cursor.json()
- expect(newCursor).to.deep.equal @cursor
diff --git a/lib/client/storage/dropbox/test/src/user_info_test.coffee b/lib/client/storage/dropbox/test/src/user_info_test.coffee
deleted file mode 100644
index 65e09476..00000000
--- a/lib/client/storage/dropbox/test/src/user_info_test.coffee
+++ /dev/null
@@ -1,95 +0,0 @@
-describe 'Dropbox.UserInfo', ->
- describe '.parse', ->
- describe 'on the API example', ->
- beforeEach ->
- userData = {
- "referral_link": "https://www.dropbox.com/referrals/r1a2n3d4m5s6t7",
- "display_name": "John P. User",
- "uid": 12345678,
- "country": "US",
- "quota_info": {
- "shared": 253738410565,
- "quota": 107374182400000,
- "normal": 680031877871
- },
- "email": "johnpuser@company.com" # Added to reflect real responses.
- }
- @userInfo = Dropbox.UserInfo.parse userData
-
- it 'parses name correctly', ->
- expect(@userInfo).to.have.property 'name'
- expect(@userInfo.name).to.equal 'John P. User'
-
- it 'parses email correctly', ->
- expect(@userInfo).to.have.property 'email'
- expect(@userInfo.email).to.equal 'johnpuser@company.com'
-
- it 'parses countryCode correctly', ->
- expect(@userInfo).to.have.property 'countryCode'
- expect(@userInfo.countryCode).to.equal 'US'
-
- it 'parses uid correctly', ->
- expect(@userInfo).to.have.property 'uid'
- expect(@userInfo.uid).to.equal '12345678'
-
- it 'parses referralUrl correctly', ->
- expect(@userInfo).to.have.property 'referralUrl'
- expect(@userInfo.referralUrl).to.
- equal 'https://www.dropbox.com/referrals/r1a2n3d4m5s6t7'
-
- it 'parses quota correctly', ->
- expect(@userInfo).to.have.property 'quota'
- expect(@userInfo.quota).to.equal 107374182400000
-
- it 'parses usedQuota correctly', ->
- expect(@userInfo).to.have.property 'usedQuota'
- expect(@userInfo.usedQuota).to.equal 933770288436
-
- it 'parses privateBytes correctly', ->
- expect(@userInfo).to.have.property 'privateBytes'
- expect(@userInfo.privateBytes).to.equal 680031877871
-
- it 'parses sharedBytes correctly', ->
- expect(@userInfo).to.have.property 'usedQuota'
- expect(@userInfo.sharedBytes).to.equal 253738410565
-
- it 'parses publicAppUrl correctly', ->
- expect(@userInfo.publicAppUrl).to.equal null
-
- it 'round-trips through json / parse correctly', ->
- newInfo = Dropbox.UserInfo.parse @userInfo.json()
- expect(newInfo).to.deep.equal @userInfo
-
- it 'passes null through', ->
- expect(Dropbox.UserInfo.parse(null)).to.equal null
-
- it 'passes undefined through', ->
- expect(Dropbox.UserInfo.parse(undefined)).to.equal undefined
-
-
- describe 'on real data from a "public app folder" application', ->
- beforeEach ->
- userData = {
- "referral_link": "https://www.dropbox.com/referrals/NTM1OTg4MTA5",
- "display_name": "Victor Costan",
- "uid": 87654321, # Anonymized.
- "public_app_url": "https://dl-web.dropbox.com/spa/90vw6zlu4268jh4/",
- "country": "US",
- "quota_info": {
- "shared": 6074393565,
- "quota": 73201090560,
- "normal": 4684642723
- },
- "email": "spam@gmail.com" # Anonymized.
- }
- @userInfo = Dropbox.UserInfo.parse userData
-
- it 'parses publicAppUrl correctly', ->
- expect(@userInfo.publicAppUrl).to.
- equal 'https://dl-web.dropbox.com/spa/90vw6zlu4268jh4'
-
- it 'round-trips through json / parse correctly', ->
- newInfo = Dropbox.UserInfo.parse @userInfo.json()
- expect(newInfo).to.deep.equal @userInfo
-
-
diff --git a/lib/client/storage/dropbox/test/src/web_file_server.coffee b/lib/client/storage/dropbox/test/src/web_file_server.coffee
deleted file mode 100644
index 9c9dfd24..00000000
--- a/lib/client/storage/dropbox/test/src/web_file_server.coffee
+++ /dev/null
@@ -1,54 +0,0 @@
-express = require 'express'
-fs = require 'fs'
-https = require 'https'
-open = require 'open'
-
-# Tiny express.js server for the Web files.
-class WebFileServer
- # Starts up a HTTP server.
- constructor: (@port = 8911) ->
- @createApp()
-
- # Opens the test URL in a browser.
- openBrowser: (appName) ->
- open @testUrl(), appName
-
- # The URL that should be used to start the tests.
- testUrl: ->
- "https://localhost:#{@port}/test/html/browser_test.html"
-
- # The server code.
- createApp: ->
- @app = express()
- @app.get '/diediedie', (request, response) =>
- if 'failed' of request.query
- failed = parseInt request.query['failed']
- else
- failed = 1
- total = parseInt request.query['total'] || 0
- passed = total - failed
- exitCode = if failed == 0 then 0 else 1
- console.log "#{passed} passed, #{failed} failed"
-
- response.header 'Content-Type', 'image/png'
- response.header 'Content-Length', '0'
- response.end ''
- unless 'NO_EXIT' of process.env
- @server.close()
- process.exit exitCode
-
- @app.use (request, response, next) ->
- response.header 'Access-Control-Allow-Origin', '*'
- response.header 'Access-Control-Allow-Methods', 'DELETE,GET,POST,PUT'
- response.header 'Access-Control-Allow-Headers',
- 'Content-Type, Authorization'
- next()
-
- @app.use express.static(fs.realpathSync(__dirname + '/../../'),
- { hidden: true })
- options = key: fs.readFileSync 'test/ssl/cert.pem'
- options.cert = options.key
- @server = https.createServer(options, @app)
- @server.listen @port
-
-module.exports = new WebFileServer
diff --git a/lib/client/storage/dropbox/test/src/xhr_test.coffee b/lib/client/storage/dropbox/test/src/xhr_test.coffee
deleted file mode 100644
index afe84a69..00000000
--- a/lib/client/storage/dropbox/test/src/xhr_test.coffee
+++ /dev/null
@@ -1,644 +0,0 @@
-describe 'Dropbox.Xhr', ->
- beforeEach ->
- @node_js = module? and module?.exports? and require?
- @oauth = new Dropbox.Oauth testKeys
-
- describe 'with a GET', ->
- beforeEach ->
- @xhr = new Dropbox.Xhr 'GET', 'https://request.url'
-
- it 'initializes correctly', ->
- expect(@xhr.isGet).to.equal true
- expect(@xhr.method).to.equal 'GET'
- expect(@xhr.url).to.equal 'https://request.url'
- expect(@xhr.preflight).to.equal false
-
- describe '#setHeader', ->
- beforeEach ->
- @xhr.setHeader 'Range', 'bytes=0-1000'
-
- it 'adds a HTTP header header', ->
- expect(@xhr.headers).to.have.property 'Range'
- expect(@xhr.headers['Range']).to.equal 'bytes=0-1000'
-
- it 'does not work twice for the same header', ->
- expect(=> @xhr.setHeader('Range', 'bytes=0-1000')).to.throw Error
-
- it 'flags the Xhr as needing preflight', ->
- expect(@xhr.preflight).to.equal true
-
- it 'rejects Content-Type', ->
- expect(=> @xhr.setHeader('Content-Type', 'text/plain')).to.throw Error
-
- describe '#setParams', ->
- beforeEach ->
- @xhr.setParams 'param 1': true, 'answer': 42
-
- it 'does not flag the XHR as needing preflight', ->
- expect(@xhr.preflight).to.equal false
-
- it 'does not work twice', ->
- expect(=> @xhr.setParams 'answer': 43).to.throw Error
-
- describe '#paramsToUrl', ->
- beforeEach ->
- @xhr.paramsToUrl()
-
- it 'changes the url', ->
- expect(@xhr.url).to.
- equal 'https://request.url?answer=42¶m%201=true'
-
- it 'sets params to null', ->
- expect(@xhr.params).to.equal null
-
- describe '#paramsToBody', ->
- it 'throws an error', ->
- expect(=> @xhr.paramsToBody()).to.throw Error
-
- describe '#addOauthParams', ->
- beforeEach ->
- @xhr.addOauthParams @oauth
-
- it 'keeps existing params', ->
- expect(@xhr.params).to.have.property 'answer'
- expect(@xhr.params.answer).to.equal 42
-
- it 'adds an oauth_signature param', ->
- expect(@xhr.params).to.have.property 'oauth_signature'
-
- it 'does not add an Authorization header', ->
- expect(@xhr.headers).not.to.have.property 'Authorization'
-
- it 'does not work twice', ->
- expect(=> @xhr.addOauthParams()).to.throw Error
-
- describe '#addOauthHeader', ->
- beforeEach ->
- @xhr.addOauthHeader @oauth
-
- it 'keeps existing params', ->
- expect(@xhr.params).to.have.property 'answer'
- expect(@xhr.params.answer).to.equal 42
-
- it 'does not add an oauth_signature param', ->
- expect(@xhr.params).not.to.have.property 'oauth_signature'
-
- it 'adds an Authorization header', ->
- expect(@xhr.headers).to.have.property 'Authorization'
-
- describe '#addOauthParams without params', ->
- beforeEach ->
- @xhr.addOauthParams @oauth
-
- it 'adds an oauth_signature param', ->
- expect(@xhr.params).to.have.property 'oauth_signature'
-
- describe '#addOauthHeader without params', ->
- beforeEach ->
- @xhr.addOauthHeader @oauth
-
- it 'adds an Authorization header', ->
- expect(@xhr.headers).to.have.property 'Authorization'
-
- describe '#signWithOauth', ->
- describe 'for a request that does not need preflight', ->
- beforeEach ->
- @xhr.signWithOauth @oauth
-
- if Dropbox.Xhr.doesPreflight
- it 'uses addOauthParams', ->
- expect(@xhr.params).to.have.property 'oauth_signature'
- else
- it 'uses addOauthHeader in node.js', ->
- expect(@xhr.headers).to.have.property 'Authorization'
-
- describe 'for a request that needs preflight', ->
- beforeEach ->
- @xhr.setHeader 'Range', 'bytes=0-1000'
- @xhr.signWithOauth @oauth
-
- if Dropbox.Xhr.ieXdr # IE's XDR doesn't do HTTP headers.
- it 'uses addOauthParams in IE', ->
- expect(@xhr.params).to.have.property 'oauth_signature'
- else
- it 'uses addOauthHeader', ->
- expect(@xhr.headers).to.have.property 'Authorization'
-
- describe 'with cacheFriendly: true', ->
- describe 'for a request that does not need preflight', ->
- beforeEach ->
- @xhr.signWithOauth @oauth, true
-
- if Dropbox.Xhr.ieXdr
- it 'uses addOauthParams in IE', ->
- expect(@xhr.params).to.have.property 'oauth_signature'
- else
- it 'uses addOauthHeader', ->
- expect(@xhr.headers).to.have.property 'Authorization'
-
- describe 'for a request that needs preflight', ->
- beforeEach ->
- @xhr.setHeader 'Range', 'bytes=0-1000'
- @xhr.signWithOauth @oauth, true
-
- if Dropbox.Xhr.ieXdr # IE's XDR doesn't do HTTP headers.
- it 'uses addOauthParams in IE', ->
- expect(@xhr.params).to.have.property 'oauth_signature'
- else
- it 'uses addOauthHeader', ->
- expect(@xhr.headers).to.have.property 'Authorization'
-
- describe '#setFileField', ->
- it 'throws an error', ->
- expect(=> @xhr.setFileField('file', 'filename.bin', 'File Data
',
- 'text/html')).to.throw Error
-
- describe '#setBody', ->
- it 'throws an error', ->
- expect(=> @xhr.setBody('body data')).to.throw Error
-
- it 'does not flag the XHR as needing preflight', ->
- expect(@xhr.preflight).to.equal false
-
- describe '#setResponseType', ->
- beforeEach ->
- @xhr.setResponseType 'b'
-
- it 'changes responseType', ->
- expect(@xhr.responseType).to.equal 'b'
-
- it 'does not flag the XHR as needing preflight', ->
- expect(@xhr.preflight).to.equal false
-
- describe '#prepare with params', ->
- beforeEach ->
- @xhr.setParams answer: 42
- @xhr.prepare()
-
- it 'creates the native xhr', ->
- expect(typeof @xhr.xhr).to.equal 'object'
-
- it 'opens the native xhr', ->
- return if Dropbox.Xhr.ieXdr # IE's XDR doesn't do readyState.
- expect(@xhr.xhr.readyState).to.equal 1
-
- it 'pushes the params in the url', ->
- expect(@xhr.url).to.equal 'https://request.url?answer=42'
-
- describe 'with a POST', ->
- beforeEach ->
- @xhr = new Dropbox.Xhr 'POST', 'https://request.url'
-
- it 'initializes correctly', ->
- expect(@xhr.isGet).to.equal false
- expect(@xhr.method).to.equal 'POST'
- expect(@xhr.url).to.equal 'https://request.url'
- expect(@xhr.preflight).to.equal false
-
- describe '#setHeader', ->
- beforeEach ->
- @xhr.setHeader 'Range', 'bytes=0-1000'
-
- it 'adds a HTTP header header', ->
- expect(@xhr.headers).to.have.property 'Range'
- expect(@xhr.headers['Range']).to.equal 'bytes=0-1000'
-
- it 'does not work twice for the same header', ->
- expect(=> @xhr.setHeader('Range', 'bytes=0-1000')).to.throw Error
-
- it 'flags the Xhr as needing preflight', ->
- expect(@xhr.preflight).to.equal true
-
- it 'rejects Content-Type', ->
- expect(=> @xhr.setHeader('Content-Type', 'text/plain')).to.throw Error
-
- describe '#setParams', ->
- beforeEach ->
- @xhr.setParams 'param 1': true, 'answer': 42
-
- it 'does not work twice', ->
- expect(=> @xhr.setParams 'answer': 43).to.throw Error
-
- it 'does not flag the XHR as needing preflight', ->
- expect(@xhr.preflight).to.equal false
-
- describe '#paramsToUrl', ->
- beforeEach ->
- @xhr.paramsToUrl()
-
- it 'changes the url', ->
- expect(@xhr.url).to.
- equal 'https://request.url?answer=42¶m%201=true'
-
- it 'sets params to null', ->
- expect(@xhr.params).to.equal null
-
- it 'does not set the body', ->
- expect(@xhr.body).to.equal null
-
- describe '#paramsToBody', ->
- beforeEach ->
- @xhr.paramsToBody()
-
- it 'url-encodes the params', ->
- expect(@xhr.body).to.equal 'answer=42¶m%201=true'
-
- it 'sets the Content-Type header', ->
- expect(@xhr.headers).to.have.property 'Content-Type'
- expect(@xhr.headers['Content-Type']).to.
- equal 'application/x-www-form-urlencoded'
-
- it 'does not change the url', ->
- expect(@xhr.url).to.equal 'https://request.url'
-
- it 'does not work twice', ->
- @xhr.setParams answer: 43
- expect(=> @xhr.paramsToBody()).to.throw Error
-
- describe '#addOauthParams', ->
- beforeEach ->
- @xhr.addOauthParams @oauth
-
- it 'keeps existing params', ->
- expect(@xhr.params).to.have.property 'answer'
- expect(@xhr.params.answer).to.equal 42
-
- it 'adds an oauth_signature param', ->
- expect(@xhr.params).to.have.property 'oauth_signature'
-
- it 'does not add an Authorization header', ->
- expect(@xhr.headers).not.to.have.property 'Authorization'
-
- it 'does not work twice', ->
- expect(=> @xhr.addOauthParams()).to.throw Error
-
- describe '#addOauthHeader', ->
- beforeEach ->
- @xhr.addOauthHeader @oauth
-
- it 'keeps existing params', ->
- expect(@xhr.params).to.have.property 'answer'
- expect(@xhr.params.answer).to.equal 42
-
- it 'does not add an oauth_signature param', ->
- expect(@xhr.params).not.to.have.property 'oauth_signature'
-
- it 'adds an Authorization header', ->
- expect(@xhr.headers).to.have.property 'Authorization'
-
- describe '#addOauthParams without params', ->
- beforeEach ->
- @xhr.addOauthParams @oauth
-
- it 'adds an oauth_signature param', ->
- expect(@xhr.params).to.have.property 'oauth_signature'
-
- describe '#addOauthHeader without params', ->
- beforeEach ->
- @xhr.addOauthHeader @oauth
-
- it 'adds an Authorization header', ->
- expect(@xhr.headers).to.have.property 'Authorization'
-
- describe '#signWithOauth', ->
- describe 'for a request that does not need preflight', ->
- beforeEach ->
- @xhr.signWithOauth @oauth
-
- if Dropbox.Xhr.doesPreflight
- it 'uses addOauthParams', ->
- expect(@xhr.params).to.have.property 'oauth_signature'
- else
- it 'uses addOauthHeader in node.js', ->
- expect(@xhr.headers).to.have.property 'Authorization'
-
- describe 'for a request that needs preflight', ->
- beforeEach ->
- @xhr.setHeader 'Range', 'bytes=0-1000'
- @xhr.signWithOauth @oauth
-
- if Dropbox.Xhr.ieXdr # IE's XDR doesn't do HTTP headers.
- it 'uses addOauthParams in IE', ->
- expect(@xhr.params).to.have.property 'oauth_signature'
- else
- it 'uses addOauthHeader', ->
- expect(@xhr.headers).to.have.property 'Authorization'
-
- describe 'with cacheFriendly: true', ->
- describe 'for a request that does not need preflight', ->
- beforeEach ->
- @xhr.signWithOauth @oauth, true
-
- if Dropbox.Xhr.doesPreflight
- it 'uses addOauthParams', ->
- expect(@xhr.params).to.have.property 'oauth_signature'
- else
- it 'uses addOauthHeader in node.js', ->
- expect(@xhr.headers).to.have.property 'Authorization'
-
- describe 'for a request that needs preflight', ->
- beforeEach ->
- @xhr.setHeader 'Range', 'bytes=0-1000'
- @xhr.signWithOauth @oauth, true
-
- if Dropbox.Xhr.ieXdr # IE's XDR doesn't do HTTP headers.
- it 'uses addOauthParams in IE', ->
- expect(@xhr.params).to.have.property 'oauth_signature'
- else
- it 'uses addOauthHeader', ->
- expect(@xhr.headers).to.have.property 'Authorization'
-
- describe '#setFileField with a String', ->
- beforeEach ->
- @nonceStub = sinon.stub @xhr, 'multipartBoundary'
- @nonceStub.returns 'multipart----boundary'
- @xhr.setFileField 'file', 'filename.bin', 'File Data
',
- 'text/html'
-
- afterEach ->
- @nonceStub.restore()
-
- it 'sets the Content-Type header', ->
- expect(@xhr.headers).to.have.property 'Content-Type'
- expect(@xhr.headers['Content-Type']).to.
- equal 'multipart/form-data; boundary=multipart----boundary'
-
- it 'sets the body', ->
- expect(@xhr.body).to.equal("""--multipart----boundary\r
-Content-Disposition: form-data; name="file"; filename="filename.bin"\r
-Content-Type: text/html\r
-Content-Transfer-Encoding: binary\r
-\r
-File Data
\r
---multipart----boundary--\r\n
-""")
-
- it 'does not work twice', ->
- expect(=> @xhr.setFileField('file', 'filename.bin', 'File Data
',
- 'text/html')).to.throw Error
-
- it 'does not flag the XHR as needing preflight', ->
- expect(@xhr.preflight).to.equal false
-
- describe '#setBody with a string', ->
- beforeEach ->
- @xhr.setBody 'body data'
-
- it 'sets the request body', ->
- expect(@xhr.body).to.equal 'body data'
-
- it 'does not work twice', ->
- expect(=> @xhr.setBody('body data')).to.throw Error
-
- it 'does not flag the XHR as needing preflight', ->
- expect(@xhr.preflight).to.equal false
-
- describe '#setBody with FormData', ->
- beforeEach ->
- if FormData?
- formData = new FormData()
- formData.append 'name', 'value'
- @xhr.setBody formData
-
- it 'does not flag the XHR as needing preflight', ->
- return unless FormData?
- expect(@xhr.preflight).to.equal false
-
- describe '#setBody with Blob', ->
- beforeEach ->
- if Blob?
- blob = new Blob ["abcdef"], type: 'image/png'
- @xhr.setBody blob
-
- it 'flags the XHR as needing preflight', ->
- return unless Blob?
- expect(@xhr.preflight).to.equal true
-
- it 'sets the Content-Type header', ->
- return unless Blob?
- expect(@xhr.headers).to.have.property 'Content-Type'
- expect(@xhr.headers['Content-Type']).to.
- equal 'application/octet-stream'
-
- describe '#setBody with ArrayBuffer', ->
- beforeEach ->
- if ArrayBuffer?
- buffer = new ArrayBuffer 5
- @xhr.setBody buffer
-
- it 'flags the XHR as needing preflight', ->
- return unless ArrayBuffer?
- expect(@xhr.preflight).to.equal true
-
- it 'sets the Content-Type header', ->
- return unless ArrayBuffer?
- expect(@xhr.headers).to.have.property 'Content-Type'
- expect(@xhr.headers['Content-Type']).to.
- equal 'application/octet-stream'
-
- describe '#setBody with ArrayBufferView', ->
- beforeEach ->
- if Uint8Array?
- view = new Uint8Array 5
- @xhr.setBody view
-
- it 'flags the XHR as needing preflight', ->
- return unless Uint8Array?
- expect(@xhr.preflight).to.equal true
-
- it 'sets the Content-Type header', ->
- return unless Uint8Array?
- expect(@xhr.headers).to.have.property 'Content-Type'
- expect(@xhr.headers['Content-Type']).to.
- equal 'application/octet-stream'
-
- describe '#setResponseType', ->
- beforeEach ->
- @xhr.setResponseType 'b'
-
- it 'changes responseType', ->
- expect(@xhr.responseType).to.equal 'b'
-
- it 'does not flag the XHR as needing preflight', ->
- expect(@xhr.preflight).to.equal false
-
- describe '#prepare with params', ->
- beforeEach ->
- @xhr.setParams answer: 42
- @xhr.prepare()
-
- it 'creates the native xhr', ->
- expect(typeof @xhr.xhr).to.equal 'object'
-
- it 'opens the native xhr', ->
- return if Dropbox.Xhr.ieXdr # IE's XDR doesn't do readyState.
- expect(@xhr.xhr.readyState).to.equal 1
-
- if Dropbox.Xhr.ieXdr
- it 'keeps the params in the URL in IE', ->
- expect(@xhr.url).to.equal 'https://request.url?answer=42'
- expect(@xhr.body).to.equal null
- else
- it 'pushes the params in the body', ->
- expect(@xhr.body).to.equal 'answer=42'
-
- describe 'with a PUT', ->
- beforeEach ->
- @xhr = new Dropbox.Xhr 'PUT', 'https://request.url'
-
- it 'initializes correctly', ->
- expect(@xhr.isGet).to.equal false
- expect(@xhr.method).to.equal 'PUT'
- expect(@xhr.url).to.equal 'https://request.url'
- expect(@xhr.preflight).to.equal true
-
- describe '#send', ->
- it 'reports errors correctly', (done) ->
- @url = 'https://api.dropbox.com/1/oauth/request_token'
- @xhr = new Dropbox.Xhr 'POST', @url
- @xhr.prepare().send (error, data) =>
- expect(data).to.equal undefined
- expect(error).to.be.instanceOf Dropbox.ApiError
- expect(error).to.have.property 'url'
- expect(error.url).to.equal @url
- expect(error).to.have.property 'method'
- expect(error.method).to.equal 'POST'
- unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do HTTP status codes.
- expect(error).to.have.property 'status'
- expect(error.status).to.equal 401 # Bad OAuth request.
- expect(error).to.have.property 'responseText'
- expect(error.responseText).to.be.a 'string'
- unless Dropbox.Xhr.ieXdr # IE's XDR hides the HTTP body on error.
- expect(error).to.have.property 'response'
- expect(error.response).to.be.an 'object'
- expect(error.toString()).to.match /^Dropbox API error/
- expect(error.toString()).to.contain 'POST'
- expect(error.toString()).to.contain @url
- done()
-
- it 'reports errors correctly when onError is set', (done) ->
- @url = 'https://api.dropbox.com/1/oauth/request_token'
- @xhr = new Dropbox.Xhr 'POST', @url
- @xhr.onError = new Dropbox.EventSource
- listenerError = null
- @xhr.onError.addListener (error) -> listenerError = error
- @xhr.prepare().send (error, data) =>
- expect(data).to.equal undefined
- expect(error).to.be.instanceOf Dropbox.ApiError
- expect(error).to.have.property 'url'
- expect(error.url).to.equal @url
- expect(error).to.have.property 'method'
- expect(error.method).to.equal 'POST'
- expect(listenerError).to.equal error
- done()
-
- it 'processes data correctly', (done) ->
- xhr = new Dropbox.Xhr 'POST',
- 'https://api.dropbox.com/1/oauth/request_token',
- xhr.addOauthParams @oauth
- xhr.prepare().send (error, data) ->
- expect(error).to.not.be.ok
- expect(data).to.have.property 'oauth_token'
- expect(data).to.have.property 'oauth_token_secret'
- done()
-
- it 'processes data correctly when using setCallback', (done) ->
- xhr = new Dropbox.Xhr 'POST',
- 'https://api.dropbox.com/1/oauth/request_token',
- xhr.addOauthParams @oauth
- xhr.setCallback (error, data) ->
- expect(error).to.not.be.ok
- expect(data).to.have.property 'oauth_token'
- expect(data).to.have.property 'oauth_token_secret'
- done()
- xhr.prepare().send()
-
- it 'sends Authorize headers correctly', (done) ->
- return done() if Dropbox.Xhr.ieXdr # IE's XDR doesn't set headers.
-
- xhr = new Dropbox.Xhr 'POST',
- 'https://api.dropbox.com/1/oauth/request_token',
- xhr.addOauthHeader @oauth
- xhr.prepare().send (error, data) ->
- expect(error).to.equal null
- expect(data).to.have.property 'oauth_token'
- expect(data).to.have.property 'oauth_token_secret'
- done()
-
- describe 'with a binary response', ->
- beforeEach ->
- testImageServerOn()
- @xhr = new Dropbox.Xhr 'GET', testImageUrl
-
- afterEach ->
- testImageServerOff()
-
- describe 'with responseType b', ->
- beforeEach ->
- @xhr.setResponseType 'b'
-
- it 'retrieves a string where each character is a byte', (done) ->
- @xhr.prepare().send (error, data) ->
- expect(error).to.not.be.ok
- expect(data).to.be.a 'string'
- expect(data).to.equal testImageBytes
- done()
-
- describe 'with responseType arraybuffer', ->
- beforeEach ->
- @xhr.setResponseType 'arraybuffer'
-
- it 'retrieves a well-formed ArrayBuffer', (done) ->
- # Skip this test on node.js and IE 9 and below
- return done() unless ArrayBuffer?
-
- @xhr.prepare().send (error, buffer) ->
- expect(error).to.not.be.ok
- expect(buffer).to.be.instanceOf ArrayBuffer
- view = new Uint8Array buffer
- length = buffer.byteLength
- bytes = (String.fromCharCode view[i] for i in [0...length]).
- join('')
- expect(bytes).to.equal testImageBytes
- done()
-
- describe 'with responseType blob', ->
- beforeEach ->
- @xhr.setResponseType 'blob'
-
- it 'retrieves a well-formed Blob', (done) ->
- # Skip this test on node.js and IE 9 and below
- return done() unless Blob?
-
- @xhr.prepare().send (error, blob) ->
- expect(error).to.not.be.ok
- expect(blob).to.be.instanceOf Blob
- reader = new FileReader
- reader.onloadend = ->
- return unless reader.readyState == FileReader.DONE
- buffer = reader.result
- view = new Uint8Array buffer
- length = buffer.byteLength
- bytes = (String.fromCharCode view[i] for i in [0...length]).
- join('')
- expect(bytes).to.equal testImageBytes
- done()
- reader.readAsArrayBuffer blob
-
- describe '#urlEncode', ->
- it 'iterates properly', ->
- expect(Dropbox.Xhr.urlEncode({foo: 'bar', baz: 5})).to.
- equal 'baz=5&foo=bar'
- it 'percent-encodes properly', ->
- expect(Dropbox.Xhr.urlEncode({'a +x()': "*b'"})).to.
- equal 'a%20%2Bx%28%29=%2Ab%27'
-
- describe '#urlDecode', ->
- it 'iterates properly', ->
- decoded = Dropbox.Xhr.urlDecode('baz=5&foo=bar')
- expect(decoded['baz']).to.equal '5'
- expect(decoded['foo']).to.equal 'bar'
- it 'percent-decodes properly', ->
- decoded = Dropbox.Xhr.urlDecode('a%20%2Bx%28%29=%2Ab%27')
- expect(decoded['a +x()']).to.equal "*b'"
-
diff --git a/lib/client/terminal.js b/lib/client/terminal.js
index 4033e510..341a6448 100644
--- a/lib/client/terminal.js
+++ b/lib/client/terminal.js
@@ -18,7 +18,7 @@ var CloudCommander, Util, DOM, $;
* function loads jquery-terminal
*/
function load(pCallBack){
- console.time('terminal load');
+ Util.time('terminal load');
var lDir = '/lib/client/terminal/jquery-terminal/jquery.',
lFiles = [
@@ -30,8 +30,8 @@ var CloudCommander, Util, DOM, $;
/* //github.com/jquery/jquery-migrate/ */
DOM.anyLoadOnLoad([lFiles, lJqueryMigrate], function(){
- console.timeEnd('terminal load');
- init();
+ Util.timeEnd('terminal load');
+ init();
$(function($, undefined) {
Term = JqueryTerminal.Term = $('#terminal').terminal(function(command, term){
term.echo('');
diff --git a/lib/client/viewer.js b/lib/client/viewer.js
index 0e4a4b91..071859f2 100644
--- a/lib/client/viewer.js
+++ b/lib/client/viewer.js
@@ -1,8 +1,8 @@
-var CloudCommander, Util, DOM, $;
+var CloudCommander, Util, DOM, CloudFunc, $;
/* object contains viewer FancyBox
* https://github.com/fancyapps/fancyBox
*/
-(function(CloudCmd, Util, DOM){
+(function(CloudCmd, Util, DOM, CloudFunc){
'use strict';
var KeyBinding = CloudCmd.KeyBinding,
@@ -37,9 +37,9 @@ var CloudCommander, Util, DOM, $;
};
CloudCmd.Viewer = {
- get: (function(){
+ get: function(){
return this.FancyBox;
- })
+ }
};
/**
@@ -48,13 +48,13 @@ var CloudCommander, Util, DOM, $;
* @pCallBack - executes, when everything loaded
*/
FancyBox.load = function(pCallBack){
- console.time('fancybox load');
+ Util.time('fancybox load');
var lDir = CloudCmd.LIBDIRCLIENT + 'viewer/fancyBox/source/',
lFiles = [ lDir + 'jquery.fancybox.css',
lDir + 'jquery.fancybox.js' ];
DOM.anyLoadOnLoad([lFiles], function(){
- console.timeEnd('fancybox load');
+ Util.timeEnd('fancybox load');
Util.exec( pCallBack );
})
.cssSet({id:'viewer',
@@ -102,7 +102,7 @@ var CloudCommander, Util, DOM, $;
* function shows FancyBox
*/
FancyBox.show = function(pCallBack){
- var lPath = DOM.getCurrentPath();
+ var lPath = CloudFunc.FS + DOM.getCurrentPath();
if( Util.checkExtension(lPath, ['png','jpg', 'gif','ico']) )
$.fancybox.open({ href : lPath }, Config);
@@ -137,20 +137,26 @@ var CloudCommander, Util, DOM, $;
/* если клавиши можно обрабатывать */
if( lKeyBinded){
- if(lKeyCode === lF3 && lShift){
- lView();
- pEvent.preventDefault();
+ switch(lKeyCode){
+ case lF3:
+ if(lShift){
+ lView();
+ DOM.preventDefault(pEvent);
+ }
+ break;
+
+ case lKEY.F1:
+ FancyBox.showHelp();
+ break;
}
- else if(lKeyCode === lKEY.F1)
- FancyBox.showHelp();
}
};
/* добавляем обработчик клавишь */
- DOM.addKeyListener(lKeyListener)
+ DOM .addKeyListener(lKeyListener)
.setButtonKey('f3', lView);
};
CloudCmd.Viewer.FancyBox = FancyBox;
-})(CloudCommander, Util, DOM);
\ No newline at end of file
+})(CloudCommander, Util, DOM, CloudFunc);
\ No newline at end of file
diff --git a/lib/cloudfunc.js b/lib/cloudfunc.js
index 915523f2..52d5bda5 100644
--- a/lib/cloudfunc.js
+++ b/lib/cloudfunc.js
@@ -1,42 +1,60 @@
-var CloudFunc, exports;
+var Util, exports, CloudFunc = {};
-(function(){
+(function(Util, CloudFunc, exports){
'use strict';
/**
* Модуль, содержащий функции, которые
* будут работать и на клиенте и на сервере
*/
-
- CloudFunc = exports || {};
+ var FS;
+ if(exports){
+ if(!global.cloudcmd)
+ return console.log(
+ '# cloudfunc.js' + '\n' +
+ '# -----------' + '\n' +
+ '# Module is part of Cloud Commander,' + '\n' +
+ '# used for generate html from json.' + '\n' +
+ '# ' + '\n' +
+ '# http://coderaiser.github.com/cloudcmd' + '\n');
+
+ Util = global.cloudcmd.main.util;
+ CloudFunc = exports;
+ }
+
/* Путь с которым мы сейчас работаем */
- CloudFunc.Path = '';
+ CloudFunc.Path = '';
/* КОНСТАНТЫ (общие для клиента и сервера)*/
/* название программы */
- CloudFunc.NAME = 'Cloud Commander';
+ CloudFunc.NAME = 'Cloud Commander';
/* если в ссылке будет эта строка - в браузере js отключен */
- CloudFunc.FS = '/fs';
+ CloudFunc.FS = FS = '/fs';
/* название css-класа кнопки обновления файловой структуры*/
- CloudFunc.REFRESHICON = 'refresh-icon';
+ CloudFunc.REFRESHICON = 'refresh-icon';
/* id панелей с файлами */
- CloudFunc.LEFTPANEL = 'left';
- CloudFunc.RIGHTPANEL = 'right';
+ CloudFunc.LEFTPANEL = 'left';
+ CloudFunc.RIGHTPANEL = 'right';
/**
* Функция убирает последний слеш,
* если он - последний символ строки
*/
CloudFunc.removeLastSlash = function(pPath){
- if(typeof pPath==='string')
- return (pPath.lastIndexOf('/') === pPath.length-1) ?
- pPath.substr(pPath, pPath.length-1):pPath;
- else return pPath;
+ var lRet = pPath,
+ lIsStr = typeof pPath==='string',
+ lLengh = pPath.length-1,
+ lLastSlash = pPath.lastIndexOf('/');
+
+ if(lIsStr && lLastSlash === lLengh)
+ lRet = pPath.substr(pPath, lLengh);
+
+ return lRet;
};
/** Функция возвращает заголовок веб страницы
@@ -54,7 +72,7 @@ var CloudFunc, exports;
* @param pPerm_s - строка с правами доступа
* к файлу в 8-миричной системе
*/
- CloudFunc.convertPermissionsToSymbolic = function(pPerm_s){
+ CloudFunc.getSymbolicPermissions = function(pPerm_s){
/*
S_IRUSR 0000400 protection: readable by owner
S_IWUSR 0000200 writable by owner
@@ -86,7 +104,7 @@ var CloudFunc, exports;
}
/* оставляем последние 3 символа*/
- pPerm_s = pPerm_s.length> 5 ?pPerm_s.substr(3) : pPerm_s.substr(2);
+ pPerm_s = pPerm_s.length > 5 ? pPerm_s.substr(3) : pPerm_s.substr(2);
/* Рекомендации гугла советуют вместо string[3]
* использовать string.charAt(3)
@@ -102,28 +120,24 @@ var CloudFunc, exports;
of using an application-specific shorthand).
*/
/* Переводим в двоичную систему */
- var lOwner = (pPerm_s[0]-0).toString(2),
- lGroup = (pPerm_s[1]-0).toString(2),
- lAll = (pPerm_s[2]-0).toString(2),
- /*
- console.log(lOwner+' '+lGroup+' '+lAll);
- */
+ var lOwner = ( pPerm_s[0] - 0 ).toString(2),
+ lGroup = ( pPerm_s[1] - 0 ).toString(2),
+ lAll = ( pPerm_s[2] - 0 ).toString(2),
+
/* переводим в символьную систему*/
- lPermissions = //lType+' '+
- (lOwner[0]-0>0?'r':'-') +
- (lOwner[1]-0>0?'w':'-') +
- (lOwner[2]-0>0?'x':'-') +
- ' ' +
- (lGroup[0]-0>0?'r':'-') +
- (lGroup[1]-0>0?'w':'-') +
- (lGroup[2]-0>0?'x':'-') +
- ' ' +
- (lAll[0]-0>0?'r':'-') +
- (lAll[1]-0>0?'w':'-') +
- (lAll[2]-0>0?'x':'-');
- /*
- console.log(lPermissions);
- */
+ lPermissions =
+ ( lOwner[0] - 0 > 0 ? 'r' : '-' ) +
+ ( lOwner[1] - 0 > 0 ? 'w' : '-' ) +
+ ( lOwner[2] - 0 > 0 ? 'x' : '-' ) +
+ ' ' +
+ ( lGroup[0] - 0 > 0 ? 'r' : '-' ) +
+ ( lGroup[1] - 0 > 0 ? 'w' : '-' ) +
+ ( lGroup[2] - 0 > 0 ? 'x' : '-' ) +
+ ' ' +
+ ( lAll[0]- 0 > 0 ? 'r' : '-' ) +
+ ( lAll[1]- 0 > 0 ? 'w' : '-' ) +
+ ( lAll[2]- 0 > 0 ? 'x' : '-' );
+
return lPermissions;
};
@@ -131,10 +145,7 @@ var CloudFunc, exports;
* Функция конвертирует права доступа к файлам из символьного вида
* в цыфровой
*/
- CloudFunc.convertPermissionsToNumberic = function(pPerm_s){
- /* если передана правильная строка, конвертированная
- * функциец convertPermissionsToSymbolic
- */
+ CloudFunc.getNumericPermissions = function(pPerm_s){
if(!pPerm_s || pPerm_s.length!==11)return pPerm_s;
var lOwner= (pPerm_s[0] === 'r' ? 4 : 0) +
@@ -152,33 +163,30 @@ var CloudFunc, exports;
/* добавляем 2 цыфры до 5 */
return '00' + lOwner + lGroup + lAll;
};
+
/** Функция получает короткие размеры
* конвертируя байт в килобайты, мегабойты,
* гигайбайты и терабайты
* @pSize - размер в байтах
*/
- CloudFunc.getShortedSize = function(pSize){
- /* if pSize=0 - return it */
- if (pSize !== pSize-0) return pSize;
+ CloudFunc.getShortSize = function(pSize){
+ if (pSize === pSize-0){
+ /* Константы размеров, что используются внутри функции */
+ var l1KB = 1024,
+ l1MB = l1KB * l1KB,
+ l1GB = l1MB * l1KB,
+ l1TB = l1GB * l1KB,
+ l1PB = l1TB * l1KB;
+
+ if (pSize < l1KB) pSize = pSize + 'b';
+ else if (pSize < l1MB) pSize = (pSize/l1KB).toFixed(2) + 'kb';
+ else if (pSize < l1GB) pSize = (pSize/l1MB).toFixed(2) + 'mb';
+ else if (pSize < l1TB) pSize = (pSize/l1GB).toFixed(2) + 'gb';
+ else if (pSize < l1PB) pSize = (pSize/l1TB).toFixed(2) + 'tb';
+ else pSize = (pSize/l1PB).toFixed(2) + 'pb';
+ }
- /* Константы размеров, что используются
- * внутри функции
- */
- var l1BMAX = 1024;
- var l1KBMAX = 1048576;
- var l1MBMAX = 1073741824;
- var l1GBMAX = 1099511627776;
- var l1TBMAX = 1125899906842624;
-
- var lShorted;
-
- if (pSize < l1BMAX) lShorted = pSize + 'b';
- else if (pSize < l1KBMAX) lShorted = (pSize/l1BMAX) .toFixed(2) + 'kb';
- else if (pSize < l1MBMAX) lShorted = (pSize/l1KBMAX).toFixed(2) + 'mb';
- else if (pSize < l1GBMAX) lShorted = (pSize/l1MBMAX).toFixed(2) + 'gb';
- else if (pSize < l1TBMAX) lShorted = (pSize/l1GBMAX).toFixed(2) + 'tb';
-
- return lShorted;
+ return pSize;
};
/** Функция парсит uid и имена пользователей
@@ -197,11 +205,11 @@ var CloudFunc, exports;
if(lLine){
/* удаляем первую строку из /etc/passwd*/
- pPasswd_s = pPasswd_s.replace(lLine, '');
+ pPasswd_s = Util.removeStr(pPasswd_s, lLine);
/* получаем первое слово строки */
var lName = lLine.substr(lLine,lLine.indexOf(':'));
- lLine = lLine.replace(lName+':x:','');
+ lLine = Util.removeStr(lLine, lName + ':x:');
/* получаем uid*/
var lUID = lLine.substr(lLine,lLine.indexOf(':'));
@@ -222,7 +230,8 @@ var CloudFunc, exports;
* @param url - адрес каталога
*/
CloudFunc._getDirPath = function(url){
- var folders = [],
+ var lShortName,
+ folders = [],
i = 0;
do{
folders[i++] = url;
@@ -235,30 +244,25 @@ var CloudFunc, exports;
_l = '">',
lHrefEnd ='',
- lHtmlPath,
+ /* корневой каталог */
+ lHtmlPath = lHref + FS + lTitle +
+ '/' + _l + '/' +
+ lHrefEnd;
+
+ for(i = folders.length - 1; i > 0; i--){
+ var lUrl = folders[i],
+ lSlashIndex = lUrl.lastIndexOf('/') + 1;
- lFS_s = CloudFunc.FS;
- /* корневой каталог */
- lHtmlPath = lHref +
- lFS_s +
- lTitle +
- '/' +
- _l +
- '/' +
- lHrefEnd;
-
- for(i = folders.length - 1; i > 0; i--)
- {
- var lUrl=folders[i],
- lShortName = lUrl.replace(lUrl.substr(lUrl,lUrl.lastIndexOf('/')+1),'');
- if (i!==1)
- lHtmlPath += lHref + lFS_s + lUrl +
- lTitle + lUrl + _l +
- lShortName + lHrefEnd + '/';
+ lShortName = Util.removeStr(lUrl, lUrl.substr(lUrl, lSlashIndex) );
+
+ if(i !== 1)
+ lHtmlPath += lHref + FS + lUrl +
+ lTitle + lUrl + _l +
+ lShortName + lHrefEnd + '/';
else
- lHtmlPath+=lShortName+'/';
+ lHtmlPath += lShortName + '/';
}
- /* *** */
+
return lHtmlPath;
};
@@ -289,7 +293,7 @@ var CloudFunc, exports;
* [{path:'путь',size:'dir'},
* {name:'имя',size:'размер',mode:'права доступа'}]
*/
- CloudFunc.buildFromJSON = function(pJSON, pSetCurrent)
+ CloudFunc.buildFromJSON = function(pJSON, pTemplate, pPathTemplate)
{
var files = pJSON,
/* сохраняем путь каталога в котором мы сейчас находимся*/
@@ -306,21 +310,11 @@ var CloudFunc, exports;
* если он есть
*/
lRefreshPath = CloudFunc.removeLastSlash(lPath),
- lFS_s = CloudFunc.FS,
- lFileTable =
- ''+
- '' +
- ' ' +
- '' +
- '' +
- ' ' +
- ' ' +
- '' + lHtmlPath + ' ' +
- ' ',
+ lFileTable = Util.render(pPathTemplate, {
+ link: FS + lRefreshPath,
+ path: lHtmlPath
+ }),
fileTableTitles = ['name','size','owner','mode'];
@@ -340,80 +334,34 @@ var CloudFunc, exports;
if(lDotDot === '')
lDotDot = '/';
- lLink = lFS_s + lDotDot;
-
+ lLink = FS + lDotDot;
/* Сохраняем путь к каталогу верхнего уровня*/
- lFileTable += '' +
- ' ' +
- '' +
- '' + ".. " +
- ' ' +
- '<dir> ' +
- '. ' +
- ' ' +
- ' ';
+ lFileTable += Util.render(pTemplate,{
+ type : 'directory',
+ link : lLink,
+ target : '',
+ name : '..',
+ size : '<dir>',
+ owner : '.',
+ mode : ''
+ });
}
for(var i = 1, n = files.length; i < n; i++){
- lFileTable += '';
- lFileTable += '';
- lFileTable += ' ';
- lFileTable += '' +
- '' + files[i].name +
- " " +
- ' ';
- /* если папка - не выводим размер */
- lFileTable += '' +
- (files[i].size === 'dir' ?
- '<dir>'
- /* если это файл - получаем
- * короткий размер
- */
- : CloudFunc.getShortedSize(
- files[i].size));
- lFileTable += ' ' +
- '' +
- (!files[i].uid ? 'root' : files[i].uid) +
- ' ' +
- '' +
- /* конвертируем названия разрешений
- * из числового формата в буквенный
- * при этом корневой каталог не трогаем
- * по скольку в нём и так всё уже
- * установлено еще на сервере
- */
- (//lPath==='/'?files[i].mode:
- CloudFunc
- .convertPermissionsToSymbolic
- (files[i].mode)) +
- ' ';
- lFileTable += ' ';
+ lFileTable += Util.render(pTemplate,{
+ type : lFile.size === 'dir' ? 'directory' : 'text-file',
+ link : FS + lPath + lFile.name,
+ target : lFile.size === 'dir' ? '' : "_blank",
+ name : lFile.name,
+ size : lFile.size === 'dir' ? '<dir>' : CloudFunc.getShortSize( lFile.size ),
+ owner : !lFile.uid ? 'root' : lFile.uid,
+ mode : CloudFunc.getSymbolicPermissions(lFile.mode)
+ });
}
- /* если клавиши назначены и
- * мы в корневом каталоге и
- * верхний файл еще не выделен -
- * выделяем верхний файл
- */
- if(pSetCurrent)
- lFileTable = lFileTable.replace('',
- ' ');
-
return lFileTable;
};
-})();
\ No newline at end of file
+})(Util, CloudFunc, exports);
\ No newline at end of file
diff --git a/lib/server.js b/lib/server.js
index 313f31c6..37c09ef8 100644
--- a/lib/server.js
+++ b/lib/server.js
@@ -15,7 +15,7 @@
LIBDIR = main.LIBDIR,
SRVDIR = main.SRVDIR,
- /* модуль для работы с путями */
+ URL = main.url,
Path = main.path,
Querystring = main.querystring,
@@ -24,9 +24,10 @@
Socket = main.socket,
http = main.http,
+ https = main.https,
Util = main.util,
- Server, Rest, Route, Minimize, Port, IP;
+ Server, Rest, Route, Minimize;
/* базовая инициализация */
function init(pAppCachProcessing){
@@ -58,39 +59,79 @@
if(!pProcessing)
pProcessing = {};
- Rest = pProcessing.rest;
- Route = pProcessing.route;
- Minimize = pProcessing.minimize;
+ Rest = pProcessing.rest;
+ Route = pProcessing.route;
+ Minimize = pProcessing.minimize;
init(pProcessing.appcache);
- Port = process.env.PORT || /* c9 */
- process.env.app_port || /* nodester */
- process.env.VCAP_APP_PORT || /* cloudfoundry */
- lConfig.port;
-
- IP = process.env.IP || /* c9 */
- lConfig.ip ||
- (main.WIN32 ? '127.0.0.1' : '0.0.0.0');
+ var lPort = process.env.PORT || /* c9 */
+ 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'),
+
+ lSSL = pProcessing.ssl,
+ lSSLPort = lConfig.sslPort,
+ lHTTP = 'http://',
+ lHTTPS = 'https://',
+
+ lSockets = function(pServer){
+ var lListen;
+ if(lConfig.socket && Socket)
+ lListen = Socket.listen(pServer);
+
+ Util.log('* Sockets ' + (lListen ? 'running' : 'disabled'));
+ },
+
+ lHTTPServer = function(){
+ Server = http.createServer( controller );
+ Server.on('error', function (pError) {
+ Util.log(pError);
+ });
+ Server.listen(lPort, lIP);
+ lServerLog(lHTTP, lPort);
+ lSockets(Server);
+ },
+
+ lServerLog = function(pHTTP, pPort){
+ Util.log('* Server running at ' + pHTTP + lIP + ':' + pPort);
+ };
/* server mode or testing mode */
if (lConfig.server) {
- var lError = Util.tryCatchLog(function(){
- Server = http.createServer( controller );
- Server.listen(Port, IP);
+ if(lSSL){
+ Util.log('* Redirection http -> https is setted up');
+ lServerLog(lHTTP, lPort);
+ var lRedirectServer = http.createServer( function(pReq, pRes){
+ var lHost = pReq.headers.host;
- var lListen;
- if(lConfig.socket && Socket)
- lListen = Socket.listen(Server);
-
- Util.log('* Sockets ' + (lListen ? 'running' : 'disabled'));
- Util.log('* Server running at http://' + IP + ':' + Port);
- });
-
- if(lError){
- Util.log('Cloud Commander server could not started');
- Util.log(lError);
+ main.redirect({
+ response: pRes,
+ url: lHTTPS + lHost + pReq.url
+ });
+ });
+
+ lRedirectServer.listen(lPort, lIP);
+
+ Server = https.createServer( lSSL, controller );
+ Server.on('error', function (pError) {
+ Util.log('Could not use https port: ' + lSSLPort);
+ Util.log(pError);
+ lRedirectServer.close();
+ Util.log('* Redirection http -> https removed');
+ lHTTPServer();
+ });
+
+ lSockets(Server);
+
+ Server.listen(lSSLPort, lIP);
+ lServerLog(lHTTPS, lSSLPort);
}
+ else
+ lHTTPServer();
}else
Util.log('Cloud Commander testing mode');
}
@@ -107,8 +148,7 @@
/* Читаем содержимое папки, переданное в url */
var lRet,
lConfig = main.config,
- lURL = main.url,
- lParsedUrl = lURL.parse(pReq.url),
+ lParsedUrl = URL.parse(pReq.url),
lPath = lParsedUrl.pathname;
/* added supporting of Russian language in directory names */
@@ -117,23 +157,21 @@
Util.log("request for " + lPath + " received...");
+ var lData = {
+ name : lPath,
+ request : pReq,
+ response : pRes
+ };
+
if( lConfig.rest )
- lRet = Util.exec(Rest, {
- name : lPath,
- request : pReq,
- response : pRes
- });
+ lRet = Util.exec(Rest, lData);
if( !lRet && Route)
- lRet = Util.exec(Route, {
- name : lPath,
- request : pReq,
- response : pRes
- });
+ lRet = Util.exec(Route, lData);
if(!lRet){
/* добавляем текующий каталог к пути */
- var lName = '.' + lPath;
+ var lName = '.' + lData.name;
Util.log('reading ' + lName);
/* watching is file changed */
@@ -154,13 +192,13 @@
main.sendFile({
name : lSendName,
+ cache : lConfig.cache,
+ gzip : true,
request : pReq,
response : pRes
});
}, function(pCallBack){
Minify.optimize(lName, {
- request : pReq,
- response : pRes,
callback : pCallBack,
returnName : true
});
diff --git a/lib/server/cache.js b/lib/server/cache.js
deleted file mode 100644
index f2c2cf2a..00000000
--- a/lib/server/cache.js
+++ /dev/null
@@ -1,61 +0,0 @@
-(function(){
- "use strict";
-
- var main = global.cloudcmd.main,
- SRVDIR = main.SRVDIR;
-
- /*
- * Обьект для работы с кэшем
- * аналог клиентского обьекта
- * с тем отличием, что в нём
- * будут храниться серверные
- * данные, такие как файлы
- * отдаваемые клиенту
- * (файлы проэкта по большому
- * счёту, для ускорения
- * первичной загрузки)
- */
- exports.Cache = {
- /* приватный переключатель возможности работы с кэшем */
- _allowed : true,
- /* данные в которых храняться файлы
- * в формате <поле> : <значение>
- * _data[name]=pData;
- * одному имени соответствуют
- * одни данные
- */
- _data : {},
-
- /* функция говорит можно ли работать с кэшем */
- isAllowed : (function(){
- return this._allowed;
- }),
- /* функция устанавливает возможность работать с кэшем */
- setAllowed : function(pAllowed){
- this._allowed = pAllowed;
- },
- /* Если доступен кэш
- * сохраняем в него данные
- */
- set : function(pName, pData){
- if(this._allowed && pName && pData){
- this._data[pName]=pData;
- }
- },
- /* Если доступен Cache принимаем из него данные*/
- get : function(pName){
- var lRet;
- if(this._allowed && pName)
- lRet = this._data[pName];
-
- return lRet;
- },
-
- /* Функция очищает кэш*/
- clear :(function(){
- if(this._allowed){
- this._data={};
- }
- })
- };
-})();
diff --git a/lib/server/commander.js b/lib/server/commander.js
index 784b0008..ab88d557 100644
--- a/lib/server/commander.js
+++ b/lib/server/commander.js
@@ -93,12 +93,11 @@
var p = pParams,
c = p.params;
- if(c.stats)
- c.stats[c.name] = !p.error ? p.data : {
- 'mode' : 0,
- 'size' : 0,
- 'isDirectory' : Util.retFalse
- };
+ c.stats[c.name] = !p.error ? p.data : {
+ 'mode' : 0,
+ 'size' : 0,
+ 'isDirectory' : Util.retFalse
+ };
if(c.count === Object.keys(c.stats).length)
Util.exec(c.callback);
@@ -154,8 +153,6 @@
lJSON[i+1] = lJSONFile;
}
- lDirPath = lDirPath.substr(lDirPath, lDirPath.lastIndexOf('/') );
-
Util.exec(p.callback, null, lJSON);
}
diff --git a/lib/server/dir.js b/lib/server/dir.js
new file mode 100644
index 00000000..761aee67
--- /dev/null
+++ b/lib/server/dir.js
@@ -0,0 +1,104 @@
+/* inspired by http://procbits.com/2011/10/29/a-node-js-experiment-thinking-asynchronously-recursion-calculate-file-size-directory */
+(function(){
+ 'use strict';
+
+ if(!global.cloudcmd)
+ return console.log(
+ '# dir.js' + '\n' +
+ '# -----------' + '\n' +
+ '# Module is part of Cloud Commander,' + '\n' +
+ '# used for getting dir size.' + '\n' +
+ '# If you wont to see at work' + '\n' +
+ '# try GET /api/v1/fs/etc?size or' + '\n' +
+ '# dir.getSize(\'/etc, function(err, size){' + '\n' +
+ '# });' + '\n' +
+ '# http://coderaiser.github.com/cloudcmd' + '\n');
+
+ var main = global.cloudcmd.main,
+ fs = main.fs,
+ Util = main.util,
+ path = main.path;
+
+ exports.getSize = function(pDir, pCallBack) {
+ var lTotal = 0;
+
+ function calcSize(pParams){
+ var lStat = pParams.stat,
+ lSize = lStat && lStat.size || 0;
+
+ lTotal += lSize;
+ }
+
+ processDir(pDir, calcSize, function(){
+ Util.log(pDir + ' -> ' + lTotal);
+ Util.exec(pCallBack, null, lTotal);
+ });
+ };
+
+ function processDir(pDir, pFunc, pCallBack){
+ var lAsyncRunning = 0,
+ lFileCounter = 1;
+
+ function getDirInfo(pDir) {
+ /* The lstat() function shall be equivalent to stat(),
+ except when path refers to a symbolic link. In that case lstat()
+ shall return information about the link, while stat() shall return
+ information about the file the link references. */
+
+ fs.lstat(pDir, Util.call(getStat, {
+ name: pDir
+ }));
+ }
+
+ function getStat(pParams) {
+ var lRet = Util.checkObj(pParams, ['params']);
+ if(lRet){
+ var p = pParams,
+ d = p.params,
+ lStat = p.data,
+ lPath = d.name;
+
+ --lFileCounter;
+
+ if (!p.error) {
+ if ( lStat.isFile() )
+ Util.exec(pFunc, {
+ name: d.name,
+ stat: lStat
+ });
+ else if ( lStat.isDirectory() ) {
+ ++lAsyncRunning;
+
+ fs.readdir(lPath, function(pError, pFiles) {
+ lAsyncRunning--;
+
+ var lDirPath, n;
+
+ if (!pError){
+ n = pFiles.length;
+ lFileCounter += n;
+
+ for (var i = 0; i < n; i++) {
+ lDirPath = path.join(lPath, pFiles[i]);
+ process.nextTick( Util.retExec(getDirInfo, lDirPath) );
+ }
+ }
+
+ if(!n)
+ execCallBack();
+ });
+ }
+ }
+ }
+
+ execCallBack();
+ }
+
+ function execCallBack(){
+ if (!lFileCounter && !lAsyncRunning)
+ Util.exec(pCallBack);
+ }
+
+ getDirInfo(pDir);
+ }
+})();
\ No newline at end of file
diff --git a/lib/server/main.js b/lib/server/main.js
index 246ae04d..79c0cceb 100644
--- a/lib/server/main.js
+++ b/lib/server/main.js
@@ -12,7 +12,8 @@
ext,
path, fs, zlib, url,
- OK, FILE_NOT_FOUND,
+ OK, FILE_NOT_FOUND, MOVED_PERMANENTLY = 301,
+ REQUEST, RESPONSE,
Config = {
server : true,
@@ -22,10 +23,11 @@
/* Consts */
- exports.OK = OK = 200;
- exports.FILE_NOT_FOUND = FILE_NOT_FOUND = 404;
- exports.REQUEST = 'request';
- exports.RESPONSE = 'response';
+ exports.OK = OK = 200;
+ exports.FILE_NOT_FOUND = FILE_NOT_FOUND = 404;
+
+ exports.REQUEST = REQUEST = 'request';
+ exports.RESPONSE = RESPONSE = 'response';
/* Native Modules*/
exports.crypto = require('crypto'),
@@ -40,7 +42,7 @@
/* Constants */
/* current dir + 2 levels up */
exports.WIN32 = ISWIN32 = isWin32();
- exports.SLASH = SLASH = ISWIN32 ? '\\' : '/',
+ exports.SLASH = SLASH = '/',
exports.SRVDIR = SRVDIR = __dirname + SLASH,
exports.LIBDIR = LIBDIR = path.normalize(SRVDIR + '../'),
@@ -53,7 +55,7 @@
exports.librequire = librequire,
exports.srvrequire = srvrequire,
exports.rootrequire = rootrequire,
- exports.quietrequire = quietrequire,
+ exports.quietrequire = quietrequire,
exports.generateHeaders = generateHeaders,
exports.getQuery = getQuery,
@@ -62,6 +64,8 @@
exports.sendFile = sendFile,
exports.sendResponse = sendResponse,
exports.sendError = sendError,
+ exports.redirect = redirect,
+ exports.readFiles = readFiles,
exports.checkParams = checkParams,
@@ -69,6 +73,8 @@
exports.fs.exists = exports.fs.exists || exports.path.exists,
/* Needed Modules */
+
+ /* we can not use librequare heare */
exports.util = Util = require(LIBDIR + 'util'),
exports.zlib = zlib = mrequire('zlib'),
@@ -95,18 +101,18 @@
exports.socket = srvrequire('socket'),
exports.auth = srvrequire('auth').auth,
exports.appcache = srvrequire('appcache'),
- exports.cache = srvrequire('cache').Cache,
exports.cloudfunc = librequire('cloudfunc'),
+ exports.dir = srvrequire('dir'),
exports.rest = srvrequire('rest').api,
exports.update = srvrequire('update'),
exports.ischanged = srvrequire('ischanged');
exports.commander = srvrequire('commander');
exports.minify = srvrequire('minify').Minify;
- /*
- * second initializing after all modules load, so global var is
- * totally filled of all information that should know all modules
- */
+
+ /* second initializing after all modules load, so global var is *
+ * totally filled of all information that should know all modules */
global.cloudcmd.main = exports;
+
/**
* function do safe require of needed module
* @param {Strin} pSrc
@@ -172,11 +178,11 @@
* https://developers.google.com/speed/docs/best-practices/caching?hl=ru#LeverageProxyCaching
*/
function generateHeaders(pParams){
- var lRet = Util.checkObjTrue(pParams, ['name']),
- p = pParams;
+ var lRet = Util.checkObjTrue(pParams, ['name']);
if(lRet){
- var lExt = Util.getExtension(p.name),
+ var p = pParams,
+ lExt = Util.getExtension(p.name),
lType = ext[lExt] || 'text/plain',
lContentEncoding = '';
@@ -194,10 +200,8 @@
'Vary': 'Accept-Encoding'
};
- if( !Util.strCmp(lExt, '.appcache') && exports.config.cache){
- var lCacheControl = 31337 * 21;
- lRet['cache-control'] = 'max-age=' + lCacheControl;
- }
+ if( !Util.strCmp(lExt, '.appcache') && p.cache)
+ lRet['cache-control'] = 'max-age=' + 31337 * 21;
if(p.gzip)
lRet['content-encoding'] = 'gzip';
@@ -214,37 +218,37 @@
* @param pGzip - данные сжаты gzip'ом
*/
function sendFile(pParams){
- var lRet,
- lName, lReq, lRes, lGziped;
+ var lRet = checkParams(pParams);
- if(pParams){
- lName = pParams.name,
- lReq = pParams.request,
- lRes = pParams.response;
- lGziped = pParams.gziped;
- }
- if(lName && lRes && lReq){
- var lGzip = isGZIP(lReq),
+ if(lRet){
+ var p = pParams,
+ lGzip = isGZIP(p.request) && p.gzip,
- lReadStream = fs.createReadStream(lName, {
+ lReadStream = fs.createReadStream(p.name, {
'bufferSize': 4 * 1024
});
lReadStream.on('error', function(pError){
- lRes.writeHead(FILE_NOT_FOUND, 'OK');
- lRes.end(String(pError));
+ p.response.writeHead(FILE_NOT_FOUND, 'OK');
+ p.response.end(String(pError));
});
- lRes.writeHead(OK, generateHeaders({
- name : lName,
+ p.response.writeHead(OK, generateHeaders({
+ name : p.name,
+ cache : p.cache,
gzip : lGzip,
- query : getQuery(lReq)
+ query : getQuery(p.request)
}) );
- if (lGzip && !lGziped)
- lReadStream = lReadStream.pipe( zlib.createGzip() );
+ var lZipStream;
- lReadStream.pipe(lRes);
+ if (lGzip && !p.gziped)
+ lZipStream = lReadStream.pipe( zlib.createGzip() );
+ else
+ lZipStream = lReadStream;
+
+
+ lZipStream.pipe(p.response);
lRet = true;
}
@@ -260,8 +264,7 @@
* @param pName - имя отсылаемого файла
*/
function sendResponse(pParams, pData){
- var lRet = Util.checkObjTrue(pParams,
- ['name', 'request', 'response']);
+ var lRet = checkParams(pParams);
if(lRet){
var p = pParams;
@@ -271,6 +274,7 @@
lGzip = isGZIP(p.request),
lHead = generateHeaders({
name : p.name,
+ cache : p.cache,
gzip : lGzip,
query : lQuery
});
@@ -299,9 +303,28 @@
}
}
- function sendError(pParams, pError){
+
+ /**
+ * redirect to another URL
+ */
+ function redirect(pParams){
var lRet = Util.checkObjTrue(pParams,
- ['name', 'request', 'response']);
+ [RESPONSE]);
+
+ if(lRet){
+ var p = pParams;
+
+ p.response.writeHead(MOVED_PERMANENTLY, {'Location': p.url});
+ p.response.end();
+ }
+ }
+
+
+ /**
+ * send error response
+ */
+ function sendError(pParams, pError){
+ var lRet = checkParams(pParams);
if(lRet){
var p = pParams;
@@ -317,14 +340,14 @@
* @pName
*/
function gzipData(pParams){
- var lRet = checkCallBackParams(pParams);
+ var lRet = checkCallBackParams(pParams),
+ p = pParams;
if(lRet)
lRet = Util.checkObj(pParams.params, ['callback']);
if(lRet){
- var p = pParams,
- c = pParams.params,
+ var lCallBack = p.params.callback,
lParams = {};
if(!p.error)
@@ -334,7 +357,7 @@
lParams.data = p.error.toString();
}
- Util.exec(c.callback, lParams);
+ Util.exec(lCallBack, lParams);
}
}
@@ -343,8 +366,49 @@
return Util.checkObj(pParams, ['error', 'data', 'params']);
}
+ function readFiles(pFiles, pCallBack){
+ var lDone = [],
+ lFiles,
+ lErrors,
+ lReadedFiles = {},
+ lDoneFunc = function (pParams){
+ var lRet = Util.checkObj(pParams, ['error', 'data', 'params']);
+
+ if(lRet){
+ lDone.pop();
+ var p = pParams,
+ lName = p.params;
+
+ if(p.error){
+ if(!lErrors) lErrors = {};
+
+ lErrors[lName] = p.error;
+ }
+ else{
+ Util.log(lName + ' readed');
+ lReadedFiles[lName] = p.data;
+ }
+
+ if( !lDone.length )
+ Util.exec(pCallBack, lErrors, lReadedFiles);
+ }
+ };
+
+ if( Util.isArray(pFiles) )
+ lFiles = pFiles;
+ else
+ lFiles = [pFiles];
+
+ for(var i = 0, n = lFiles.length; i < n; i++){
+ var lName = lFiles.pop();
+ lDone.push(lName);
+
+ fs.readFile(lName, Util.call( lDoneFunc, lName ));
+ }
+ }
+
function checkParams(pParams, pAdditional){
- var lRet = Util.checkObjTrue( pParams, ['name', 'request', 'response'] );
+ var lRet = Util.checkObjTrue( pParams, ['name', REQUEST, RESPONSE] );
if(lRet && pAdditional)
lRet = Util.checkObjTrue( pParams, pAdditional);
diff --git a/lib/server/minify.js b/lib/server/minify.js
index d1c1f2ed..4f8245d8 100644
--- a/lib/server/minify.js
+++ b/lib/server/minify.js
@@ -36,9 +36,6 @@
img : true
},
- /* minimize even if file not changed */
- forse : false,
-
/* функция разрешает или
* запрещает минимизировать
* css/js/html
@@ -49,13 +46,13 @@
* img отвечает за перевод картинок в base64
* и сохранение их в css-файл
*/
- setAllowed :(function(pAllowed){
+ setAllowed :function(pAllowed){
this.allowed = pAllowed && Minify ? pAllowed : {
js : false,
css : false,
html : false
};
- }),
+ },
optimize: function(pName, pParams){
var lRet;
@@ -74,7 +71,7 @@
if(pChanged)
Minify.optimize(pName, pParams);
else
- main.sendFile(pParams);
+ Util.exec(pParams.callback, pParams);
});
}
else{
diff --git a/lib/server/rest.js b/lib/server/rest.js
index e49add33..bc3f9332 100644
--- a/lib/server/rest.js
+++ b/lib/server/rest.js
@@ -17,6 +17,7 @@
fs = main.fs,
Util = main.util,
CloudFunc = main.cloudfunc,
+ dir = main.dir,
OK = 200,
Header = main.generateHeaders({
name:'api.json'
@@ -34,14 +35,13 @@
lRet = Util.isContainStr(p.name, lAPIURL);
if( lRet ){
- p.name = Util.removeStr(p.name, lAPIURL);
+ p.name = Util.removeStrOneTime(p.name, lAPIURL);
sendData( pParams);
}
}
return lRet;
};
-
/**
* send data
*
@@ -66,12 +66,12 @@
if(lRet){
var p = pParams;
- lRet = Util.isContainStr(p.name, CloudFunc.FS);
+ lRet = Util.isContainStrAtBegin(p.name, CloudFunc.FS);
if( lRet)
onFS(pParams);
else{
if(p.name[0] === '/')
- p.command = Util.removeStr(p.name, '/');
+ p.command = Util.removeStrOneTime(p.name, '/');
switch(p.request.method){
case 'GET':
@@ -96,29 +96,39 @@
var p = pParams,
lQuery = main.getQuery(p.request);
- p.name = Util.removeStrOneTime(p.name, [CloudFunc.FS, '?dir']) || '/';
+ p.name = Util.removeStrOneTime(p.name, CloudFunc.FS) || '/';
switch(p.request.method){
case 'GET':
- fs.stat(p.name, function(pError, pStat){
- if(!pError)
- if( pStat.isDirectory() )
- main.commander.getDirContent(pParams.name, function(pError, pData){
- if(!pError){
- pParams.request.url += '.json';
- pParams.data = Util.stringifyJSON(pData);
- main.sendResponse(pParams);
- }
- else
- main.sendError(pParams, pError);
- });
+ if( Util.strCmp(lQuery, 'size') )
+ dir.getSize(p.name, function(pErr, pSize){
+ if(!pErr){
+ var lSize = CloudFunc.getShortSize(pSize);
+ console.log(lSize);
+ main.sendResponse(p, lSize);
+ }
else
- main.sendFile(pParams);
- else
- main.sendError(pParams, pError);
+ main.sendError(p, pErr);
+ });
+ else
+ fs.stat(p.name, function(pError, pStat){
+ if(!pError)
+ if( pStat.isDirectory() )
+ main.commander.getDirContent(p.name, function(pError, pData){
+ if(!pError){
+ p.name += '.json';
+ p.data = Util.stringifyJSON(pData);
+ main.sendResponse(p);
+ }
+ else
+ main.sendError(p, pError);
+ });
+ else
+ main.sendFile(p);
+ else
+ main.sendError(p, pError);
- });
-
- break;
+ });
+ break;
case 'PUT':
if(lQuery === 'dir')
@@ -129,14 +139,13 @@
main.sendError(pParams, pError);
});
else{
- var lWriteStream = fs.createWriteStream(p.name);
+ var lWriteStream = fs.createWriteStream(p.name);
lWriteStream.on('error', function(pError){
- console.log(pError);
main.sendError(pParams, pError);
});
- p.request.on('end', function(){
+ lWriteStream.on('open', function(){
main.sendResponse(pParams, 'writed: ' + p.name);
});
@@ -147,12 +156,55 @@
case 'DELETE':
if(lQuery === 'dir')
fs.rmdir(p.name, function(pError){
- if(!pError)
- main.sendResponse(pParams, 'Folder ' + p.name + ' deleted.');
- else
- main.sendError(pParams, pError);
+ if(!pError)
+ main.sendResponse(pParams, 'Folder ' + p.name + ' deleted.');
+ else
+ main.sendError(pParams, pError);
+ });
+ 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),
+ lAssync = 0;
+
+ function stat(pStat){
+ var lRet = Util.checkObjTrue(pStat, 'params') &&
+ Util.checkObjTrue(pStat.params, 'name');
+
+ if(lRet){
+ var p = pStat,
+ d = p.params;
+
+ ++lAssync;
+
+ if( p.error ){
+ main.sendError(pParams, p.error);
+ Util.log(p.error);
+ }
+ else
+ if(p.data.isDirectory())
+ fs.rmdir(d.name, log);
+
+ else if(p.data.isFile())
+ fs.unlink(d.name, log);
+
+ if(lAssync === n && !p.error)
+ main.sendResponse(pParams, 'Files deleted: ' + pBody);
+ }
+ }
+
+
+ for(var i = 0; i < n; i ++){
+ var lName = lDir + lFiles[i];
+ Util.log(lName);
+ fs.stat(lName, Util.call(stat, {
+ name: lName
+ }));
+ }
});
- else
+ }else
fs.unlink(p.name, function(pError){
if(!pError)
main.sendResponse(pParams, 'File ' + p.name + ' delete.');
@@ -184,6 +236,14 @@
};
send(p);
break;
+
+ case 'proxy':
+
+ break;
+
+ case 'zip':
+ main.sendFile(pParams);
+ break;
case 'kill':
p.data = {
@@ -234,6 +294,7 @@
main.sendError(pParams, lError);
});
break;
+
case 'mv':
if( Util.checkObjTrue(lFiles, ['from', 'to']) )
fs.rename(lFiles.from, lFiles.to, function(pError){
@@ -243,27 +304,30 @@
main.sendError(pParams, pError);
});
else
- main.sendError(pParams, p.data);
+ main.sendError(pParams, p.data);
break;
case 'cp':
- if(lFiles){
- var lReadStream = fs.createReadStream(lFiles.from),
- lWriteStream = fs.createWriteStream(lFiles.to),
+ if( Util.checkObjTrue(lFiles, ['from', 'to']) ){
+ var l = lFiles,
+ lReadStream = fs.createReadStream(l.from),
+ lWriteStream = fs.createWriteStream(l.to),
+
lError = function(pError){
main.sendError(pParams, pError);
};
-
lWriteStream.on('error', lError);
lReadStream.on('error', lError);
- lWriteStream.on('end', function(){
- main.sendResponse(pParams, 'copied: ' + p.name);
+ lReadStream.on('end', function(){
+ main.sendResponse(pParams, 'copied to: ' + l.to);
});
lReadStream.pipe(lWriteStream);
}
+ else
+ main.sendError(pParams, p.data);
break;
default:
send(pParams);
diff --git a/lib/server/socket.js b/lib/server/socket.js
index f064a044..0a63de2a 100644
--- a/lib/server/socket.js
+++ b/lib/server/socket.js
@@ -22,16 +22,15 @@
exports.listen = function(pServer){
var lRet;
if(io){
- io = io.listen(pServer);
+ var lListen = io.listen(pServer),
+ /* number of connections */
+ lConnNum = 0;
- /* number of connections */
- var lConnNum = 0;
-
- lRet = io.sockets.on('connection', function (socket){
+ lRet = lListen.sockets.on('connection', function (socket){
++lConnNum;
socket.send('{"stdout":"client connected"}');
- console.log('server connected');
+ Util.log('server connected');
if(!OnMessageFuncs[lConnNum])
OnMessageFuncs[lConnNum] = onMessage(lConnNum, socket);
@@ -54,7 +53,7 @@
*/
function onMessage(pConnNum, pSocket){
return function(pCommand) {
- console.log(pCommand);
+ Util.log(pCommand);
if( Util.isContainStr(pCommand, 'cloudcmd') ){
pCommand = Util.removeStr(pCommand, 'cloudcmd');
@@ -80,10 +79,8 @@
lMsg = JSON.stringify(lMsg);
pSocket.send(lMsg);
- console.log('received from client: ' + pCommand);
- console.log('sended to client: ' + lMsg);
-
- return;
+ Util.log('received from client: ' + pCommand);
+ Util.log('sended to client: ' + lMsg);
}
}
@@ -114,7 +111,7 @@
function getExec(pSocket){
return function(pError, pStdout, pStderr) {
if (pError !== null) {
- console.log('exec error: ' + pError);
+ Util.log('exec error: ' + pError);
}
var lExec = {
diff --git a/lib/util.js b/lib/util.js
index cafe5cf9..66e7a8b5 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -7,7 +7,7 @@ Util = exports || {};
(function(Util){
'use strict';
-
+
var Scope = exports ? global : window;
/** setting function context
@@ -15,7 +15,7 @@ Util = exports || {};
* @param {object} pContext
*/
Util.bind = function(pFunction, pContext){
- var lRet = false;
+ var lRet;
if( Util.isFunction(pFunction) )
lRet = pFunction.bind(pContext);
@@ -23,16 +23,6 @@ Util = exports || {};
return lRet;
};
- Util.breakpoint = function(){
- var lRet = Util.tryCatch(function(){
- debugger;
- });
-
- Util.log(lRet);
-
- return lRet;
- };
-
/**
* callback for functions(pError, pData)
* thet moves on our parameters.
@@ -41,13 +31,13 @@ Util = exports || {};
* @param pParams
*/
Util.call = function(pFunc, pParams){
- var lFunc = function(pError, pData){
+ function lFunc(pError, pData){
Util.exec(pFunc, {
error : pError,
data : pData,
params : pParams
});
- };
+ }
return lFunc;
};
@@ -61,9 +51,8 @@ Util = exports || {};
Util.checkExtension = function(pName, pExt){
var lRet = false,
lLength = pName.length; /* длина имени*/
- /* если длина имени больше
- * длинны расширения -
- * имеет смысл продолжать
+
+ /* если длина имени больше длинны расширения - имеет смысл продолжать
*/
if (Util.isString(pExt) && pName.length > pExt.length) {
var lExtNum = pName.lastIndexOf(pExt), /* последнее вхождение расширения*/
@@ -117,7 +106,7 @@ Util = exports || {};
return lRet;
};
- /**
+ /**
* Check is Properties exists and they are true
*
* @param pObj
@@ -125,21 +114,20 @@ Util = exports || {};
* @param pTrueArr
*/
Util.checkObjTrue = function(pObj, pTrueArr){
- var lRet,
+ var lRet, lTrueArr,
i, n;
if( pObj ){
- lRet = Util.isArray(pTrueArr);
- if(lRet){
- n = pTrueArr.length;
- for(i = 0; i < n; i++){
- var lProp = pTrueArr[i];
- lRet = pObj[lProp];
-
- if( !lRet){
- Util.logError(lProp + ' not true!');
- Util.log(pObj);
- break;
- }
+ lTrueArr = Util.isArray(pTrueArr) ? pTrueArr : [pTrueArr];
+
+ n = lTrueArr.length;
+ for(i = 0; i < n; i++){
+ var lProp = lTrueArr[i];
+ lRet = pObj[lProp];
+
+ if( !lRet){
+ Util.logError(lProp + ' not true!');
+ Util.log(pObj);
+ break;
}
}
}
@@ -147,6 +135,39 @@ Util = exports || {};
return lRet;
};
+ /**
+ * Copy properties array pProps from pFromObj to pToObj
+ *
+ * @param pFromObj
+ * @param pToObj
+ * @param pProps
+ */
+ Util.copyObj = function(pFromObj, pToObj, pProps){
+ var lRet;
+
+ if( !pToObj )
+ lRet = pToObj = {};
+
+ function copy(pI){
+ var lName = pProps ? pProps[pI] : pI,
+ lValue = pFromObj[lName];
+
+ if(lValue)
+ pToObj[lName] = pFromObj[lName];
+ }
+
+ if( Util.isObject(pFromObj) ){
+ if(!pProps)
+ Util.forIn(pFromObj, copy);
+ else
+ Util.fori(pProps.length, copy);
+
+ lRet = lRet || true;
+ }
+
+ return lRet;
+ };
+
/** for function
* @param pI
* @param pN
@@ -160,6 +181,17 @@ Util = exports || {};
}
};
+ /** for in function
+ * @param pObj
+ * @param pFunc
+ */
+ Util.forIn = function(pObj, pFunc){
+ if(Util.isFunction(pFunc))
+ for(var lName in pObj)
+ if(pFunc(lName))
+ break;
+ };
+
/** for function with i = 0
* @param pN
* @param pFunc
@@ -176,7 +208,7 @@ Util = exports || {};
Util.parseJSON = function(pJSON){
var lRet;
- Util.tryCatchLog(function(){
+ Util.tryCatch(function(){
lRet = JSON.parse(pJSON);
});
@@ -247,6 +279,24 @@ Util = exports || {};
return lRet;
};
+ /**
+ * is pStr1 contains pStr2 at begin
+ * @param pStr1
+ * @param pStr2
+ */
+ Util.isContainStrAtBegin = function(pStr1, pStr2){
+ var lRet;
+
+ if( Util.isString(pStr1) && Util.isString(pStr2) ){
+ var lLength = pStr2.length,
+ lSubStr = pStr1.substring(0, lLength);
+
+ lRet = lSubStr === pStr2;
+ }
+
+ return lRet;
+ };
+
/**
* function log pArg if it's not empty
* @param pArg
@@ -485,6 +535,14 @@ Util = exports || {};
return Util.isType(pVarible, 'function');
};
+ /**
+ * functions check is pVarible is number
+ * @param pVarible
+ */
+ Util.isNumber = function(pVarible){
+ return Util.isType(pVarible, 'number');
+ };
+
/**
* functions check is pVarible is object
* @param pVarible
@@ -707,8 +765,11 @@ Util = exports || {};
*/
Util.execIfExist = function(pObj, pName, pArg){
var lRet;
- if(pObj)
- lRet = Util.exec(pObj[pName], pArg);
+
+ if(pObj){
+ var lFunc = Util.bind(pObj[pName], pObj);
+ lRet = Util.exec(lFunc, pArg);
+ }
return lRet;
};
@@ -814,6 +875,7 @@ Util = exports || {};
return lRet;
};
+
/**
* stop timer
* @pArg
@@ -824,8 +886,9 @@ Util = exports || {};
lRet = Util.execIfExist(lConsole, 'timeEnd', pArg);
- return this;
+ return lRet;
};
+
/**
* Gets current date in format yy.mm.dd hh:mm:ss
*/
diff --git a/manifest.yml b/manifest.yml
new file mode 100644
index 00000000..5353529e
--- /dev/null
+++ b/manifest.yml
@@ -0,0 +1,13 @@
+---
+applications:
+ .:
+ name: cloudcmd
+ framework:
+ name: node
+ info:
+ mem: 512M
+ description: Node.js Application
+ exec:
+ url: ${name}.${target-base}
+ mem: 128M
+ instances: 2
diff --git a/package.json b/package.json
index 284725e8..31355ad9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cloudcmd",
- "version": "0.1.9",
+ "version": "0.2.0",
"author": "coderaiser (https://github.com/coderaiser)",
"description": "User friendly cloud file manager.",
"homepage": "https://github.com/coderaiser/cloudcmd",
@@ -9,18 +9,19 @@
"url": "git://github.com/coderaiser/cloudcmd.git"
},
"scripts": {
- "test": "sh test/test.sh",
+ "test": "sh ./test/test.sh",
"start": "cloudcmd.js"
},
"node": "0.6.17",
"subdomain": "cloudcmd",
"dependencies": {
- "minify": "0.1.9",
- "socket.io": "0.9.13"
+ "dropbox": "0.9.2",
+ "minify": "0.2.0",
+ "socket.io": "0.9.14"
},
"devDependencies": {},
"engines": {
"node": ">=0.4.x"
},
"main": "cloudcmd.js"
-}
\ No newline at end of file
+}
diff --git a/shell/deploy.sh b/shell/deploy.sh
index 316dbf69..d91f5825 100755
--- a/shell/deploy.sh
+++ b/shell/deploy.sh
@@ -1,12 +1,11 @@
-cd ..
+echo 'jitsu'
+cp package.json tmp/package.json
+echo 'y'|jitsu deploy
+echo '://cloudcmd.jit.su'
+cp tmp/package.json package.json
echo 'appfog'
af update
-echo 'http://cloudcmd.aws.af.cm/'
+echo '://cloudcmd.aws.af.cm'
echo 'cloud foundry'
-vmc update
-echo 'http://cloudcmd.cloudfoundry.com/'
-echo 'nodester'
-git push nodester master
-echo 'heroku'
-git push heroku master
-cd shell
\ No newline at end of file
+vmc push
+echo '://cloudcmd.cloudfoundry.com'
\ No newline at end of file
diff --git a/shell/ssl.sh b/shell/ssl.sh
new file mode 100644
index 00000000..e703ad7d
--- /dev/null
+++ b/shell/ssl.sh
@@ -0,0 +1,3 @@
+openssl genrsa -out privatekey.pem 1024
+openssl req -new -key privatekey.pem -out certrequest.csr
+openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem
\ No newline at end of file
diff --git a/ssl/ssl.crt b/ssl/ssl.crt
new file mode 100644
index 00000000..a0c89725
--- /dev/null
+++ b/ssl/ssl.crt
@@ -0,0 +1,37 @@
+-----BEGIN CERTIFICATE-----
+MIIGbTCCBVWgAwIBAgIDCW2NMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
+TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
+YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
+MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTMwMzA3MDYzMDAz
+WhcNMTQwMzA3MTQxMDM1WjB0MRkwFwYDVQQNExAwN005bXA1NnloSllmV0NIMQsw
+CQYDVQQGEwJVQTEeMBwGA1UEAxMVc3NsLnJhc3RhY29kaW5nLnJ2LnVhMSowKAYJ
+KoZIhvcNAQkBFht3ZWJtYXN0ZXJAcmFzdGFjb2RpbmcucnYudWEwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDL+GkzmHlBF/5zNwY1KRRw9lZFUd8ON7d7
+KeA8GTyB1OlZiWsOFGrYGuCAbnBElM6kDqRWjIgqjna/81eapZq7lTNXmJN7l9g1
+digOPJHHs1oVJvztMZ1kHc75I1t4cOYNeq0l4m3UbvazFpEN90B4Uh1vKSfzLXN8
+3EF0SQFcmA90e5G/D3ZTJZ7em7t/tbrlAdZfF7Nsc5Rq7pNG+WxLsjbt1eA5lM9x
+GMNcMLqo+O74WZYyLQarKhRDESqaQL0UxdFg9I2SmU73YyYqRmRv6SKkCWWaNvyB
+7gi+2ocvXHI3UD9jOxH2vf3YchOkzmn3byMogAUVMTt8eM+rhI2vAgMBAAGjggLt
+MIIC6TAJBgNVHRMEAjAAMAsGA1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcD
+ATAdBgNVHQ4EFgQUina5BS9zmNpc7s8zf9+I7kV/eaEwHwYDVR0jBBgwFoAU60I0
+0Jiwq5/0G2sI98xkLu8OLEUwMwYDVR0RBCwwKoIVc3NsLnJhc3RhY29kaW5nLnJ2
+LnVhghFyYXN0YWNvZGluZy5ydi51YTCCAVYGA1UdIASCAU0wggFJMAgGBmeBDAEC
+ATCCATsGCysGAQQBgbU3AQIDMIIBKjAuBggrBgEFBQcCARYiaHR0cDovL3d3dy5z
+dGFydHNzbC5jb20vcG9saWN5LnBkZjCB9wYIKwYBBQUHAgIwgeowJxYgU3RhcnRD
+b20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwAwIBARqBvlRoaXMgY2VydGlmaWNh
+dGUgd2FzIGlzc3VlZCBhY2NvcmRpbmcgdG8gdGhlIENsYXNzIDEgVmFsaWRhdGlv
+biByZXF1aXJlbWVudHMgb2YgdGhlIFN0YXJ0Q29tIENBIHBvbGljeSwgcmVsaWFu
+Y2Ugb25seSBmb3IgdGhlIGludGVuZGVkIHB1cnBvc2UgaW4gY29tcGxpYW5jZSBv
+ZiB0aGUgcmVseWluZyBwYXJ0eSBvYmxpZ2F0aW9ucy4wNQYDVR0fBC4wLDAqoCig
+JoYkaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0MS1jcmwuY3JsMIGOBggrBgEF
+BQcBAQSBgTB/MDkGCCsGAQUFBzABhi1odHRwOi8vb2NzcC5zdGFydHNzbC5jb20v
+c3ViL2NsYXNzMS9zZXJ2ZXIvY2EwQgYIKwYBBQUHMAKGNmh0dHA6Ly9haWEuc3Rh
+cnRzc2wuY29tL2NlcnRzL3N1Yi5jbGFzczEuc2VydmVyLmNhLmNydDAjBgNVHRIE
+HDAahhhodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS8wDQYJKoZIhvcNAQEFBQADggEB
+AHLUd3DlzMItncDAGft5EjmgD2A/1aO4yfPfzfxR9XxrjhwLq9l526myJi2cSHuF
+jasS09gRqKmEQWghiINGIzXJWAzjTA+pq8Kwlbepm2K8rItmePd4TpZc4xd8gXFj
+P5d74ix12HQW78vap7WavLDLtbVG6LygQ8CE566fc6J7rkiEJdfWmsWNP3ihH2GB
+DL2fPzH2hIn3qgymnvnpCpS0MU4/L8+Jr6AJes+kOpgesDVqFWvUMOjfSIZga2eF
+/5FJP5NOcHlv7cq3LodKYtPy2vRDHHALDgjV01G3kKGz9A0BOT6KWbVbLTRkTwFP
+FT4BPrLPkRSAXgI1Vj6LHYs=
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/ssl/ssl.key b/ssl/ssl.key
new file mode 100644
index 00000000..1f62598e
--- /dev/null
+++ b/ssl/ssl.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAy/hpM5h5QRf+czcGNSkUcPZWRVHfDje3eyngPBk8gdTpWYlr
+DhRq2BrggG5wRJTOpA6kVoyIKo52v/NXmqWau5UzV5iTe5fYNXYoDjyRx7NaFSb8
+7TGdZB3O+SNbeHDmDXqtJeJt1G72sxaRDfdAeFIdbykn8y1zfNxBdEkBXJgPdHuR
+vw92UyWe3pu7f7W65QHWXxezbHOUau6TRvlsS7I27dXgOZTPcRjDXDC6qPju+FmW
+Mi0GqyoUQxEqmkC9FMXRYPSNkplO92MmKkZkb+kipAllmjb8ge4IvtqHL1xyN1A/
+YzsR9r392HITpM5p928jKIAFFTE7fHjPq4SNrwIDAQABAoIBAQCPZuqvt7coKLJg
+VoMqxOL2OHqW6eSknk+Fa/+WwTdlIEefB5oYoAouPVcxdHPCA8z0Usb/gnYJVXfv
+pConM98Bmvgp0b9+2VbM33Fx8OudN19SF8MjEArT5JErX8xjdRyIxYMOa49EF2+i
+oW8CHp9Y+IJxMMJBmebkFgZ+twUaDxz8YcOfKJcGL4aHPPIde6JPvom2Bg14YBKa
+pMtOWTuYFKyVSwWD1xgY886laGG7WB6Nbevlu8vpUr4mSX2N2BloJUrq4JhFx/7f
+iWs/QrqTJFenVCj6S+xWlBbRau10ajvyqIJtqdWMZStUjeuCY/0Dw/G4fAed3H6c
+aIHEB4fhAoGBAOstXMfbqHONhNKd1xrZCN9qADfsCJvfBE9nHmoPmmgyKL5FfMaU
+Fr6ebfW2P+4rxNbC31gl8c3OfZ9cv9PjmcBPyO14ALb5LAZne9FjmH4aKyV8tWox
+J5WjNpC8yIo/XIBdn4Y72r9VgYjF5tceNJZoHeZj7i36Ug84N2LKllhFAoGBAN4H
+sxFx5wgzlDy8fitiCY4wN6NE2zOQSwFk2NyuWzRzw/vbqnJ7kwX/3yS3NtT1P4Ha
+ma6jIpD/LEr6rVNLbw2okgUAM6BWQ5ZZaIyTwLahqnXmNlsG+t/SeALVgEryqxz1
+0tTPkTK0HJEy2dIXtIVauss450TyzQ6/eJ42mO9jAoGARo2EURzvy0LAfyMFHjPQ
+Op4lVKGF76UXOO75q93kd6/ck0Brb3OL40HKQTWctkoBMmCh+mLfyNtSypVboyib
+vprw73TZ2gqkj4NKHQYhAGu/V+6yyhnXA0hEnWVVUEwz5vqvWejo9g+j3bFpUE3q
+ftjbZ3vBP5/iMFiwHP4j3nUCgYAGx3NnN/QW4wRGqnarum2SQtSgDo0m0OQJYdvh
+OQ2d118HhJh6sF031K0qgNGSxP4wZ81DcMWwaaofi/HY1jfI0fnLX0s0PQ4JPCee
+CzDaIquCuAm208q7JMD3TS+CmlAxLSxHxSKoyqkIoeXWrVScsb18UPt2tnceWShE
+pGQdAwKBgAcwUjldLORhwKUEvaKtExwxTMjS6mzxp2zIm+6SCFwBUAvazbE9xD7Z
+P4yKB8C6lKpq+MqgiyBPk2tlLjF1rbJX7ARXtFsiXpx6RTAvYzV8IxlDwHSvncmx
+GkQ+hpORn8BHD1pjEDxmGRQCNHWLCjLYwISrWaNXe1QmkJF+MtbT
+-----END RSA PRIVATE KEY-----
diff --git a/ssl/sub.class1.server.ca.pem b/ssl/sub.class1.server.ca.pem
new file mode 100644
index 00000000..4a894c7b
--- /dev/null
+++ b/ssl/sub.class1.server.ca.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGNDCCBBygAwIBAgIBGDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcxMDI0MjA1NDE3WjCB
+jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT
+IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0
+YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj0PREGBiE
+gFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJA
+pgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVv
+kvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/
+ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5
+xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwID
+AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov
+L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0
+YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3
+dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0
+c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu
+BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0
+BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl
+LnBkZjANBgkqhkiG9w0BAQUFAAOCAgEAIQlJPqWIbuALi0jaMU2P91ZXouHTYlfp
+tVbzhUV1O+VQHwSL5qBaPucAroXQ+/8gA2TLrQLhxpFy+KNN1t7ozD+hiqLjfDen
+xk+PNdb01m4Ge90h2c9W/8swIkn+iQTzheWq8ecf6HWQTd35RvdCNPdFWAwRDYSw
+xtpdPvkBnufh2lWVvnQce/xNFE+sflVHfXv0pQ1JHpXo9xLBzP92piVH0PN1Nb6X
+t1gW66pceG/sUzCv6gRNzKkC4/C2BBL2MLERPZBOVmTX3DxDX3M570uvh+v2/miI
+RHLq0gfGabDBoYvvF0nXYbFFSF87ICHpW7LM9NfpMfULFWE7epTj69m8f5SuauNi
+YpaoZHy4h/OZMn6SolK+u/hlz8nyMPyLwcKmltdfieFcNID1j0cHL7SRv7Gifl9L
+WtBbnySGBVFaaQNlQ0lxxeBvlDRr9hvYqbBMflPrj0jfyjO1SPo2ShpTpjMM0InN
+SRXNiTE8kMBy12VLUjWKRhFEuT2OKGWmPnmeXAhEKa2wNREuIU640ucQPl2Eg7PD
+wuTSxv0JS3QJ3fGz0xk+gA2iCxnwOOfFwq/iI9th4p1cbiCJSS4jarJiwUW0n6+L
+p/EiO/h94pDQehn7Skzj0n1fSoMD7SfWI55rjbRZotnvbIIp3XUZPD9MEI3vu3Un
+0q6Dp6jOW6c=
+-----END CERTIFICATE-----
diff --git a/test/expect.html b/test/expect.html
new file mode 100644
index 00000000..49b3f67f
--- /dev/null
+++ b/test/expect.html
@@ -0,0 +1,22 @@
+
+
+
+ ..
+
+ <dir> .
+
+
+
+
+ applnk
+
+ <dir> root
+ rwx r-x r-x
+
+
+
+ prefdm
+
+ 1.30kb root
+ rwx r-x r-x
+
\ No newline at end of file
diff --git a/test/test.js b/test/test.js
index fd131686..2ead67a1 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,10 +1,19 @@
(function(){
'use strict';
- var DIR = process.cwd() + '/',
- main = require(DIR + 'lib/server/main'),
+ var DIR = process.cwd() + '/',
+ main = require(DIR + 'lib/server/main'),
+
+ Util = main.util,
- CloudFunc = main.cloudfunc,
+ CloudFunc = main.cloudfunc,
+ HTMLDIR = main.HTMLDIR,
+
+ TEMPLATEPATH = HTMLDIR + 'file.html',
+ PATHTEMPLATE_PATH = HTMLDIR + 'path.html',
+ EXPECT_PATH = DIR + 'test/expect.html',
+
+ Files = [TEMPLATEPATH, PATHTEMPLATE_PATH, EXPECT_PATH],
lJSON = [{
"path": "/etc/X11/",
@@ -19,80 +28,59 @@
"size": 1328,
"uid": 0,
"mode": "100755"
- }];
-
- start();
- var lResult = CloudFunc.buildFromJSON(lJSON);
- end();
-
- var lExpect =
- '' +
- '' +
- ' ' +
- ''+
- ' ' +
- '' +
- '/ ' +
- '' +
- 'etc' +
- ' /X11/' +
- ' ' +
- ' ' +
- '' +
- '' +
- ' ' +
- '' +
- '.. ' +
- ' ' +
- '<dir> ' +
- '. ' +
- ' ' +
- ' ' +
- '' +
- ' ' +
- '' +
- 'applnk ' +
- ' ' +
- '<dir> ' +
- 'root ' +
- 'rwx r-x r-x ' +
- ' ' +
- '' +
- ' ' +
- '' +
- '' +
- 'prefdm' +
- ' ' +
- ' ' +
- '1.30kb ' +
- 'root ' +
- 'rwx r-x r-x ' +
- ' ';
+ }],
- for(var i = 0, n = lExpect.length; i < n; i++)
- if(lResult[i] !== lExpect[i]){
- console.log('Error in char number: ' + i + '\n' +
- 'Expect: ' + lExpect.substr(i) + '\n' +
- 'Result: ' + lResult.substr(i) );
- break;
+
+ Expect =
+ '' +
+ '' +
+ ' ' +
+ ''+
+ ' ' +
+ '' +
+ '/ ' +
+ '' +
+ 'etc' +
+ ' /X11/' +
+ ' ' +
+ ' ' +
+ '';
+
+
+ main.readFiles(Files, function(pErrors, pFiles){
+ if(pErrors)
+ Util.log(pErrors);
+ else{
+ console.time('CloudFunc.buildFromJSON');
+
+ var lTemplate = pFiles[TEMPLATEPATH].toString(),
+ lPathTemplate = pFiles[PATHTEMPLATE_PATH].toString(),
+ lExpect = pFiles[EXPECT_PATH].toString(),
+
+ lResult = CloudFunc.buildFromJSON(lJSON, lTemplate, lPathTemplate);
+
+ Expect += lExpect;
+
+ for(var i = 0, n = Expect.length; i < n; i++)
+ if(lResult[i] !== Expect[i]){
+ console.log('Error in char number: ' + i + '\n' +
+ 'Expect: ' + Expect.substr(i) + '\n' +
+ 'Result: ' + lResult.substr(i) );
+ break;
+ }
+
+ if(i===n)
+ console.log('CloudFunc.buildFromJSON: OK');
+
+ console.timeEnd('CloudFunc.buildFromJSON');
}
- if(i===n)
- console.log('CloudFunc.buildFromJSON: OK');
-
-
- function start(){
- return console.time('CloudFunc.buildFromJSON');
- }
- function end(){
- return console.timeEnd('CloudFunc.buildFromJSON');
- }
+ });
+
})();
diff --git a/test/test.sh b/test/test.sh
index 8a20d346..e9c2fd3e 100755
--- a/test/test.sh
+++ b/test/test.sh
@@ -1,13 +1,13 @@
#!/bin/sh
npm i recess jshint
echo "jshint server.js client.js cloudcmd.js"
-node_modules/jshint/bin/hint --config test/.jshintrc lib/server.js lib/client.js cloudcmd.js
+node_modules/jshint/bin/jshint --config test/.jshintrc lib/server.js lib/client.js cloudcmd.js
echo "jshint lib/cloudfunc.js lib/client/keyBinding.js"
-node_modules/jshint/bin/hint --config test/.jshintrc lib/util.js lib/cloudfunc.js lib/client/keyBinding.js
+node_modules/jshint/bin/jshint --config test/.jshintrc lib/util.js lib/cloudfunc.js lib/client/keyBinding.js
echo "lib/client/dom.js lib/client/ie.js lib/client/menu.js lib/client/socket.js ./lib/client/terminal.js lib/client/viewer.js lib/client/storage/_github.js lib/client/menu.js lib/client/editor/_codemirror.js"
-node_modules/jshint/bin/hint --config test/.jshintrc lib/client/dom.js lib/client/ie.js lib/client/menu.js lib/client/socket.js ./lib/client/terminal.js lib/client/viewer.js lib/client/storage/_github.js lib/client/menu.js lib/client/editor/_codemirror.js
-echo "jshint ./package.json ./config.json"
-node_modules/jshint/bin/hint --config test/.jshintrc ./package.json ./config.json
+node_modules/jshint/bin/jshint --config test/.jshintrc lib/client/dom.js lib/client/ie.js lib/client/menu.js lib/client/socket.js ./lib/client/terminal.js lib/client/viewer.js lib/client/storage/_github.js lib/client/menu.js lib/client/editor/_codemirror.js
+echo "jshint ./package.json ./json/config.json"
+node_modules/jshint/bin/jshint --config test/.jshintrc ./package.json ./json/config.json
#linting css files
echo "recess css/*.css"
./node_modules/recess/bin/recess css/*.css