diff --git a/ChangeLog b/ChangeLog index 6b679ec2..f951d2f1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -43,6 +43,9 @@ writed root directory. * Changed sync reading of certs to async. +* Updated dropbox to v0.9.2 and moved to packege.json +from storage folder. + 2012.03.01, Version 0.1.9 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\n

Please 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\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>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 - - - - - - - - - - - - - - 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=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="
    t
    ",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>");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>"),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=/)<[^<]*)*<\/script>/gi,bn=/([?&])_=[^&]*/,wn=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,En=v.fn.load,Sn={},xn={},Tn=["*/"]+["*"];try{cn=s.href}catch(Nn){cn=i.createElement("a"),cn.href="",cn=cn.href}ln=wn.exec(cn.toLowerCase())||[],v.fn.load=function(e,n,r){if(typeof e!="string"&&En)return En.apply(this,arguments);if(!this.length)return this;var i,s,o,u=this,a=e.indexOf(" ");return a>=0&&(i=e.slice(a,e.length),e=e.slice(0,a)),v.isFunction(n)?(r=n,n=t):n&&typeof n=="object"&&(s="POST"),v.ajax({url:e,type:s,dataType:"html",data:n,complete:function(e,t){r&&u.each(r,o||[e.responseText,t,e])}}).done(function(e){o=arguments,u.html(i?v("
    ").append(e.replace(yn,"")).find(i):e)}),this},v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,t){v.fn[t]=function(e){return this.on(t,e)}}),v.each(["get","post"],function(e,n){v[n]=function(e,r,i,s){return v.isFunction(r)&&(s=s||i,i=r,r=t),v.ajax({type:n,url:e,data:r,success:i,dataType:s})}}),v.extend({getScript:function(e,n){return v.get(e,t,n,"script")},getJSON:function(e,t,n){return v.get(e,t,n,"json")},ajaxSetup:function(e,t){return t?Ln(e,v.ajaxSettings):(t=e,e=v.ajaxSettings),Ln(e,t),e},ajaxSettings:{url:cn,isLocal:dn.test(ln[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":Tn},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":v.parseJSON,"text xml":v.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:Cn(Sn),ajaxTransport:Cn(xn),ajax:function(e,n){function T(e,n,s,a){var l,y,b,w,S,T=n;if(E===2)return;E=2,u&&clearTimeout(u),o=t,i=a||"",x.readyState=e>0?4:0,s&&(w=An(c,x,s));if(e>=200&&e<300||e===304)c.ifModified&&(S=x.getResponseHeader("Last-Modified"),S&&(v.lastModified[r]=S),S=x.getResponseHeader("Etag"),S&&(v.etag[r]=S)),e===304?(T="notmodified",l=!0):(l=On(c,w),T=l.state,y=l.data,b=l.error,l=!b);else{b=T;if(!T||e)T="error",e<0&&(e=0)}x.status=e,x.statusText=(n||T)+"",l?d.resolveWith(h,[y,T,x]):d.rejectWith(h,[x,T,b]),x.statusCode(g),g=t,f&&p.trigger("ajax"+(l?"Success":"Error"),[x,c,l?y:b]),m.fireWith(h,[x,T]),f&&(p.trigger("ajaxComplete",[x,c]),--v.active||v.event.trigger("ajaxStop"))}typeof e=="object"&&(n=e,e=t),n=n||{};var r,i,s,o,u,a,f,l,c=v.ajaxSetup({},n),h=c.context||c,p=h!==c&&(h.nodeType||h instanceof v)?v(h):v.event,d=v.Deferred(),m=v.Callbacks("once memory"),g=c.statusCode||{},b={},w={},E=0,S="canceled",x={readyState:0,setRequestHeader:function(e,t){if(!E){var n=e.toLowerCase();e=w[n]=w[n]||e,b[e]=t}return this},getAllResponseHeaders:function(){return E===2?i:null},getResponseHeader:function(e){var n;if(E===2){if(!s){s={};while(n=pn.exec(i))s[n[1].toLowerCase()]=n[2]}n=s[e.toLowerCase()]}return n===t?null:n},overrideMimeType:function(e){return E||(c.mimeType=e),this},abort:function(e){return e=e||S,o&&o.abort(e),T(0,e),this}};d.promise(x),x.success=x.done,x.error=x.fail,x.complete=m.add,x.statusCode=function(e){if(e){var t;if(E<2)for(t in e)g[t]=[g[t],e[t]];else t=e[x.status],x.always(t)}return this},c.url=((e||c.url)+"").replace(hn,"").replace(mn,ln[1]+"//"),c.dataTypes=v.trim(c.dataType||"*").toLowerCase().split(y),c.crossDomain==null&&(a=wn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===ln[1]&&a[2]===ln[2]&&(a[3]||(a[1]==="http:"?80:443))==(ln[3]||(ln[1]==="http:"?80:443)))),c.data&&c.processData&&typeof c.data!="string"&&(c.data=v.param(c.data,c.traditional)),kn(Sn,c,n,x);if(E===2)return x;f=c.global,c.type=c.type.toUpperCase(),c.hasContent=!vn.test(c.type),f&&v.active++===0&&v.event.trigger("ajaxStart");if(!c.hasContent){c.data&&(c.url+=(gn.test(c.url)?"&":"?")+c.data,delete c.data),r=c.url;if(c.cache===!1){var N=v.now(),C=c.url.replace(bn,"$1_="+N);c.url=C+(C===c.url?(gn.test(c.url)?"&":"?")+"_="+N:"")}}(c.data&&c.hasContent&&c.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",c.contentType),c.ifModified&&(r=r||c.url,v.lastModified[r]&&x.setRequestHeader("If-Modified-Since",v.lastModified[r]),v.etag[r]&&x.setRequestHeader("If-None-Match",v.etag[r])),x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+Tn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)x.setRequestHeader(l,c.headers[l]);if(!c.beforeSend||c.beforeSend.call(h,x,c)!==!1&&E!==2){S="abort";for(l in{success:1,error:1,complete:1})x[l](c[l]);o=kn(xn,c,n,x);if(!o)T(-1,"No Transport");else{x.readyState=1,f&&p.trigger("ajaxSend",[x,c]),c.async&&c.timeout>0&&(u=setTimeout(function(){x.abort("timeout")},c.timeout));try{E=1,o.send(b,T)}catch(k){if(!(E<2))throw k;T(-1,k)}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var Mn=[],_n=/\?/,Dn=/(=)\?(?=&|$)|\?\?/,Pn=v.now();v.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Mn.pop()||v.expando+"_"+Pn++;return this[e]=!0,e}}),v.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.data,f=n.url,l=n.jsonp!==!1,c=l&&Dn.test(f),h=l&&!c&&typeof a=="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Dn.test(a);if(n.dataTypes[0]==="jsonp"||c||h)return s=n.jsonpCallback=v.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,o=e[s],c?n.url=f.replace(Dn,"$1"+s):h?n.data=a.replace(Dn,"$1"+s):l&&(n.url+=(_n.test(f)?"&":"?")+n.jsonp+"="+s),n.converters["script json"]=function(){return u||v.error(s+" was not called"),u[0]},n.dataTypes[0]="json",e[s]=function(){u=arguments},i.always(function(){e[s]=o,n[s]&&(n.jsonpCallback=r.jsonpCallback,Mn.push(s)),u&&v.isFunction(o)&&o(u[0]),u=o=t}),"script"}),v.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){return v.globalEval(e),e}}}),v.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),v.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=i.head||i.getElementsByTagName("head")[0]||i.documentElement;return{send:function(s,o){n=i.createElement("script"),n.async="async",e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,i){if(i||!n.readyState||/loaded|complete/.test(n.readyState))n.onload=n.onreadystatechange=null,r&&n.parentNode&&r.removeChild(n),n=t,i||o(200,"success")},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(0,1)}}}});var Hn,Bn=e.ActiveXObject?function(){for(var e in Hn)Hn[e](0,1)}:!1,jn=0;v.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&Fn()||In()}:Fn,function(e){v.extend(v.support,{ajax:!!e,cors:!!e&&"withCredentials"in e})}(v.ajaxSettings.xhr()),v.support.ajax&&v.ajaxTransport(function(n){if(!n.crossDomain||v.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();n.username?a.open(n.type,n.url,n.async,n.username,n.password):a.open(n.type,n.url,n.async);if(n.xhrFields)for(u in n.xhrFields)a[u]=n.xhrFields[u];n.mimeType&&a.overrideMimeType&&a.overrideMimeType(n.mimeType),!n.crossDomain&&!i["X-Requested-With"]&&(i["X-Requested-With"]="XMLHttpRequest");try{for(u in i)a.setRequestHeader(u,i[u])}catch(f){}a.send(n.hasContent&&n.data||null),r=function(e,i){var u,f,l,c,h;try{if(r&&(i||a.readyState===4)){r=t,o&&(a.onreadystatechange=v.noop,Bn&&delete Hn[o]);if(i)a.readyState!==4&&a.abort();else{u=a.status,l=a.getAllResponseHeaders(),c={},h=a.responseXML,h&&h.documentElement&&(c.xml=h);try{c.text=a.responseText}catch(p){}try{f=a.statusText}catch(p){f=""}!u&&n.isLocal&&!n.crossDomain?u=c.text?200:404:u===1223&&(u=204)}}}catch(d){i||s(-1,d)}c&&s(u,f,c,l)},n.async?a.readyState===4?setTimeout(r,0):(o=++jn,Bn&&(Hn||(Hn={},v(e).unload(Bn)),Hn[o]=r),a.onreadystatechange=r):r()},abort:function(){r&&r(0,1)}}}});var qn,Rn,Un=/^(?:toggle|show|hide)$/,zn=new RegExp("^(?:([-+])=|)("+m+")([a-z%]*)$","i"),Wn=/queueHooks$/,Xn=[Gn],Vn={"*":[function(e,t){var n,r,i=this.createTween(e,t),s=zn.exec(t),o=i.cur(),u=+o||0,a=1,f=20;if(s){n=+s[2],r=s[3]||(v.cssNumber[e]?"":"px");if(r!=="px"&&u){u=v.css(i.elem,e,!0)||n||1;do a=a||".5",u/=a,v.style(i.elem,e,u+r);while(a!==(a=i.cur()/o)&&a!==1&&--f)}i.unit=r,i.start=u,i.end=s[1]?u+(s[1]+1)*n:n}return i}]};v.Animation=v.extend(Kn,{tweener:function(e,t){v.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;r-1,f={},l={},c,h;a?(l=i.position(),c=l.top,h=l.left):(c=parseFloat(o)||0,h=parseFloat(u)||0),v.isFunction(t)&&(t=t.call(e,n,s)),t.top!=null&&(f.top=t.top-s.top+c),t.left!=null&&(f.left=t.left-s.left+h),"using"in t?t.using.call(e,f):i.css(f)}},v.fn.extend({position:function(){if(!this[0])return;var e=this[0],t=this.offsetParent(),n=this.offset(),r=er.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(v.css(e,"marginTop"))||0,n.left-=parseFloat(v.css(e,"marginLeft"))||0,r.top+=parseFloat(v.css(t[0],"borderTopWidth"))||0,r.left+=parseFloat(v.css(t[0],"borderLeftWidth"))||0,{top:n.top-r.top,left:n.left-r.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||i.body;while(e&&!er.test(e.nodeName)&&v.css(e,"position")==="static")e=e.offsetParent;return e||i.body})}}),v.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);v.fn[e]=function(i){return v.access(this,function(e,i,s){var o=tr(e);if(s===t)return o?n in o?o[n]:o.document.documentElement[i]:e[i];o?o.scrollTo(r?v(o).scrollLeft():s,r?s:v(o).scrollTop()):e[i]=s},e,i,arguments.length,null)}}),v.each({Height:"height",Width:"width"},function(e,n){v.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){v.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!="boolean"),u=r||(i===!0||s===!0?"margin":"border");return v.access(this,function(n,r,i){var s;return v.isWindow(n)?n.document.documentElement["client"+e]:n.nodeType===9?(s=n.documentElement,Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])):i===t?v.css(n,r,i,u):v.style(n,r,i,u)},n,o?i:t,o,null)}})}),e.jQuery=e.$=v,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return v})})(window); \ No newline at end of file diff --git a/lib/client/storage/dropbox/samples/checkbox.js/public/lib/less.js b/lib/client/storage/dropbox/samples/checkbox.js/public/lib/less.js deleted file mode 100644 index 9b0fa6ba..00000000 --- a/lib/client/storage/dropbox/samples/checkbox.js/public/lib/less.js +++ /dev/null @@ -1,9 +0,0 @@ -// -// LESS - Leaner CSS v1.3.3 -// http://lesscss.org -// -// Copyright (c) 2009-2013, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(e,t){function n(t){return e.less[t.split("/")[1]]}function f(){r.env==="development"?(r.optimization=0,r.watchTimer=setInterval(function(){r.watchMode&&g(function(e,t,n,r,i){t&&S(t.toCSS(),r,i.lastModified)})},r.poll)):r.optimization=3}function m(){var e=document.getElementsByTagName("style");for(var t=0;t0&&(s.splice(o-1,2),o-=2)}return i.hostPart=r[1],i.directories=s,i.path=r[1]+s.join("/"),i.fileUrl=i.path+(r[4]||""),i.url=i.fileUrl+(r[5]||""),i}function w(t,n,i,s){var o=t.contents||{},u=t.files||{},a=b(t.href,e.location.href),f=a.url,c=l&&l.getItem(f),h=l&&l.getItem(f+":timestamp"),p={css:c,timestamp:h},d;r.relativeUrls?r.rootpath?t.entryPath?d=b(r.rootpath+y(a.path,t.entryPath)).path:d=r.rootpath:d=a.path:r.rootpath?d=r.rootpath:t.entryPath?d=t.entryPath:d=a.path,x(f,t.type,function(e,l){v+=e.replace(/@import .+?;/ig,"");if(!i&&p&&l&&(new Date(l)).valueOf()===(new Date(p.timestamp)).valueOf())S(p.css,t),n(null,null,e,t,{local:!0,remaining:s},f);else try{o[f]=e,(new r.Parser({optimization:r.optimization,paths:[a.path],entryPath:t.entryPath||a.path,mime:t.type,filename:f,rootpath:d,relativeUrls:t.relativeUrls,contents:o,files:u,dumpLineNumbers:r.dumpLineNumbers})).parse(e,function(r,i){if(r)return k(r,f);try{n(r,i,e,t,{local:!1,lastModified:l,remaining:s},f),N(document.getElementById("less-error-message:"+E(f)))}catch(r){k(r,f)}})}catch(c){k(c,f)}},function(e,t){throw new Error("Couldn't load "+t+" ("+e+")")})}function E(e){return e.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\.[a-zA-Z]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function S(e,t,n){var r,i=t.href||"",s="less:"+(t.title||E(i));if((r=document.getElementById(s))===null){r=document.createElement("style"),r.type="text/css",t.media&&(r.media=t.media),r.id=s;var o=t&&t.nextSibling||null;(o||document.getElementsByTagName("head")[0]).parentNode.insertBefore(r,o)}if(r.styleSheet)try{r.styleSheet.cssText=e}catch(u){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(e){r.childNodes.length>0?r.firstChild.nodeValue!==e.nodeValue&&r.replaceChild(e,r.firstChild):r.appendChild(e)})(document.createTextNode(e));if(n&&l){C("saving "+i+" to cache.");try{l.setItem(i,e),l.setItem(i+":timestamp",n)}catch(u){C("failed to save")}}}function x(e,t,n,i){function a(t,n,r){t.status>=200&&t.status<300?n(t.responseText,t.getResponseHeader("Last-Modified")):typeof r=="function"&&r(t.status,e)}var s=T(),u=o?r.fileAsync:r.async;typeof s.overrideMimeType=="function"&&s.overrideMimeType("text/css"),s.open("GET",e,u),s.setRequestHeader("Accept",t||"text/x-less, text/css; q=0.9, */*; q=0.5"),s.send(null),o&&!r.fileAsync?s.status===0||s.status>=200&&s.status<300?n(s.responseText):i(s.status,e):u?s.onreadystatechange=function(){s.readyState==4&&a(s,n,i)}:a(s,n,i)}function T(){if(e.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(t){return C("browser doesn't support AJAX."),null}}function N(e){return e&&e.parentNode.removeChild(e)}function C(e){r.env=="development"&&typeof console!="undefined"&&console.log("less: "+e)}function k(e,t){var n="less-error-message:"+E(t),i='
  • {content}
  • ',s=document.createElement("div"),o,u,a=[],f=e.filename||t,l=f.match(/([^\/]+(\?.*)?)$/)[1];s.id=n,s.className="less-error-message",u="

    "+(e.message||"There is an error in your .less file")+"

    "+'

    in '+l+" ";var c=function(e,t,n){e.extract[t]&&a.push(i.replace(/\{line\}/,parseInt(e.line)+(t-1)).replace(/\{class\}/,n).replace(/\{content\}/,e.extract[t]))};e.stack?u+="
    "+e.stack.split("\n").slice(1).join("
    "):e.extract&&(c(e,0,""),c(e,1,"line"),c(e,2,""),u+="on line "+e.line+", column "+(e.column+1)+":

    "+"
      "+a.join("")+"
    "),s.innerHTML=u,S([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),s.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),r.env=="development"&&(o=setInterval(function(){document.body&&(document.getElementById(n)?document.body.replaceChild(s,document.getElementById(n)):document.body.insertBefore(s,document.body.firstChild),clearInterval(o))},10))}Array.isArray||(Array.isArray=function(e){return Object.prototype.toString.call(e)==="[object Array]"||e instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(e,t){var n=this.length>>>0;for(var r=0;r>>0,n=new Array(t),r=arguments[1];for(var i=0;i>>0,n=0;if(t===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var r=arguments[1];else do{if(n in this){r=this[n++];break}if(++n>=t)throw new TypeError}while(!0);for(;n=t)return-1;n<0&&(n+=t);for(;nh&&(c[u]=c[u].slice(o-h),h=o)}function w(e){var t=e.charCodeAt(0);return t===32||t===10||t===9}function E(e){var t,n,r,i,a;if(e instanceof Function)return e.call(p.parsers);if(typeof e=="string")t=s.charAt(o)===e?e:null,r=1,b();else{b();if(!(t=e.exec(c[u])))return null;r=t[0].length}if(t)return S(r),typeof t=="string"?t:t.length===1?t[0]:t}function S(e){var t=o,n=u,r=o+c[u].length,i=o+=e;while(o=0&&t.charAt(n)!=="\n";n--)r++;return{line:typeof e=="number"?(t.slice(0,e).match(/\n/g)||"").length:null,column:r}}function L(e){return r.mode==="browser"||r.mode==="rhino"?e.filename:n("path").resolve(e.filename)}function A(e,t,n){return{lineNumber:k(e,t).line+1,fileName:L(n)}}function O(e,t){var n=C(e,t),r=k(e.index,n),i=r.line,s=r.column,o=n.split("\n");this.type=e.type||"Syntax",this.message=e.message,this.filename=e.filename||t.filename,this.index=e.index,this.line=typeof i=="number"?i+1:null,this.callLine=e.call&&k(e.call,n).line+1,this.callExtract=o[k(e.call,n).line],this.stack=e.stack,this.column=s,this.extract=[o[i-1],o[i],o[i+1]]}var s,o,u,a,f,l,c,h,p,d=this,t=t||{};t.contents||(t.contents={}),t.rootpath=t.rootpath||"",t.files||(t.files={});var v=function(){},m=this.imports={paths:t.paths||[],queue:[],files:t.files,contents:t.contents,mime:t.mime,error:null,push:function(e,n){var i=this;this.queue.push(e),r.Parser.importer(e,this.paths,function(t,r,s){i.queue.splice(i.queue.indexOf(e),1);var o=s in i.files;i.files[s]=r,t&&!i.error&&(i.error=t),n(t,r,o),i.queue.length===0&&v(i.error)},t)}};return this.env=t=t||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,p={imports:m,parse:function(e,a){var f,d,m,g,y,b,w=[],S,x=null;o=u=h=l=0,s=e.replace(/\r\n/g,"\n"),s=s.replace(/^\uFEFF/,""),c=function(e){var n=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,o=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,u=0,a,f=e[0],l;for(var c=0,h,p;c0?"missing closing `}`":"missing opening `{`",filename:t.filename},t)),e.map(function(e){return e.join("")})}([[]]);if(x)return a(x,t);try{f=new i.Ruleset([],E(this.parsers.primary)),f.root=!0}catch(T){return a(new O(T,t))}f.toCSS=function(e){var s,o,u;return function(s,o){var u=[],a;s=s||{},typeof o=="object"&&!Array.isArray(o)&&(o=Object.keys(o).map(function(e){var t=o[e];return t instanceof i.Value||(t instanceof i.Expression||(t=new i.Expression([t])),t=new i.Value([t])),new i.Rule("@"+e,t,!1,0)}),u=[new i.Ruleset(null,o)]);try{var f=e.call(this,{frames:u}).toCSS([],{compress:s.compress||!1,dumpLineNumbers:t.dumpLineNumbers})}catch(l){throw new O(l,t)}if(a=p.imports.error)throw a instanceof O?a:new O(a,t);return s.yuicompress&&r.mode==="node"?n("ycssmin").cssmin(f):s.compress?f.replace(/(\s)+/g,"$1"):f}}(f.eval);if(o=0&&s.charAt(N)!=="\n";N--)C++;x={type:"Parse",message:"Syntax Error on line "+y,index:o,filename:t.filename,line:y,column:C,extract:[b[y-2],b[y-1],b[y]]}}this.imports.queue.length>0?v=function(e){e=x||e,e?a(e):a(null,f)}:a(x,f)},parsers:{primary:function(){var e,t=[];while((e=E(this.mixin.definition)||E(this.rule)||E(this.ruleset)||E(this.mixin.call)||E(this.comment)||E(this.directive))||E(/^[\s\n]+/)||E(/^;+/))e&&t.push(e);return t},comment:function(){var e;if(s.charAt(o)!=="/")return;if(s.charAt(o+1)==="/")return new i.Comment(E(/^\/\/.*/),!0);if(e=E(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=='"'&&s.charAt(t)!=="'")return;n&&E("~");if(e=E(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new i.Quoted(e[0],e[1]||e[2],n)},keyword:function(){var e;if(e=E(/^[_A-Za-z-][_A-Za-z0-9-]*/))return i.colors.hasOwnProperty(e)?new i.Color(i.colors[e].slice(1)):new i.Keyword(e)},call:function(){var e,n,r,s,a=o;if(!(e=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(c[u])))return;e=e[1],n=e.toLowerCase();if(n==="url")return null;o+=e.length;if(n==="alpha"){s=E(this.alpha);if(typeof s!="undefined")return s}E("("),r=E(this.entities.arguments);if(!E(")"))return;if(e)return new i.Call(e,r,a,t.filename)},arguments:function(){var e=[],t;while(t=E(this.entities.assignment)||E(this.expression)){e.push(t);if(!E(","))break}return e},literal:function(){return E(this.entities.ratio)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.quoted)||E(this.entities.unicodeDescriptor)},assignment:function(){var e,t;if((e=E(/^\w+(?=\s?=)/i))&&E("=")&&(t=E(this.entity)))return new i.Assignment(e,t)},url:function(){var e;if(s.charAt(o)!=="u"||!E(/^url\(/))return;return e=E(this.entities.quoted)||E(this.entities.variable)||E(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",x(")"),new i.URL(e.value!=null||e instanceof i.Variable?e:new i.Anonymous(e),t.rootpath)},variable:function(){var e,n=o;if(s.charAt(o)==="@"&&(e=E(/^@@?[\w-]+/)))return new i.Variable(e,n,t.filename)},variableCurly:function(){var e,n,r=o;if(s.charAt(o)==="@"&&(n=E(/^@\{([\w-]+)\}/)))return new i.Variable("@"+n[1],r,t.filename)},color:function(){var e;if(s.charAt(o)==="#"&&(e=E(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/)))return new i.Color(e[1])},dimension:function(){var e,t=s.charCodeAt(o);if(t>57||t<43||t===47||t==44)return;if(e=E(/^([+-]?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/))return new i.Dimension(e[1],e[2])},ratio:function(){var e,t=s.charCodeAt(o);if(t>57||t<48)return;if(e=E(/^(\d+\/\d+)/))return new i.Ratio(e[1])},unicodeDescriptor:function(){var e;if(e=E(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))return new i.UnicodeDescriptor(e[0])},javascript:function(){var e,t=o,n;s.charAt(t)==="~"&&(t++,n=!0);if(s.charAt(t)!=="`")return;n&&E("~");if(e=E(/^`([^`]*)`/))return new i.JavaScript(e[1],o,n)}},variable:function(){var e;if(s.charAt(o)==="@"&&(e=E(/^(@[\w-]+)\s*:/)))return e[1]},shorthand:function(){var e,t;if(!N(/^[@\w.%-]+\/[@\w.-]+/))return;g();if((e=E(this.entity))&&E("/")&&(t=E(this.entity)))return new i.Shorthand(e,t);y()},mixin:{call:function(){var e=[],n,r,u=[],a=[],f,l,c,h,p,d,v,m=o,b=s.charAt(o),w,S,C=!1;if(b!=="."&&b!=="#")return;g();while(n=E(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/))e.push(new i.Element(r,n,o)),r=E(">");if(E("(")){p=[];while(c=E(this.expression)){h=null,S=c;if(c.value.length==1){var k=c.value[0];k instanceof i.Variable&&E(":")&&(p.length>0&&(d&&T("Cannot mix ; and , as delimiter types"),v=!0),S=x(this.expression),h=w=k.name)}p.push(S),a.push({name:h,value:S});if(E(","))continue;if(E(";")||d)v&&T("Cannot mix ; and , as delimiter types"),d=!0,p.length>1&&(S=new i.Value(p)),u.push({name:w,value:S}),w=null,p=[],v=!1}x(")")}f=d?u:a,E(this.important)&&(C=!0);if(e.length>0&&(E(";")||N("}")))return new i.mixin.Call(e,f,m,t.filename,C);y()},definition:function(){var e,t=[],n,r,u,a,f,c=!1;if(s.charAt(o)!=="."&&s.charAt(o)!=="#"||N(/^[^{]*\}/))return;g();if(n=E(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){e=n[1];do{E(this.comment);if(s.charAt(o)==="."&&E(/^\.{3}/)){c=!0,t.push({variadic:!0});break}if(!(u=E(this.entities.variable)||E(this.entities.literal)||E(this.entities.keyword)))break;if(u instanceof i.Variable)if(E(":"))a=x(this.expression,"expected expression"),t.push({name:u.name,value:a});else{if(E(/^\.{3}/)){t.push({name:u.name,variadic:!0}),c=!0;break}t.push({name:u.name})}else t.push({value:u})}while(E(",")||E(";"));E(")")||(l=o,y()),E(this.comment),E(/^when/)&&(f=x(this.conditions,"expected condition")),r=E(this.block);if(r)return new i.mixin.Definition(e,t,r,f,c);y()}}},entity:function(){return E(this.entities.literal)||E(this.entities.variable)||E(this.entities.url)||E(this.entities.call)||E(this.entities.keyword)||E(this.entities.javascript)||E(this.comment)},end:function(){return E(";")||N("}")},alpha:function(){var e;if(!E(/^\(opacity=/i))return;if(e=E(/^\d+/)||E(this.entities.variable))return x(")"),new i.Alpha(e)},element:function(){var e,t,n,r;n=E(this.combinator),e=E(/^(?:\d+\.\d+|\d+)%/)||E(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||E("*")||E("&")||E(this.attribute)||E(/^\([^()@]+\)/)||E(/^[\.#](?=@)/)||E(this.entities.variableCurly),e||E("(")&&(r=E(this.entities.variableCurly)||E(this.entities.variable)||E(this.selector))&&E(")")&&(e=new i.Paren(r));if(e)return new i.Element(n,e,o)},combinator:function(){var e,t=s.charAt(o);if(t===">"||t==="+"||t==="~"||t==="|"){o++;while(s.charAt(o).match(/\s/))o++;return new i.Combinator(t)}return s.charAt(o-1).match(/\s/)?new i.Combinator(" "):new i.Combinator(null)},selector:function(){var e,t,n=[],r,u;if(E("("))return e=E(this.entity),E(")")?new i.Selector([new i.Element("",e,o)]):null;while(t=E(this.element)){r=s.charAt(o),n.push(t);if(r==="{"||r==="}"||r===";"||r===","||r===")")break}if(n.length>0)return new i.Selector(n)},attribute:function(){var e="",t,n,r;if(!E("["))return;if(t=E(/^(?:[_A-Za-z0-9-]|\\.)+/)||E(this.entities.quoted))(r=E(/^[|~*$^]?=/))&&(n=E(this.entities.quoted)||E(/^[\w-]+/))?e=[t,r,n.toCSS?n.toCSS():n].join(""):e=t;if(!E("]"))return;if(e)return"["+e+"]"},block:function(){var e;if(E("{")&&(e=E(this.primary))&&E("}"))return e},ruleset:function(){var e=[],n,r,u,a;g(),t.dumpLineNumbers&&(a=A(o,s,t));while(n=E(this.selector)){e.push(n),E(this.comment);if(!E(","))break;E(this.comment)}if(e.length>0&&(r=E(this.block))){var f=new i.Ruleset(e,r,t.strictImports);return t.dumpLineNumbers&&(f.debugInfo=a),f}l=o,y()},rule:function(){var e,t,n=s.charAt(o),r,a;g();if(n==="."||n==="#"||n==="&")return;if(e=E(this.variable)||E(this.property)){e.charAt(0)!="@"&&(a=/^([^@+\/'"*`(;{}-]*);/.exec(c[u]))?(o+=a[0].length-1,t=new i.Anonymous(a[1])):e==="font"?t=E(this.font):t=E(this.value),r=E(this.important);if(t&&E(this.end))return new i.Rule(e,t,r,f);l=o,y()}},"import":function(){var e,n,r=o;g();var s=E(/^@import(?:-(once))?\s+/);if(s&&(e=E(this.entities.quoted)||E(this.entities.url))){n=E(this.mediaFeatures);if(E(";"))return new i.Import(e,m,n,s[1]==="once",r,t.rootpath)}y()},mediaFeature:function(){var e,t,n=[];do if(e=E(this.entities.keyword))n.push(e);else if(E("(")){t=E(this.property),e=E(this.entity);if(!E(")"))return null;if(t&&e)n.push(new i.Paren(new i.Rule(t,e,null,o,!0)));else{if(!e)return null;n.push(new i.Paren(e))}}while(e);if(n.length>0)return new i.Expression(n)},mediaFeatures:function(){var e,t=[];do if(e=E(this.mediaFeature)){t.push(e);if(!E(","))break}else if(e=E(this.entities.variable)){t.push(e);if(!E(","))break}while(e);return t.length>0?t:null},media:function(){var e,n,r,u;t.dumpLineNumbers&&(u=A(o,s,t));if(E(/^@media/)){e=E(this.mediaFeatures);if(n=E(this.block))return r=new i.Media(n,e),t.dumpLineNumbers&&(r.debugInfo=u),r}},directive:function(){var e,n,r,u,a,f,l,c,h,p;if(s.charAt(o)!=="@")return;if(n=E(this["import"])||E(this.media))return n;g(),e=E(/^@[a-z-]+/);if(!e)return;l=e,e.charAt(1)=="-"&&e.indexOf("-",2)>0&&(l="@"+e.slice(e.indexOf("-",2)+1));switch(l){case"@font-face":c=!0;break;case"@viewport":case"@top-left":case"@top-left-corner":case"@top-center":case"@top-right":case"@top-right-corner":case"@bottom-left":case"@bottom-left-corner":case"@bottom-center":case"@bottom-right":case"@bottom-right-corner":case"@left-top":case"@left-middle":case"@left-bottom":case"@right-top":case"@right-middle":case"@right-bottom":c=!0;break;case"@page":case"@document":case"@supports":case"@keyframes":c=!0,h=!0;break;case"@namespace":p=!0}h&&(e+=" "+(E(/^[^{]+/)||"").trim());if(c){if(r=E(this.block))return new i.Directive(e,r)}else if((n=p?E(this.expression):E(this.entity))&&E(";")){var d=new i.Directive(e,n);return t.dumpLineNumbers&&(d.debugInfo=A(o,s,t)),d}y()},font:function(){var e=[],t=[],n,r,s,o;while(o=E(this.shorthand)||E(this.entity))t.push(o);e.push(new i.Expression(t));if(E(","))while(o=E(this.expression)){e.push(o);if(!E(","))break}return new i.Value(e)},value:function(){var e,t=[],n;while(e=E(this.expression)){t.push(e);if(!E(","))break}if(t.length>0)return new i.Value(t)},important:function(){if(s.charAt(o)==="!")return E(/^! *important/)},sub:function(){var e;if(E("(")&&(e=E(this.expression))&&E(")"))return e},multiplication:function(){var e,t,n,r;if(e=E(this.operand)){while(!N(/^\/[*\/]/)&&(n=E("/")||E("*"))&&(t=E(this.operand)))r=new i.Operation(n,[r||e,t]);return r||e}},addition:function(){var e,t,n,r;if(e=E(this.multiplication)){while((n=E(/^[-+]\s+/)||!w(s.charAt(o-1))&&(E("+")||E("-")))&&(t=E(this.multiplication)))r=new i.Operation(n,[r||e,t]);return r||e}},conditions:function(){var e,t,n=o,r;if(e=E(this.condition)){while(E(",")&&(t=E(this.condition)))r=new i.Condition("or",r||e,t,n);return r||e}},condition:function(){var e,t,n,r,s=o,u=!1;E(/^not/)&&(u=!0),x("(");if(e=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))return(r=E(/^(?:>=|=<|[<=>])/))?(t=E(this.addition)||E(this.entities.keyword)||E(this.entities.quoted))?n=new i.Condition(r,e,t,s,u):T("expected expression"):n=new i.Condition("=",e,new i.Keyword("true"),s,u),x(")"),E(/^and/)?new i.Condition("and",n,E(this.condition)):n},operand:function(){var e,t=s.charAt(o+1);s.charAt(o)==="-"&&(t==="@"||t==="(")&&(e=E("-"));var n=E(this.sub)||E(this.entities.dimension)||E(this.entities.color)||E(this.entities.variable)||E(this.entities.call);return e?new i.Operation("*",[new i.Dimension(-1),n]):n},expression:function(){var e,t,n=[],r;while(e=E(this.addition)||E(this.entity))n.push(e);if(n.length>0)return new i.Expression(n)},property:function(){var e;if(e=E(/^(\*?-?[_a-z0-9-]+)\s*:/))return e[1]}}}};if(r.mode==="browser"||r.mode==="rhino")r.Parser.importer=function(e,t,n,r){!/^([a-z-]+:)?\//.test(e)&&t.length>0&&(e=t[0]+e),w({href:e,title:e,type:r.mime,contents:r.contents,files:r.files,rootpath:r.rootpath,entryPath:r.entryPath,relativeUrls:r.relativeUrls},function(e,i,s,o,u,a){e&&typeof r.errback=="function"?r.errback.call(null,a,t,n,r):n.call(null,e,i,a)},!0)};(function(e){function t(t){return e.functions.hsla(t.h,t.s,t.l,t.a)}function n(t,n){return t instanceof e.Dimension&&t.unit=="%"?parseFloat(t.value*n/100):r(t)}function r(t){if(t instanceof e.Dimension)return parseFloat(t.unit=="%"?t.value/100:t.value);if(typeof t=="number")return t;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function i(e){return Math.min(1,Math.max(0,e))}e.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(t,i,s,o){var u=[t,i,s].map(function(e){return n(e,256)});return o=r(o),new e.Color(u,o)},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,n,i){function u(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?o+(s-o)*e*6:e*2<1?s:e*3<2?o+(s-o)*(2/3-e)*6:o}e=r(e)%360/360,t=r(t),n=r(n),i=r(i);var s=n<=.5?n*(t+1):n+t-n*t,o=n*2-s;return this.rgba(u(e+1/3)*255,u(e)*255,u(e-1/3)*255,i)},hsv:function(e,t,n){return this.hsva(e,t,n,1)},hsva:function(e,t,n,i){e=r(e)%360/360*360,t=r(t),n=r(n),i=r(i);var s,o;s=Math.floor(e/60%6),o=e/60-s;var u=[n,n*(1-t),n*(1-o*t),n*(1-(1-o)*t)],a=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return this.rgba(u[a[s][0]]*255,u[a[s][1]]*255,u[a[s][2]]*255,i)},hue:function(t){return new e.Dimension(Math.round(t.toHSL().h))},saturation:function(t){return new e.Dimension(Math.round(t.toHSL().s*100),"%")},lightness:function(t){return new e.Dimension(Math.round(t.toHSL().l*100),"%")},red:function(t){return new e.Dimension(t.rgb[0])},green:function(t){return new e.Dimension(t.rgb[1])},blue:function(t){return new e.Dimension(t.rgb[2])},alpha:function(t){return new e.Dimension(t.toHSL().a)},luma:function(t){return new e.Dimension(Math.round((.2126*(t.rgb[0]/255)+.7152*(t.rgb[1]/255)+.0722*(t.rgb[2]/255))*t.alpha*100),"%")},saturate:function(e,n){var r=e.toHSL();return r.s+=n.value/100,r.s=i(r.s),t(r)},desaturate:function(e,n){var r=e.toHSL();return r.s-=n.value/100,r.s=i(r.s),t(r)},lighten:function(e,n){var r=e.toHSL();return r.l+=n.value/100,r.l=i(r.l),t(r)},darken:function(e,n){var r=e.toHSL();return r.l-=n.value/100,r.l=i(r.l),t(r)},fadein:function(e,n){var r=e.toHSL();return r.a+=n.value/100,r.a=i(r.a),t(r)},fadeout:function(e,n){var r=e.toHSL();return r.a-=n.value/100,r.a=i(r.a),t(r)},fade:function(e,n){var r=e.toHSL();return r.a=n.value/100,r.a=i(r.a),t(r)},spin:function(e,n){var r=e.toHSL(),i=(r.h+n.value)%360;return r.h=i<0?360+i:i,t(r)},mix:function(t,n,r){r||(r=new e.Dimension(50));var i=r.value/100,s=i*2-1,o=t.toHSL().a-n.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[t.rgb[0]*u+n.rgb[0]*a,t.rgb[1]*u+n.rgb[1]*a,t.rgb[2]*u+n.rgb[2]*a],l=t.alpha*i+n.alpha*(1-i);return new e.Color(f,l)},greyscale:function(t){return this.desaturate(t,new e.Dimension(100))},contrast:function(e,t,n,r){return e.rgb?(typeof n=="undefined"&&(n=this.rgba(255,255,255,1)),typeof t=="undefined"&&(t=this.rgba(0,0,0,1)),typeof r=="undefined"?r=.43:r=r.value,(.2126*(e.rgb[0]/255)+.7152*(e.rgb[1]/255)+.0722*(e.rgb[2]/255))*e.alpha255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},operate:function(t,n){var r=[];n instanceof e.Color||(n=n.toColor());for(var i=0;i<3;i++)r[i]=e.operate(t,this.rgb[i],n.rgb[i]);return new e.Color(r,this.alpha+n.alpha)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t,n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},compare:function(e){return e.rgb?e.rgb[0]===this.rgb[0]&&e.rgb[1]===this.rgb[1]&&e.rgb[2]===this.rgb[2]&&e.alpha===this.alpha?0:-1:-1}}}(n("../tree")),function(e){e.Comment=function(e,t){this.value=e,this.silent=!!t},e.Comment.prototype={toCSS:function(e){return e.compress?"":this.value},eval:function(){return this}}}(n("../tree")),function(e){e.Condition=function(e,t,n,r,i){this.op=e.trim(),this.lvalue=t,this.rvalue=n,this.index=r,this.negate=i},e.Condition.prototype.eval=function(e){var t=this.lvalue.eval(e),n=this.rvalue.eval(e),r=this.index,i,i=function(e){switch(e){case"and":return t&&n;case"or":return t||n;default:if(t.compare)i=t.compare(n);else{if(!n.compare)throw{type:"Type",message:"Unable to perform comparison",index:r};i=n.compare(t)}switch(i){case-1:return e==="<"||e==="=<";case 0:return e==="="||e===">="||e==="=<";case 1:return e===">"||e===">="}}}(this.op);return this.negate?!i:i}}(n("../tree")),function(e){e.Dimension=function(e,t){this.value=parseFloat(e),this.unit=t||null},e.Dimension.prototype={eval:function(){return this},toColor:function(){return new e.Color([this.value,this.value,this.value])},toCSS:function(){var e=this.value+this.unit;return e},operate:function(t,n){return new e.Dimension(e.operate(t,this.value,n.value),this.unit||n.unit)},compare:function(t){return t instanceof e.Dimension?t.value>this.value?-1:t.value":e.compress?">":" > ","|":e.compress?"|":" | "}[this.value]}}(n("../tree")),function(e){e.Expression=function(e){this.value=e},e.Expression.prototype={eval:function(t){return this.value.length>1?new e.Expression(this.value.map(function(e){return e.eval(t)})):this.value.length===1?this.value[0].eval(t):this},toCSS:function(e){return this.value.map(function(t){return t.toCSS?t.toCSS(e):""}).join(" ")}}}(n("../tree")),function(e){e.Import=function(t,n,r,i,s,o){var u=this;this.once=i,this.index=s,this._path=t,this.features=r&&new e.Value(r),this.rootpath=o,t instanceof e.Quoted?this.path=/(\.[a-z]*$)|([\?;].*)$/.test(t.value)?t.value:t.value+".less":this.path=t.value.value||t.value,this.css=/css([\?;].*)?$/.test(this.path),this.css||n.push(this.path,function(t,n,r){t&&(t.index=s),r&&u.once&&(u.skip=r),u.root=n||new e.Ruleset([],[])})},e.Import.prototype={toCSS:function(e){var t=this.features?" "+this.features.toCSS(e):"";return this.css?(typeof this._path.value=="string"&&!/^(?:[a-z-]+:|\/)/.test(this._path.value)&&(this._path.value=this.rootpath+this._path.value),"@import "+this._path.toCSS()+t+";\n"):""},eval:function(t){var n,r=this.features&&this.features.eval(t);return this.skip?[]:this.css?this:(n=new e.Ruleset([],this.root.rules.slice(0)),n.evalImports(t),this.features?new e.Media(n.rules,this.features.value):n.rules)}}}(n("../tree")),function(e){e.JavaScript=function(e,t,n){this.escaped=n,this.expression=e,this.index=t},e.JavaScript.prototype={eval:function(t){var n,r=this,i={},s=this.expression.replace(/@\{([\w-]+)\}/g,function(n,i){return e.jsify((new e.Variable("@"+i,r.index)).eval(t))});try{s=new Function("return ("+s+")")}catch(o){throw{message:"JavaScript evaluation error: `"+s+"`",index:this.index}}for(var u in t.frames[0].variables())i[u.slice(1)]={value:t.frames[0].variables()[u].value,toJS:function(){return this.value.eval(t).toCSS()}};try{n=s.call(i)}catch(o){throw{message:"JavaScript evaluation error: '"+o.name+": "+o.message+"'",index:this.index}}return typeof n=="string"?new e.Quoted('"'+n+'"',n,this.escaped,this.index):Array.isArray(n)?new e.Anonymous(n.join(", ")):new e.Anonymous(n)}}}(n("../tree")),function(e){e.Keyword=function(e){this.value=e},e.Keyword.prototype={eval:function(){return this},toCSS:function(){return this.value},compare:function(t){return t instanceof e.Keyword?t.value===this.value?0:1:-1}},e.True=new e.Keyword("true"),e.False=new e.Keyword("false")}(n("../tree")),function(e){e.Media=function(t,n){var r=this.emptySelectors();this.features=new e.Value(n),this.ruleset=new e.Ruleset(r,t),this.ruleset.allowImports=!0},e.Media.prototype={toCSS:function(e,t){var n=this.features.toCSS(t);return this.ruleset.root=e.length===0||e[0].multiMedia,"@media "+n+(t.compress?"{":" {\n ")+this.ruleset.toCSS(e,t).trim().replace(/\n/g,"\n ")+(t.compress?"}":"\n}\n")},eval:function(t){t.mediaBlocks||(t.mediaBlocks=[],t.mediaPath=[]);var n=new e.Media([],[]);return this.debugInfo&&(this.ruleset.debugInfo=this.debugInfo,n.debugInfo=this.debugInfo),n.features=this.features.eval(t),t.mediaPath.push(n),t.mediaBlocks.push(n),t.frames.unshift(this.ruleset),n.ruleset=this.ruleset.eval(t),t.frames.shift(),t.mediaPath.pop(),t.mediaPath.length===0?n.evalTop(t):n.evalNested(t)},variable:function(t){return e.Ruleset.prototype.variable.call(this.ruleset,t)},find:function(){return e.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return e.Ruleset.prototype.rulesets.apply(this.ruleset)},emptySelectors:function(){var t=new e.Element("","&",0);return[new e.Selector([t])]},evalTop:function(t){var n=this;if(t.mediaBlocks.length>1){var r=this.emptySelectors();n=new e.Ruleset(r,t.mediaBlocks),n.multiMedia=!0}return delete t.mediaBlocks,delete t.mediaPath,n},evalNested:function(t){var n,r,i=t.mediaPath.concat([this]);for(n=0;n0;n--)t.splice(n,0,new e.Anonymous("and"));return new e.Expression(t)})),new e.Ruleset([],[])},permute:function(e){if(e.length===0)return[];if(e.length===1)return e[0];var t=[],n=this.permute(e.slice(1));for(var r=0;r0){c=!0;for(a=0;athis.params.length)return!1;if(this.required>0&&n>this.params.length)return!1}r=Math.min(n,this.arity);for(var s=0;si.selectors[o].elements.length?Array.prototype.push.apply(r,i.find(new e.Selector(t.elements.slice(1)),n)):r.push(i);break}}),this._lookups[o]=r)},toCSS:function(t,n){var r=[],i=[],s=[],o=[],u=[],a,f,l;this.root||this.joinSelectors(u,t,this.selectors);for(var c=0;c0){f=e.debugInfo(n,this),a=u.map(function(e){return e.map(function(e){return e.toCSS(n)}).join("").trim()}).join(n.compress?",":",\n");for(var c=i.length-1;c>=0;c--)s.indexOf(i[c])===-1&&s.unshift(i[c]);i=s,r.push(f+a+(n.compress?"{":" {\n ")+i.join(n.compress?"":"\n ")+(n.compress?"}":"\n}\n"))}return r.push(o),r.join("")+(n.compress?"\n":"")},joinSelectors:function(e,t,n){for(var r=0;r0)for(i=0;i0&&this.mergeElementsOnToSelectors(g,a);for(s=0;s0&&(l[0].elements=l[0].elements.slice(0),l[0].elements.push(new e.Element(f.combinator,"",0))),y.push(l);else for(o=0;o0?(h=l.slice(0),m=h.pop(),d=new e.Selector(m.elements.slice(0)),v=!1):d=new e.Selector([]),c.length>1&&(p=p.concat(c.slice(1))),c.length>0&&(v=!1,d.elements.push(new e.Element(f.combinator,c[0].elements[0].value,0)),d.elements=d.elements.concat(c[0].elements.slice(1))),v||h.push(d),h=h.concat(p),y.push(h)}a=y,g=[]}}g.length>0&&this.mergeElementsOnToSelectors(g,a);for(i=0;i0?i[i.length-1]=new e.Selector(i[i.length-1].elements.concat(t)):i.push(new e.Selector(t))}}}(n("../tree")),function(e){e.Selector=function(e){this.elements=e},e.Selector.prototype.match=function(e){var t=this.elements,n=t.length,r,i,s,o;r=e.elements.slice(e.elements.length&&e.elements[0].value==="&"?1:0),i=r.length,s=Math.min(n,i);if(i===0||n1?"["+e.value.map(function(e){return e.toCSS(!1)}).join(", ")+"]":e.toCSS(!1)}}(n("./tree"));var o=/^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol);r.env=r.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||o?"development":"production"),r.async=r.async||!1,r.fileAsync=r.fileAsync||!1,r.poll=r.poll||(o?1e3:1500);if(r.functions)for(var u in r.functions)r.tree.functions[u]=r.functions[u];var a=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);a&&(r.dumpLineNumbers=a[1]),r.watch=function(){return r.watchMode||(r.env="development",f()),this.watchMode=!0},r.unwatch=function(){return clearInterval(r.watchTimer),this.watchMode=!1},/!watch/.test(location.hash)&&r.watch();var l=null;if(r.env!="development")try{l=typeof e.localStorage=="undefined"?null:e.localStorage}catch(c){}var h=document.getElementsByTagName("link"),p=/^text\/(x-)?less$/;r.sheets=[];for(var d=0;d - @client = new DropboxClient options - - # NOTE: this is not yet implemented. diff --git a/lib/client/storage/dropbox/src/api_error.coffee b/lib/client/storage/dropbox/src/api_error.coffee deleted file mode 100644 index 26217b6d..00000000 --- a/lib/client/storage/dropbox/src/api_error.coffee +++ /dev/null @@ -1,59 +0,0 @@ -# Information about a failed call to the Dropbox API. -class Dropbox.ApiError - # @property {Number} the HTTP error code (e.g., 403) - status: undefined - - # @property {String} the HTTP method of the failed request (e.g., 'GET') - method: undefined - - # @property {String} the URL of the failed request - url: undefined - - # @property {?String} the body of the HTTP error response; can be null if - # the error was caused by a network failure or by a security issue - responseText: undefined - - # @property {?Object} the result of parsing the JSON in the HTTP error - # response; can be null if the API server didn't return JSON, or if the - # HTTP response body is unavailable - response: undefined - - # Wraps a failed XHR call to the Dropbox API. - # - # @param {String} method the HTTP verb of the API request (e.g., 'GET') - # @param {String} url the URL of the API request - # @param {XMLHttpRequest} xhr the XMLHttpRequest instance of the failed - # request - constructor: (xhr, @method, @url) -> - @status = xhr.status - if xhr.responseType - try - text = xhr.response or xhr.responseText - catch e - try - text = xhr.responseText - catch e - text = null - else - try - text = xhr.responseText - catch e - text = null - - if text - try - @responseText = text.toString() - @response = JSON.parse text - catch e - @response = null - else - @responseText = '(no response)' - @response = null - - # Used when the error is printed out by developers. - toString: -> - "Dropbox API error #{@status} from #{@method} #{@url} :: #{@responseText}" - - # Used by some testing frameworks. - inspect: -> - @toString() diff --git a/lib/client/storage/dropbox/src/base64.coffee b/lib/client/storage/dropbox/src/base64.coffee deleted file mode 100644 index fa165d3a..00000000 --- a/lib/client/storage/dropbox/src/base64.coffee +++ /dev/null @@ -1,72 +0,0 @@ -# node.js implementation of atob and btoa - -if window? - if window.atob and window.btoa - atob = (string) -> window.atob string - btoa = (base64) -> window.btoa base64 - else - # IE < 10 doesn't implement the standard atob / btoa functions. - base64Digits = - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' - - btoaNibble = (accumulator, bytes, result) -> - 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 - null - atobNibble = (accumulator, digits, result) -> - limit = 4 - digits - accumulator <<= limit * 6 - i = 2 - while i >= limit - result.push String.fromCharCode((accumulator >> (8 * i)) & 0xFF) - i -= 1 - null - - btoa = (string) -> - result = [] - accumulator = 0 - bytes = 0 - for i in [0...string.length] - accumulator = (accumulator << 8) | string.charCodeAt(i) - bytes += 1 - if bytes is 3 - btoaNibble accumulator, bytes, result - accumulator = bytes = 0 - - if bytes > 0 - btoaNibble accumulator, bytes, result - result.join '' - - atob = (base64) -> - result = [] - accumulator = 0 - digits = 0 - for i in [0...base64.length] - digit = base64.charAt i - break if digit is '=' - accumulator = (accumulator << 6) | base64Digits.indexOf(digit) - digits += 1 - if digits is 4 - atobNibble accumulator, digits, result - accumulator = digits = 0 - - if digits > 0 - atobNibble accumulator, digits, result - result.join '' - -else - # NOTE: the npm packages atob and btoa don't do base64-encoding correctly. - atob = (arg) -> - buffer = new Buffer arg, 'base64' - (String.fromCharCode(buffer[i]) for i in [0...buffer.length]).join '' - btoa = (arg) -> - buffer = new Buffer(arg.charCodeAt(i) for i in [0...arg.length]) - buffer.toString 'base64' diff --git a/lib/client/storage/dropbox/src/client.coffee b/lib/client/storage/dropbox/src/client.coffee deleted file mode 100644 index abbd3810..00000000 --- a/lib/client/storage/dropbox/src/client.coffee +++ /dev/null @@ -1,1270 +0,0 @@ -# Represents a user accessing the application. -class Dropbox.Client - # Dropbox client representing an application. - # - # For an optimal user experience, applications should use a single client for - # all Dropbox interactions. - # - # @param {Object} options the application type and API key - # @option options {Boolean} sandbox true for applications that request - # sandbox access (access to a single folder exclusive to the app) - # @option options {String} key the Dropbox application's key; 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; - # browser-side applications should not use the secret option; instead, - # they should pass the result of Dropbox.encodeKey as the key option - # @option options {String} token if set, the user's access token - # @option options {String} tokenSecret if set, the secret for the user's - # access token - # @option options {String} uid if set, the user's Dropbox UID - # @option options {Number} authState if set, indicates that the token and - # tokenSecret are in an intermediate state in the authentication process; - # this option should never be set by hand, however it may be returned by - # calls to credentials() - constructor: (options) -> - @sandbox = options.sandbox or false - @apiServer = options.server or @defaultApiServer() - @authServer = options.authServer or @defaultAuthServer() - @fileServer = options.fileServer or @defaultFileServer() - @downloadServer = options.downloadServer or @defaultDownloadServer() - - @onXhr = new Dropbox.EventSource cancelable: true - @onError = new Dropbox.EventSource - @onAuthStateChange = new Dropbox.EventSource - - @oauth = new Dropbox.Oauth options - @driver = null - @filter = null - @uid = null - @authState = null - @authError = null - @_credentials = null - @setCredentials options - - @setupUrls() - - # Plugs in the OAuth / application integration code. - # - # @param {DropboxAuthDriver} driver provides the integration between the - # application and the Dropbox OAuth flow; most applications should be - # able to use instances of Dropbox.Driver.Redirect, Dropbox.Driver.Popup, - # or Dropbox.Driver.NodeServer - # @return {Dropbox.Client} this, for easy call chaining - authDriver: (driver) -> - @driver = driver - @ - - # @property {Dropbox.EventSource} cancelable event fired every - # time when a network request to the Dropbox API server is about to be - # sent; if the event is canceled by returning a falsey value from a - # listener, the network request is silently discarded; whenever possible, - # listeners should restrict themselves to using the xhr property of the - # Dropbox.Xhr instance passed to them; everything else in the Dropbox.Xhr - # API is in flux - onXhr: null - - # @property {Dropbox.EventSource} non-cancelable event - # fired every time when a network request to the Dropbox API server results - # in an error - onError: null - - # @property {Dropbox.EventSource} non-cancelable event fired - # every time the authState property changes; this can be used to update UI - # state - onAuthStateChange: null - - # The authenticated user's Dropbx user ID. - # - # This user ID is guaranteed to be consistent across API calls from the same - # application (not across applications, though). - # - # @return {?String} a short ID that identifies the user, or null if no user - # is authenticated - dropboxUid: -> - @uid - - # Get the client's OAuth credentials. - # - # @param {?Object} the result of a prior call to credentials() - # @return {Object} a plain object whose properties can be passed to the - # Dropbox.Client constructor to reuse this client's login credentials - credentials: () -> - @computeCredentials() unless @_credentials - @_credentials - - # Authenticates the app's user to Dropbox' API server. - # - # @param {function(?Dropbox.ApiError, ?Dropbox.Client)} callback called when - # the authentication completes; if successful, the second parameter is - # this client and the first parameter is null - # @return {Dropbox.Client} this, for easy call chaining - authenticate: (callback) -> - oldAuthState = null - - unless @driver or @authState is DropboxClient.DONE - throw new Error "Call authDriver to set an authentication driver" - - # Advances the authentication FSM by one step. - _fsmStep = => - if oldAuthState isnt @authState - if oldAuthState isnt null - @onAuthStateChange.dispatch @ - oldAuthState = @authState - if @driver and @driver.onAuthStateChange - return @driver.onAuthStateChange(@, _fsmStep) - - switch @authState - when DropboxClient.RESET # No user credentials -> request token. - @requestToken (error, data) => - if error - @authError = error - @authState = DropboxClient.ERROR - else - token = data.oauth_token - tokenSecret = data.oauth_token_secret - @oauth.setToken token, tokenSecret - @authState = DropboxClient.REQUEST - @_credentials = null - _fsmStep() - - when DropboxClient.REQUEST # Have request token, get it authorized. - authUrl = @authorizeUrl @oauth.token - @driver.doAuthorize authUrl, @oauth.token, @oauth.tokenSecret, => - @authState = DropboxClient.AUTHORIZED - @_credentials = null - _fsmStep() - - when DropboxClient.AUTHORIZED - # Request token authorized, switch it for an access token. - @getAccessToken (error, data) => - if error - @authError = error - @authState = DropboxClient.ERROR - else - @oauth.setToken data.oauth_token, data.oauth_token_secret - @uid = data.uid - @authState = DropboxClient.DONE - @_credentials = null - _fsmStep() - - when DropboxClient.DONE # We have an access token. - callback null, @ - - when DropboxClient.SIGNED_OFF # The user signed off, restart the flow. - # The authState change makes reset() not trigger onAuthStateChange. - @authState = DropboxClient.RESET - @reset() - _fsmStep() - - when DropboxClient.ERROR # An error occurred during authentication. - callback @authError - - _fsmStep() # Start up the state machine. - @ - - # @return {Boolean} true if this client is authenticated, false otherwise - isAuthenticated: -> - @authState is DropboxClient.DONE - - # Revokes the user's Dropbox credentials. - # - # This should be called when the user explictly signs off from your - # application, to meet the users' expectation that after they sign off, their - # access tokens will be persisted on the machine. - # - # @param {function(?Dropbox.ApiError)} callback called when - # the authentication completes; if successful, the error parameter is - # null - # @return {XMLHttpRequest} the XHR object used for this API call - signOut: (callback) -> - xhr = new Dropbox.Xhr 'POST', @urls.signOut - xhr.signWithOauth @oauth - @dispatchXhr xhr, (error) => - return callback(error) if error - - # The authState change makes reset() not trigger onAuthStateChange. - @authState = DropboxClient.RESET - @reset() - @authState = DropboxClient.SIGNED_OFF - @onAuthStateChange.dispatch @ - if @driver.onAuthStateChange - @driver.onAuthStateChange @, -> - callback error - else - callback error - - # Alias for signOut. - signOff: (callback) -> - @signOut callback - - # Retrieves information about the logged in user. - # - # @param {?Object} options the advanced settings below; for the default - # settings, skip the argument or pass null - # @option options {Boolean} httpCache if true, the API request will be set to - # allow HTTP caching to work; by default, requests are set up to avoid - # CORS preflights; setting this option can make sense when making the same - # request repeatedly (polling?) - # @param {function(?Dropbox.ApiError, ?Dropbox.UserInfo, ?Object)} callback - # called with the result of the /account/info HTTP request; if the call - # succeeds, the second parameter is a Dropbox.UserInfo instance, the - # third parameter is the parsed JSON data behind the Dropbox.UserInfo - # instance, and the first parameter is null - # @return {XMLHttpRequest} the XHR object used for this API call - getUserInfo: (options, callback) -> - if (not callback) and (typeof options is 'function') - callback = options - options = null - - httpCache = false - if options and options.httpCache - httpCache = true - - xhr = new Dropbox.Xhr 'GET', @urls.accountInfo - xhr.signWithOauth @oauth, httpCache - @dispatchXhr xhr, (error, userData) -> - callback error, Dropbox.UserInfo.parse(userData), userData - - # Retrieves the contents of a file stored in Dropbox. - # - # Some options are silently ignored in Internet Explorer 9 and below, due to - # insufficient support in its proprietary XDomainRequest replacement for XHR. - # Currently, the options are: arrayBuffer, blob, length, start. - # - # @param {String} path the path of the file to be read, relative to the - # user's Dropbox or to the application's folder - # @param {?Object} options the advanced settings below; for the default - # settings, skip the argument or pass null - # @option options {String} versionTag the tag string for the desired version - # of the file contents; the most recent version is retrieved by default - # @option options {String} rev alias for "versionTag" that matches the HTTP - # API - # @option options {Boolean} arrayBuffer if true, the file's contents will be - # passed to the callback in an ArrayBuffer; this is the recommended method - # of reading non-UTF8 data such as images, as it is well supported across - # modern browsers; requires XHR Level 2 support, which is not available in - # IE <= 9 - # @option options {Boolean} blob if true, the file's contents will be - # passed to the callback in a Blob; this is a good method of reading - # non-UTF8 data, such as images; requires XHR Level 2 support, which is not - # available in IE <= 9 - # @option options {Boolean} binary if true, the file will be retrieved as a - # binary string; the default is an UTF-8 encoded string; this relies on - # hacks and should not be used if the environment supports XHR Level 2 API - # @option options {Number} length the number of bytes to be retrieved from - # the file; if the start option is not present, the last "length" bytes - # will be read (after issue #30 is closed); by default, the entire file is - # read - # @option options {Number} start the 0-based offset of the first byte to be - # retrieved; if the length option is not present, the bytes between - # "start" and the file's end will be read; by default, the entire - # file is read - # @option options {Boolean} httpCache if true, the API request will be set to - # allow HTTP caching to work; by default, requests are set up to avoid - # CORS preflights; setting this option can make sense when making the same - # request repeatedly (polling?) - # @param {function(?Dropbox.ApiError, ?String, ?Dropbox.Stat)} callback - # called with the result of the /files (GET) HTTP request; the second - # parameter is the contents of the file, the third parameter is a - # Dropbox.Stat instance describing the file, and the first parameter is - # null - # @return {XMLHttpRequest} the XHR object used for this API call - readFile: (path, options, callback) -> - if (not callback) and (typeof options is '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' # See the Dropbox.Xhr.request2 docs - - if options.length - if options.start? - rangeStart = options.start - rangeEnd = options.start + options.length - 1 - else - rangeStart = '' - rangeEnd = options.length - rangeHeader = "bytes=#{rangeStart}-#{rangeEnd}" - else if options.start? - rangeHeader = "bytes=#{options.start}-" - - httpCache = true if options.httpCache - - xhr = new Dropbox.Xhr 'GET', "#{@urls.getFile}/#{@urlEncodePath(path)}" - xhr.setParams(params).signWithOauth(@oauth, httpCache) - xhr.setResponseType(responseType) - xhr.setHeader 'Range', rangeHeader if rangeHeader - @dispatchXhr xhr, (error, data, metadata) -> - callback error, data, Dropbox.Stat.parse(metadata) - - # Store a file into a user's Dropbox. - # - # @param {String} path the path of the file to be created, relative to the - # user's Dropbox or to the application's folder - # @param {String, ArrayBuffer, ArrayBufferView, Blob, File} data the contents - # written to the file; if a File is passed, its name is ignored - # @param {?Object} options the advanced settings below; for the default - # settings, skip the argument or pass null - # @option options {String} lastVersionTag the identifier string for the - # version of the file's contents that was last read by this program, used - # for conflict resolution; for best results, use the versionTag attribute - # value from the Dropbox.Stat instance provided by readFile - # @option options {String} parentRev alias for "lastVersionTag" that matches - # the HTTP API - # @option options {Boolean} noOverwrite if set, the write will not overwrite - # a file with the same name that already exsits; instead the contents - # will be written to a similarly named file (e.g. "notes (1).txt" - # instead of "notes.txt") - # @param {function(?Dropbox.ApiError, ?Dropbox.Stat)} callback called with - # the result of the /files (POST) HTTP request; the second paramter is a - # Dropbox.Stat instance describing the newly created file, and the first - # parameter is null - # @return {XMLHttpRequest} the XHR object used for this API call - writeFile: (path, data, options, callback) -> - if (not callback) and (typeof options is 'function') - callback = options - options = null - - useForm = Dropbox.Xhr.canSendForms and typeof data is 'object' - if useForm - @writeFileUsingForm path, data, options, callback - else - @writeFileUsingPut path, data, options, callback - - # writeFile implementation that uses the POST /files API. - # - # @private - # This method is more demanding in terms of CPU and browser support, but does - # not require CORS preflight, so it always completes in 1 HTTP request. - writeFileUsingForm: (path, data, options, callback) -> - # Break down the path into a file/folder name and the containing folder. - slashIndex = path.lastIndexOf '/' - if slashIndex is -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 or options.parent_rev - params.parent_rev = options.parentRev or options.parent_rev - # TODO: locale support would edit the params here - - xhr = new Dropbox.Xhr 'POST', "#{@urls.postFile}/#{@urlEncodePath(path)}" - xhr.setParams(params).signWithOauth(@oauth).setFileField('file', fileName, - data, 'application/octet-stream') - - # NOTE: the Dropbox API docs ask us to replace the 'file' parameter after - # signing the request; the hack below works as intended - delete params.file - - @dispatchXhr xhr, (error, metadata) -> - callback error, Dropbox.Stat.parse(metadata) - - # writeFile implementation that uses the /files_put API. - # - # @private - # This method is less demanding on CPU, and makes fewer assumptions about - # browser support, but it takes 2 HTTP requests for binary files, because it - # needs CORS preflight. - writeFileUsingPut: (path, data, options, callback) -> - params = {} - if options - if options.noOverwrite - params.overwrite = 'false' - if options.lastVersionTag - params.parent_rev = options.lastVersionTag - else if options.parentRev or options.parent_rev - params.parent_rev = options.parentRev or options.parent_rev - # TODO: locale support would edit the params here - xhr = new Dropbox.Xhr 'POST', "#{@urls.putFile}/#{@urlEncodePath(path)}" - xhr.setBody(data).setParams(params).signWithOauth(@oauth) - @dispatchXhr xhr, (error, metadata) -> - callback error, Dropbox.Stat.parse(metadata) - - # Atomic step in a resumable file upload. - # - # @param {String, ArrayBuffer, ArrayBufferView, Blob, File} data the file - # contents fragment to be uploaded; if a File is passed, its name is - # ignored - # @param {?Dropbox.UploadCursor} cursor the cursor that tracks the state of - # the resumable file upload; the cursor information will not be updated - # when the API call completes - # @param {function(?Dropbox.ApiError, ?Dropbox.UploadCursor)} callback called - # with the result of the /chunked_upload HTTP request; the second paramter - # is a Dropbox.UploadCursor instance describing the progress of the upload - # operation, and the first parameter is null if things go well - # @return {XMLHttpRequest} the XHR object used for this API call - resumableUploadStep: (data, cursor, callback) -> - if cursor - params = { offset: cursor.offset } - params.upload_id = cursor.tag if cursor.tag - else - params = { offset: 0 } - - xhr = new Dropbox.Xhr 'POST', @urls.chunkedUpload - xhr.setBody(data).setParams(params).signWithOauth(@oauth) - @dispatchXhr xhr, (error, cursor) -> - if error and error.status is 400 and - error.response.upload_id and error.response.offset - callback null, Dropbox.UploadCursor.parse(error.response) - else - callback error, Dropbox.UploadCursor.parse(cursor) - - # Finishes a resumable file upload. - # - # @param {String} path the path of the file to be created, relative to the - # user's Dropbox or to the application's folder - # @param {?Object} options the advanced settings below; for the default - # settings, skip the argument or pass null - # @option options {String} lastVersionTag the identifier string for the - # version of the file's contents that was last read by this program, used - # for conflict resolution; for best results, use the versionTag attribute - # value from the Dropbox.Stat instance provided by readFile - # @option options {String} parentRev alias for "lastVersionTag" that matches - # the HTTP API - # @option options {Boolean} noOverwrite if set, the write will not overwrite - # a file with the same name that already exsits; instead the contents - # will be written to a similarly named file (e.g. "notes (1).txt" - # instead of "notes.txt") - # @param {function(?Dropbox.ApiError, ?Dropbox.Stat)} callback called with - # the result of the /files (POST) HTTP request; the second paramter is a - # Dropbox.Stat instance describing the newly created file, and the first - # parameter is null - # @return {XMLHttpRequest} the XHR object used for this API call - resumableUploadFinish: (path, cursor, options, callback) -> - if (not callback) and (typeof options is 'function') - callback = options - options = null - - params = { upload_id: cursor.tag } - - if options - if options.lastVersionTag - params.parent_rev = options.lastVersionTag - else if options.parentRev or options.parent_rev - params.parent_rev = options.parentRev or options.parent_rev - if options.noOverwrite - params.autorename = true - - # TODO: locale support would edit the params here - xhr = new Dropbox.Xhr 'POST', - "#{@urls.commitChunkedUpload}/#{@urlEncodePath(path)}" - xhr.setParams(params).signWithOauth(@oauth) - @dispatchXhr xhr, (error, metadata) -> - callback error, Dropbox.Stat.parse(metadata) - - # Reads the metadata of a file or folder in a user's Dropbox. - # - # @param {String} path the path to the file or folder whose metadata will be - # read, relative to the user's Dropbox or to the application's folder - # @param {?Object} options the advanced settings below; for the default - # settings, skip the argument or pass null - # @option options {Number} version if set, the call will return the metadata - # for the given revision of the file / folder; the latest version is used - # by default - # @option options {Boolean} removed if set to true, the results will include - # files and folders that were deleted from the user's Dropbox - # @option options {Boolean} deleted alias for "removed" that matches the HTTP - # API; using this alias is not recommended, because it may cause confusion - # with JavaScript's delete operation - # @option options {Boolean, Number} readDir only meaningful when stat-ing - # folders; if this is set, the API call will also retrieve the folder's - # contents, which is passed into the callback's third parameter; if this - # is a number, it specifies the maximum number of files and folders that - # should be returned; the default limit is 10,000 items; if the limit is - # exceeded, the call will fail with an error - # @option options {String} versionTag used for saving bandwidth when getting - # a folder's contents; if this value is specified and it matches the - # folder's contents, the call will fail with a 304 (Contents not changed) - # error code; a folder's version identifier can be obtained from the - # versionTag attribute of a Dropbox.Stat instance describing it - # @option options {Boolean} httpCache if true, the API request will be set to - # allow HTTP caching to work; by default, requests are set up to avoid - # CORS preflights; setting this option can make sense when making the same - # request repeatedly (polling?) - # @param {function(?Dropbox.ApiError, ?Dropbox.Stat, ?Array)} - # callback called with the result of the /metadata HTTP request; if the - # call succeeds, the second parameter is a Dropbox.Stat instance - # describing the file / folder, and the first parameter is null; - # if the readDir option is true and the call succeeds, the third - # parameter is an array of Dropbox.Stat instances describing the folder's - # entries - # @return {XMLHttpRequest} the XHR object used for this API call - stat: (path, options, callback) -> - if (not callback) and (typeof options is 'function') - callback = options - options = null - - params = {} - httpCache = false - if options - if options.version? - params.rev = options.version - if options.removed or options.deleted - params.include_deleted = 'true' - if options.readDir - params.list = 'true' - if options.readDir isnt true - params.file_limit = options.readDir.toString() - if options.cacheHash - params.hash = options.cacheHash - if options.httpCache - httpCache = true - params.include_deleted ||= 'false' - params.list ||= 'false' - # TODO: locale support would edit the params here - xhr = new Dropbox.Xhr 'GET', "#{@urls.metadata}/#{@urlEncodePath(path)}" - xhr.setParams(params).signWithOauth @oauth, httpCache - @dispatchXhr xhr, (error, metadata) -> - stat = Dropbox.Stat.parse metadata - if metadata?.contents - entries = (Dropbox.Stat.parse(entry) for entry in metadata.contents) - else - entries = undefined - callback error, stat, entries - - # Lists the files and folders inside a folder in a user's Dropbox. - # - # @param {String} path the path to the folder whose contents will be - # retrieved, relative to the user's Dropbox or to the application's - # folder - # @param {?Object} options the advanced settings below; for the default - # settings, skip the argument or pass null - # @option options {Boolean} removed if set to true, the results will include - # files and folders that were deleted from the user's Dropbox - # @option options {Boolean} deleted alias for "removed" that matches the HTTP - # API; using this alias is not recommended, because it may cause confusion - # with JavaScript's delete operation - # @option options {Boolean, Number} limit the maximum number of files and - # folders that should be returned; the default limit is 10,000 items; if - # the limit is exceeded, the call will fail with an error - # @option options {String} versionTag used for saving bandwidth; if this - # option is specified, and its value matches the folder's version tag, - # the call will fail with a 304 (Contents not changed) error code - # instead of returning the contents; a folder's version identifier can be - # obtained from the versionTag attribute of a Dropbox.Stat instance - # describing it - # @option options {Boolean} httpCache if true, the API request will be set to - # allow HTTP caching to work; by default, requests are set up to avoid - # CORS preflights; setting this option can make sense when making the same - # request repeatedly (polling?) - # @param {function(?Dropbox.ApiError, ?Array, ?Dropbox.Stat, - # ?Array)} callback called with the result of the /metadata - # HTTP request; if the call succeeds, the second parameter is an array - # containing the names of the files and folders in the given folder, the - # third parameter is a Dropbox.Stat instance describing the folder, the - # fourth parameter is an array of Dropbox.Stat instances describing the - # folder's entries, and the first parameter is null - # @return {XMLHttpRequest} the XHR object used for this API call - readdir: (path, options, callback) -> - if (not callback) and (typeof options is 'function') - callback = options - options = null - - statOptions = { readDir: true } - if options - if options.limit? - statOptions.readDir = options.limit - if options.versionTag - statOptions.versionTag = options.versionTag - if options.removed or options.deleted - statOptions.removed = options.removed or options.deleted - if options.httpCache - statOptions.httpCache = options.httpCache - @stat path, statOptions, (error, stat, entry_stats) -> - if entry_stats - entries = (entry_stat.name for entry_stat in entry_stats) - else - entries = null - callback error, entries, stat, entry_stats - - # Alias for "stat" that matches the HTTP API. - metadata: (path, options, callback) -> - @stat path, options, callback - - # Creates a publicly readable URL to a file or folder in the user's Dropbox. - # - # @param {String} path the path to the file or folder that will be linked to; - # the path is relative to the user's Dropbox or to the application's - # folder - # @param {?Object} options the advanced settings below; for the default - # settings, skip the argument or pass null - # @option options {Boolean} download if set, the URL will be a direct - # download URL, instead of the usual Dropbox preview URLs; direct - # download URLs are short-lived (currently 4 hours), whereas regular URLs - # virtually have no expiration date (currently set to 2030); no direct - # download URLs can be generated for directories - # @option options {Boolean} downloadHack if set, a long-living download URL - # will be generated by asking for a preview URL and using the officially - # documented hack at https://www.dropbox.com/help/201 to turn the preview - # URL into a download URL - # @option options {Boolean} long if set, the URL will not be shortened using - # Dropbox's shortner; the download and downloadHack options imply long - # @option options {Boolean} longUrl synonym for long; makes life easy for - # RhinoJS users - # @param {function(?Dropbox.ApiError, ?Dropbox.PublicUrl)} callback called - # with the result of the /shares or /media HTTP request; if the call - # succeeds, the second parameter is a Dropbox.PublicUrl instance, and the - # first parameter is null - # @return {XMLHttpRequest} the XHR object used for this API call - makeUrl: (path, options, callback) -> - if (not callback) and (typeof options is 'function') - callback = options - options = null - - # NOTE: cannot use options.long; normally, the CoffeeScript compiler - # escapes keywords for us; although long isn't really a keyword, the - # Rhino VM thinks it is; this hack can be removed when the bug below - # is fixed: - # https://github.com/mozilla/rhino/issues/93 - if options and (options['long'] or options.longUrl or options.downloadHack) - params = { short_url: 'false' } - else - params = {} - - path = @urlEncodePath path - url = "#{@urls.shares}/#{path}" - isDirect = false - useDownloadHack = false - if options - if options.downloadHack - isDirect = true - useDownloadHack = true - else if options.download - isDirect = true - url = "#{@urls.media}/#{path}" - - # TODO: locale support would edit the params here - xhr = new Dropbox.Xhr('POST', url).setParams(params).signWithOauth(@oauth) - @dispatchXhr xhr, (error, urlData) -> - if useDownloadHack and urlData and urlData.url - urlData.url = urlData.url.replace(@authServer, @downloadServer) - callback error, Dropbox.PublicUrl.parse(urlData, isDirect) - - # Retrieves the revision history of a file in a user's Dropbox. - # - # @param {String} path the path to the file whose revision history will be - # retrieved, relative to the user's Dropbox or to the application's - # folder - # @param {?Object} options the advanced settings below; for the default - # settings, skip the argument or pass null - # @option options {Number} limit if specified, the call will return at most - # this many versions - # @option options {Boolean} httpCache if true, the API request will be set to - # allow HTTP caching to work; by default, requests are set up to avoid - # CORS preflights; setting this option can make sense when making the same - # request repeatedly (polling?) - # @param {function(?Dropbox.ApiError, ?Array)} callback called - # with the result of the /revisions HTTP request; if the call succeeds, - # the second parameter is an array with one Dropbox.Stat instance per - # file version, and the first parameter is null - # @return {XMLHttpRequest} the XHR object used for this API call - history: (path, options, callback) -> - if (not callback) and (typeof options is 'function') - callback = options - options = null - - params = {} - httpCache = false - if options - if options.limit? - params.rev_limit = options.limit - if options.httpCache - httpCache = true - - xhr = new Dropbox.Xhr 'GET', "#{@urls.revisions}/#{@urlEncodePath(path)}" - xhr.setParams(params).signWithOauth @oauth, httpCache - @dispatchXhr xhr, (error, versions) -> - if versions - stats = (Dropbox.Stat.parse(metadata) for metadata in versions) - else - stats = undefined - callback error, stats - - # Alias for "history" that matches the HTTP API. - revisions: (path, options, callback) -> - @history path, options, callback - - # Computes a URL that generates a thumbnail for a file in the user's Dropbox. - # - # @param {String} path the path to the file whose thumbnail image URL will be - # computed, relative to the user's Dropbox or to the application's - # folder - # @param {?Object} options the advanced settings below; for the default - # settings, skip the argument or pass null - # @option options {Boolean} png if true, the thumbnail's image will be a PNG - # file; the default thumbnail format is JPEG - # @option options {String} format value that gets passed directly to the API; - # this is intended for newly added formats that the API may not support; - # use options such as "png" when applicable - # @option options {String} sizeCode specifies the image's dimensions; this - # gets passed directly to the API; currently, the following values are - # supported: 'small' (32x32), 'medium' (64x64), 'large' (128x128), - # 's' (64x64), 'm' (128x128), 'l' (640x480), 'xl' (1024x768); the default - # value is "small" - # @return {String} a URL to an image that can be used as the thumbnail for - # the given file - thumbnailUrl: (path, options) -> - xhr = @thumbnailXhr path, options - xhr.paramsToUrl().url - - # Retrieves the image data of a thumbnail for a file in the user's Dropbox. - # - # This method is intended to be used with low-level painting APIs. Whenever - # possible, it is easier to place the result of thumbnailUrl in a DOM - # element, and rely on the browser to fetch the file. - # - # @param {String} path the path to the file whose thumbnail image URL will be - # computed, relative to the user's Dropbox or to the application's - # folder - # @param {?Object} options the advanced settings below; for the default - # settings, skip the argument or pass null - # @option options {Boolean} png if true, the thumbnail's image will be a PNG - # file; the default thumbnail format is JPEG - # @option options {String} format value that gets passed directly to the API; - # this is intended for newly added formats that the API may not support; - # use options such as "png" when applicable - # @option options {String} sizeCode specifies the image's dimensions; this - # gets passed directly to the API; currently, the following values are - # supported: 'small' (32x32), 'medium' (64x64), 'large' (128x128), - # 's' (64x64), 'm' (128x128), 'l' (640x480), 'xl' (1024x768); the default - # value is "small" - # @option options {Boolean} blob if true, the file will be retrieved as a - # Blob, instead of a String; this requires XHR Level 2 support, which is - # not available in IE <= 9 - # @param {function(?Dropbox.ApiError, ?Object, ?Dropbox.Stat)} callback - # called with the result of the /thumbnails HTTP request; if the call - # succeeds, the second parameter is the image data as a String or Blob, - # the third parameter is a Dropbox.Stat instance describing the - # thumbnailed file, and the first argument is null - # @return {XMLHttpRequest} the XHR object used for this API call - readThumbnail: (path, options, callback) -> - if (not callback) and (typeof options is 'function') - callback = options - options = null - - responseType = 'b' - if options - responseType = 'blob' if options.blob - - xhr = @thumbnailXhr path, options - xhr.setResponseType responseType - @dispatchXhr xhr, (error, data, metadata) -> - callback error, data, Dropbox.Stat.parse(metadata) - - # Sets up an XHR for reading a thumbnail for a file in the user's Dropbox. - # - # @see Dropbox.Client#thumbnailUrl - # @return {Dropbox.Xhr} an XHR request configured for fetching the thumbnail - thumbnailXhr: (path, options) -> - params = {} - if options - if options.format - params.format = options.format - else if options.png - params.format = 'png' - if options.size - # Can we do something nicer here? - params.size = options.size - - xhr = new Dropbox.Xhr 'GET', "#{@urls.thumbnails}/#{@urlEncodePath(path)}" - xhr.setParams(params).signWithOauth(@oauth) - - # Reverts a file's contents to a previous version. - # - # This is an atomic, bandwidth-optimized equivalent of reading the file - # contents at the given file version (readFile), and then using it to - # overwrite the file (writeFile). - # - # @param {String} path the path to the file whose contents will be reverted - # to a previous version, relative to the user's Dropbox or to the - # application's folder - # @param {String} versionTag the tag of the version that the file will be - # reverted to; maps to the "rev" parameter in the HTTP API - # @param {function(?Dropbox.ApiError, ?Dropbox.Stat)} callback called with - # the result of the /restore HTTP request; if the call succeeds, the - # second parameter is a Dropbox.Stat instance describing the file after - # the revert operation, and the first parameter is null - # @return {XMLHttpRequest} the XHR object used for this API call - revertFile: (path, versionTag, callback) -> - xhr = new Dropbox.Xhr 'POST', "#{@urls.restore}/#{@urlEncodePath(path)}" - xhr.setParams(rev: versionTag).signWithOauth @oauth - @dispatchXhr xhr, (error, metadata) -> - callback error, Dropbox.Stat.parse(metadata) - - # Alias for "revertFile" that matches the HTTP API. - restore: (path, versionTag, callback) -> - @revertFile path, versionTag, callback - - # Finds files / folders whose name match a pattern, in the user's Dropbox. - # - # @param {String} path the path to the file whose contents will be reverted - # to a previous version, relative to the user's Dropbox or to the - # application's folder - # @param {String} namePattern the string that file / folder names must - # contain in order to match the search criteria; - # @param {?Object} options the advanced settings below; for the default - # settings, skip the argument or pass null - # @option options {Number} limit if specified, the call will return at most - # this many versions - # @option options {Boolean} removed if set to true, the results will include - # files and folders that were deleted from the user's Dropbox; the default - # limit is the maximum value of 1,000 - # @option options {Boolean} deleted alias for "removed" that matches the HTTP - # API; using this alias is not recommended, because it may cause confusion - # with JavaScript's delete operation - # @option options {Boolean} httpCache if true, the API request will be set to - # allow HTTP caching to work; by default, requests are set up to avoid - # CORS preflights; setting this option can make sense when making the same - # request repeatedly (polling?) - # @param {function(?Dropbox.ApiError, ?Array)} callback called - # with the result of the /search HTTP request; if the call succeeds, the - # second parameter is an array with one Dropbox.Stat instance per search - # result, and the first parameter is null - # @return {XMLHttpRequest} the XHR object used for this API call - findByName: (path, namePattern, options, callback) -> - if (not callback) and (typeof options is 'function') - callback = options - options = null - - params = { query: namePattern } - httpCache = false - if options - if options.limit? - params.file_limit = options.limit - if options.removed or options.deleted - params.include_deleted = true - if options.httpCache - httpCache = true - - xhr = new Dropbox.Xhr 'GET', "#{@urls.search}/#{@urlEncodePath(path)}" - xhr.setParams(params).signWithOauth @oauth, httpCache - @dispatchXhr xhr, (error, results) -> - if results - stats = (Dropbox.Stat.parse(metadata) for metadata in results) - else - stats = undefined - callback error, stats - - # Alias for "findByName" that matches the HTTP API. - search: (path, namePattern, options, callback) -> - @findByName path, namePattern, options, callback - - # Creates a reference used to copy a file to another user's Dropbox. - # - # @param {String} path the path to the file whose contents will be - # referenced, relative to the uesr's Dropbox or to the application's - # folder - # @param {function(?Dropbox.ApiError, ?Dropbox.CopyReference)} callback - # called with the result of the /copy_ref HTTP request; if the call - # succeeds, the second parameter is a Dropbox.CopyReference instance, and - # the first parameter is null - # @return {XMLHttpRequest} the XHR object used for this API call - makeCopyReference: (path, callback) -> - xhr = new Dropbox.Xhr 'GET', "#{@urls.copyRef}/#{@urlEncodePath(path)}" - xhr.signWithOauth @oauth - @dispatchXhr xhr, (error, refData) -> - callback error, Dropbox.CopyReference.parse(refData) - - # Alias for "makeCopyReference" that matches the HTTP API. - copyRef: (path, callback) -> - @makeCopyReference path, callback - - # Fetches a list of changes in the user's Dropbox since the last call. - # - # This method is intended to make full sync implementations easier and more - # performant. Each call returns a cursor that can be used in a future call - # to obtain all the changes that happened in the user's Dropbox (or - # application directory) between the two calls. - # - # @param {Dropbox.PulledChanges, String} cursor the result of a previous - # call to pullChanges, or a string containing a tag representing the - # Dropbox state that is used as the baseline for the change list; this - # should either be the Dropbox.PulledChanges obtained from a previous call - # to pullChanges, the return value of Dropbox.PulledChanges#cursor, or null - # / ommitted on the first call to pullChanges - # @param {function(?Dropbox.ApiError, ?Dropbox.PulledChanges)} callback - # called with the result of the /delta HTTP request; if the call - # succeeds, the second parameter is a Dropbox.PulledChanges describing - # the changes to the user's Dropbox since the pullChanges call that - # produced the given cursor, and the first parameter is null - # @return {XMLHttpRequest} the XHR object used for this API call - pullChanges: (cursor, callback) -> - if (not callback) and (typeof cursor is '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', @urls.delta - xhr.setParams(params).signWithOauth @oauth - @dispatchXhr xhr, (error, deltaInfo) -> - callback error, Dropbox.PulledChanges.parse(deltaInfo) - - # Alias for "pullChanges" that matches the HTTP API. - delta: (cursor, callback) -> - @pullChanges cursor, callback - - # Creates a folder in a user's Dropbox. - # - # @param {String} path the path of the folder that will be created, relative - # to the user's Dropbox or to the application's folder - # @param {function(?Dropbox.ApiError, ?Dropbox.Stat)} callback called with - # the result of the /fileops/create_folder HTTP request; if the call - # succeeds, the second parameter is a Dropbox.Stat instance describing - # the newly created folder, and the first parameter is null - # @return {XMLHttpRequest} the XHR object used for this API call - mkdir: (path, callback) -> - xhr = new Dropbox.Xhr 'POST', @urls.fileopsCreateFolder - xhr.setParams(root: @fileRoot, path: @normalizePath(path)). - signWithOauth(@oauth) - @dispatchXhr xhr, (error, metadata) -> - callback error, Dropbox.Stat.parse(metadata) - - # Removes a file or diretory from a user's Dropbox. - # - # @param {String} path the path of the file to be read, relative to the - # user's Dropbox or to the application's folder - # @param {function(?Dropbox.ApiError, ?Dropbox.Stat)} callback called with - # the result of the /fileops/delete HTTP request; if the call succeeds, - # the second parameter is a Dropbox.Stat instance describing the removed - # file or folder, and the first parameter is null - # @return {XMLHttpRequest} the XHR object used for this API call - remove: (path, callback) -> - xhr = new Dropbox.Xhr 'POST', @urls.fileopsDelete - xhr.setParams(root: @fileRoot, path: @normalizePath(path)). - signWithOauth(@oauth) - @dispatchXhr xhr, (error, metadata) -> - callback error, Dropbox.Stat.parse(metadata) - - # node.js-friendly alias for "remove". - unlink: (path, callback) -> - @remove path, callback - - # Alias for "remove" that matches the HTTP API. - delete: (path, callback) -> - @remove path, callback - - # Copies a file or folder in the user's Dropbox. - # - # This method's "from" parameter can be either a path or a copy reference - # obtained by a previous call to makeCopyRef. The method uses a crude - # heuristic to interpret the "from" string -- if it doesn't contain any - # slash (/) or dot (.) character, it is assumed to be a copy reference. The - # easiest way to work with it is to prepend "/" to every path passed to the - # method. The method will process paths that start with multiple /s - # correctly. - # - # @param {String, Dropbox.CopyReference} from the path of the file or folder - # that will be copied, or a Dropbox.CopyReference instance obtained by - # calling makeCopyRef or Dropbox.CopyReference.parse; if this is a path, it - # is relative to the user's Dropbox or to the application's folder - # @param {String} toPath the path that the file or folder will have after the - # method call; the path is relative to the user's Dropbox or to the - # application folder - # @param {function(?Dropbox.ApiError, ?Dropbox.Stat)} callback called with - # the result of the /fileops/copy HTTP request; if the call succeeds, the - # second parameter is a Dropbox.Stat instance describing the file or folder - # created by the copy operation, and the first parameter is null - # @return {XMLHttpRequest} the XHR object used for this API call - copy: (from, toPath, callback) -> - if (not callback) and (typeof options is 'function') - callback = options - options = null - - params = { root: @fileRoot, to_path: @normalizePath(toPath) } - if from instanceof Dropbox.CopyReference - params.from_copy_ref = from.tag - else - params.from_path = @normalizePath from - # TODO: locale support would edit the params here - - xhr = new Dropbox.Xhr 'POST', @urls.fileopsCopy - xhr.setParams(params).signWithOauth @oauth - @dispatchXhr xhr, (error, metadata) -> - callback error, Dropbox.Stat.parse(metadata) - - # Moves a file or folder to a different location in a user's Dropbox. - # - # @param {String} fromPath the path of the file or folder that will be moved, - # relative to the user's Dropbox or to the application's folder - # @param {String} toPath the path that the file or folder will have after - # the method call; the path is relative to the user's Dropbox or to the - # application's folder - # @param {function(?Dropbox.ApiError, ?Dropbox.Stat)} callback called with - # the result of the /fileops/move HTTP request; if the call succeeds, the - # second parameter is a Dropbox.Stat instance describing the moved - # file or folder at its new location, and the first parameter is - # null - # @return {XMLHttpRequest} the XHR object used for this API call - move: (fromPath, toPath, callback) -> - if (not callback) and (typeof options is 'function') - callback = options - options = null - - xhr = new Dropbox.Xhr 'POST', @urls.fileopsMove - xhr.setParams( - root: @fileRoot, from_path: @normalizePath(fromPath), - to_path: @normalizePath(toPath)).signWithOauth @oauth - @dispatchXhr xhr, (error, metadata) -> - callback error, Dropbox.Stat.parse(metadata) - - # Removes all login information. - # - # @return {Dropbox.Client} this, for easy call chaining - reset: -> - @uid = null - @oauth.setToken null, '' - oldAuthState = @authState - @authState = DropboxClient.RESET - if oldAuthState isnt @authState - @onAuthStateChange.dispatch @ - @authError = null - @_credentials = null - @ - - # Change the client's OAuth credentials. - # - # @param {?Object} the result of a prior call to credentials() - # @return {Dropbox.Client} this, for easy call chaining - setCredentials: (credentials) -> - oldAuthState = @authState - @oauth.reset credentials - @uid = credentials.uid or null - if credentials.authState - @authState = credentials.authState - else - if credentials.token - @authState = DropboxClient.DONE - else - @authState = DropboxClient.RESET - @authError = null - @_credentials = null - if oldAuthState isnt @authState - @onAuthStateChange.dispatch @ - @ - - # @return {String} a string that uniquely identifies the Dropbox application - # of this client - appHash: -> - @oauth.appHash() - - # Computes the URLs of all the Dropbox API calls. - # - # @private - # This is called by the constructor, and used by the other methods. It should - # not be used directly. - setupUrls: -> - @fileRoot = if @sandbox then 'sandbox' else 'dropbox' - - @urls = - # Authentication. - requestToken: "#{@apiServer}/1/oauth/request_token" - authorize: "#{@authServer}/1/oauth/authorize" - accessToken: "#{@apiServer}/1/oauth/access_token" - signOut: "#{@apiServer}/1/unlink_access_token" - - # Accounts. - accountInfo: "#{@apiServer}/1/account/info" - - # Files and metadata. - getFile: "#{@fileServer}/1/files/#{@fileRoot}" - postFile: "#{@fileServer}/1/files/#{@fileRoot}" - putFile: "#{@fileServer}/1/files_put/#{@fileRoot}" - metadata: "#{@apiServer}/1/metadata/#{@fileRoot}" - delta: "#{@apiServer}/1/delta" - revisions: "#{@apiServer}/1/revisions/#{@fileRoot}" - restore: "#{@apiServer}/1/restore/#{@fileRoot}" - search: "#{@apiServer}/1/search/#{@fileRoot}" - shares: "#{@apiServer}/1/shares/#{@fileRoot}" - media: "#{@apiServer}/1/media/#{@fileRoot}" - copyRef: "#{@apiServer}/1/copy_ref/#{@fileRoot}" - thumbnails: "#{@fileServer}/1/thumbnails/#{@fileRoot}" - chunkedUpload: "#{@fileServer}/1/chunked_upload" - commitChunkedUpload: - "#{@fileServer}/1/commit_chunked_upload/#{@fileRoot}" - - # File operations. - fileopsCopy: "#{@apiServer}/1/fileops/copy" - fileopsCreateFolder: "#{@apiServer}/1/fileops/create_folder" - fileopsDelete: "#{@apiServer}/1/fileops/delete" - fileopsMove: "#{@apiServer}/1/fileops/move" - - # @property {Number} the client's progress in the authentication process; - # Dropbox.Client#isAuthenticated should be called instead whenever - # possible; this attribute was intended to be used by OAuth drivers - authState: null - - # authState value for a client that experienced an authentication error - @ERROR: 0 - - # authState value for a properly initialized client with no user credentials - @RESET: 1 - - # authState value for a client with a request token that must be authorized - @REQUEST: 2 - - # authState value for a client whose request token was authorized - @AUTHORIZED: 3 - - # authState value for a client that has an access token - @DONE: 4 - - # authState value for a client that voluntarily invalidated its access token - @SIGNED_OFF: 5 - - # Normalizes a Dropobx path and encodes it for inclusion in a request URL. - # - # @private - # This is called internally by the other client functions, and should not be - # used outside the {Dropbox.Client} class. - urlEncodePath: (path) -> - Dropbox.Xhr.urlEncodeValue(@normalizePath(path)).replace /%2F/gi, '/' - - # Normalizes a Dropbox path for API requests. - # - # @private - # This is an internal method. It is used by all the client methods that take - # paths as arguments. - # - # @param {String} path a path - normalizePath: (path) -> - if path.substring(0, 1) is '/' - i = 1 - while path.substring(i, i + 1) is '/' - i += 1 - path.substring i - else - path - - # Generates an OAuth request token. - # - # @private - # This a low-level method called by authorize. Users should call authorize. - # - # @param {function(error, data)} callback called with the result of the - # /oauth/request_token HTTP request - requestToken: (callback) -> - xhr = new Dropbox.Xhr('POST', @urls.requestToken).signWithOauth(@oauth) - @dispatchXhr xhr, callback - - # The URL for /oauth/authorize, embedding the user's token. - # - # @private - # This a low-level method called by authorize. Users should call authorize. - # - # @param {String} token the oauth_token obtained from an /oauth/request_token - # call - # @return {String} the URL that the user's browser should be redirected to in - # order to perform an /oauth/authorize request - authorizeUrl: (token) -> - params = { oauth_token: token, oauth_callback: @driver.url() } - "#{@urls.authorize}?" + Dropbox.Xhr.urlEncode(params) - - # Exchanges an OAuth request token with an access token. - # - # @private - # This a low-level method called by authorize. Users should call authorize. - # - # @param {function(error, data)} callback called with the result of the - # /oauth/access_token HTTP request - getAccessToken: (callback) -> - xhr = new Dropbox.Xhr('POST', @urls.accessToken).signWithOauth(@oauth) - @dispatchXhr xhr, callback - - # Prepares and sends an XHR to the Dropbox API server. - # - # @private - # This is a low-level method called by other client methods. - # - # @param {Dropbox.Xhr} xhr wrapper for the XHR to be sent - # @param {function(?Dropbox.ApiError, ?Object)} callback called with the - # outcome of the XHR - # @return {XMLHttpRequest} the native XHR object used to make the request - dispatchXhr: (xhr, callback) -> - xhr.setCallback callback - xhr.onError = @onError - xhr.prepare() - nativeXhr = xhr.xhr - if @onXhr.dispatch xhr - xhr.send() - nativeXhr - - # @private - # @return {String} the URL to the default value for the "server" option - defaultApiServer: -> - 'https://api.dropbox.com' - - # @private - # @return {String} the URL to the default value for the "authServer" option - defaultAuthServer: -> - @apiServer.replace 'api.', 'www.' - - # @private - # @return {String} the URL to the default value for the "fileServer" option - defaultFileServer: -> - @apiServer.replace 'api.', 'api-content.' - - # @private - # @return {String} the URL to the default value for the "downloadServer" - # option - defaultDownloadServer: -> - @apiServer.replace 'api.', 'dl.' - - # Computes the cached value returned by credentials. - # - # @private - # @see Dropbox.Client#computeCredentials - computeCredentials: -> - value = - key: @oauth.key - sandbox: @sandbox - value.secret = @oauth.secret if @oauth.secret - if @oauth.token - value.token = @oauth.token - value.tokenSecret = @oauth.tokenSecret - value.uid = @uid if @uid - if @authState isnt DropboxClient.ERROR and - @authState isnt DropboxClient.RESET and - @authState isnt DropboxClient.DONE and - @authState isnt DropboxClient.SIGNED_OFF - value.authState = @authState - if @apiServer isnt @defaultApiServer() - value.server = @apiServer - if @authServer isnt @defaultAuthServer() - value.authServer = @authServer - if @fileServer isnt @defaultFileServer() - value.fileServer = @fileServer - if @downloadServer isnt @defaultDownloadServer() - value.downloadServer = @downloadServer - @_credentials = value - -DropboxClient = Dropbox.Client diff --git a/lib/client/storage/dropbox/src/drivers-browser.coffee b/lib/client/storage/dropbox/src/drivers-browser.coffee deleted file mode 100644 index 13306168..00000000 --- a/lib/client/storage/dropbox/src/drivers-browser.coffee +++ /dev/null @@ -1,342 +0,0 @@ -# Base class for drivers that run in the browser. -# -# Inheriting from this class makes a driver use HTML5 localStorage to preserve -# OAuth tokens across page reloads. -class Dropbox.Drivers.BrowserBase - # Sets up the OAuth driver. - # - # Subclasses should pass the options object they receive to the superclass - # constructor. - # - # @param {?Object} options the advanced settings below - # @option options {Boolean} rememberUser if true, the user's OAuth tokens are - # saved in localStorage; if you use this, you MUST provide a UI item that - # calls signOut() on Dropbox.Client, to let the user "log out" of the - # application - # @option options {String} scope embedded in the localStorage key that holds - # the authentication data; useful for having multiple OAuth tokens in a - # single application - constructor: (options) -> - @rememberUser = options?.rememberUser or false - @scope = options?.scope or 'default' - @storageKey = null - - # The magic happens here. - onAuthStateChange: (client, callback) -> - @setStorageKey client - - switch client.authState - when DropboxClient.RESET - @loadCredentials (credentials) => - return callback() unless credentials - - if credentials.authState # Incomplete authentication. - client.setCredentials credentials - return callback() - - # There is an old access token. Only use it if the app supports - # logout. - unless @rememberUser - @forgetCredentials() - return callback() - - # Verify that the old access token still works. - client.setCredentials credentials - client.getUserInfo (error) => - if error - client.reset() - @forgetCredentials callback - else - callback() - when DropboxClient.REQUEST - @storeCredentials client.credentials(), callback - when DropboxClient.DONE - if @rememberUser - return @storeCredentials(client.credentials(), callback) - @forgetCredentials callback - when DropboxClient.SIGNED_OFF - @forgetCredentials callback - when DropboxClient.ERROR - @forgetCredentials callback - else - callback() - @ - - # Computes the @storageKey used by loadCredentials and forgetCredentials. - # - # @private - # This is called by onAuthStateChange. - # - # @param {Dropbox.Client} client the client instance that is running the - # authorization process - # @return {Dropbox.Driver} this, for easy call chaining - setStorageKey: (client) -> - # NOTE: the storage key is dependent on the app hash so that multiple apps - # hosted off the same server don't step on eachother's toes - @storageKey = "dropbox-auth:#{@scope}:#{client.appHash()}" - @ - - # Stores a Dropbox.Client's credentials to localStorage. - # - # @private - # onAuthStateChange calls this method during the authentication flow. - # - # @param {Object} credentials the result of a Drobpox.Client#credentials call - # @param {function()} callback called when the storing operation is complete - # @return {Dropbox.Drivers.BrowserBase} this, for easy call chaining - storeCredentials: (credentials, callback) -> - localStorage.setItem @storageKey, JSON.stringify(credentials) - callback() - @ - - # Retrieves a token and secret from localStorage. - # - # @private - # onAuthStateChange calls this method during the authentication flow. - # - # @param {function(?Object)} callback supplied with the credentials object - # stored by a previous call to - # Dropbox.Drivers.BrowserBase#storeCredentials; null if no credentials were - # stored, or if the previously stored credentials were deleted - # @return {Dropbox.Drivers.BrowserBase} this, for easy call chaining - loadCredentials: (callback) -> - jsonString = localStorage.getItem @storageKey - unless jsonString - callback null - return @ - - try - callback JSON.parse(jsonString) - catch e - # Parse errors. - callback null - @ - - # Deletes information previously stored by a call to storeCredentials. - # - # @private - # onAuthStateChange calls this method during the authentication flow. - # - # @param {function()} callback called after the credentials are deleted - # @return {Dropbox.Drivers.BrowserBase} this, for easy call chaining - forgetCredentials: (callback) -> - localStorage.removeItem @storageKey - callback() - @ - - # Wrapper for window.location, for testing purposes. - # - # @return {String} the current page's URL - @currentLocation: -> - window.location.href - -# OAuth driver that uses a redirect and localStorage to complete the flow. -class Dropbox.Drivers.Redirect extends Dropbox.Drivers.BrowserBase - # Sets up the redirect-based OAuth driver. - # - # @param {?Object} options the advanced settings below - # @option options {Boolean} useQuery if true, the page will receive OAuth - # data as query parameters; by default, the page receives OAuth data in - # the fragment part of the URL (the string following the #, - # available as document.location.hash), to avoid confusing the server - # generating the page - # @option options {Boolean} rememberUser if true, the user's OAuth tokens are - # saved in localStorage; if you use this, you MUST provide a UI item that - # calls signOut() on Dropbox.Client, to let the user "log out" of the - # application - # @option options {String} scope embedded in the localStorage key that holds - # the authentication data; useful for having multiple OAuth tokens in a - # single application - constructor: (options) -> - super options - @useQuery = options?.useQuery or false - @receiverUrl = @computeUrl options - @tokenRe = new RegExp "(#|\\?|&)oauth_token=([^&#]+)(&|#|$)" - - # Forwards the authentication process from REQUEST to AUTHORIZED on redirect. - onAuthStateChange: (client, callback) -> - superCall = do => => super client, callback - @setStorageKey client - if client.authState is DropboxClient.RESET - @loadCredentials (credentials) => - if credentials and credentials.authState # Incomplete authentication. - if credentials.token is @locationToken() and - credentials.authState is DropboxClient.REQUEST - # locationToken matched, so the redirect happened - credentials.authState = DropboxClient.AUTHORIZED - return @storeCredentials credentials, superCall - else - # The authentication process broke down, start over. - return @forgetCredentials superCall - superCall() - else - superCall() - - # URL of the current page, since the user will be sent right back. - url: -> - @receiverUrl - - # Redirects to the authorize page. - doAuthorize: (authUrl) -> - window.location.assign authUrl - - # Pre-computes the return value of url. - computeUrl: -> - querySuffix = "_dropboxjs_scope=#{encodeURIComponent @scope}" - location = Dropbox.Drivers.BrowserBase.currentLocation() - if location.indexOf('#') is -1 - fragment = null - else - locationPair = location.split '#', 2 - location = locationPair[0] - fragment = locationPair[1] - if @useQuery - if location.indexOf('?') is -1 - location += "?#{querySuffix}" # No query string in the URL. - else - location += "&#{querySuffix}" # The URL already has a query string. - else - fragment = "?#{querySuffix}" - - if fragment - location + '#' + fragment - else - location - - # Figures out if the user completed the OAuth flow based on the current URL. - # - # @return {?String} the OAuth token that the user just authorized, or null if - # the user accessed this directly, without having authorized a token - locationToken: -> - location = Dropbox.Drivers.BrowserBase.currentLocation() - - # Check for the scope. - scopePattern = "_dropboxjs_scope=#{encodeURIComponent @scope}&" - return null if location.indexOf?(scopePattern) is -1 - - # Extract the token. - match = @tokenRe.exec location - if match then decodeURIComponent(match[2]) else null - -# OAuth driver that uses a popup window and postMessage to complete the flow. -class Dropbox.Drivers.Popup extends Dropbox.Drivers.BrowserBase - # Sets up a popup-based OAuth driver. - # - # @param {?Object} options one of the settings below; leave out the argument - # to use the current location for redirecting - # @option options {Boolean} rememberUser if true, the user's OAuth tokens are - # saved in localStorage; if you use this, you MUST provide a UI item that - # calls signOut() on Dropbox.Client, to let the user "log out" of the - # application - # @option options {String} scope embedded in the localStorage key that holds - # the authentication data; useful for having multiple OAuth tokens in a - # single application - # @option options {String} receiverUrl URL to the page that receives the - # /authorize redirect and performs the postMessage - # @option options {Boolean} noFragment if true, the receiverUrl will be used - # as given; by default, a hash "#" is appended to URLs that don't have - # one, so the OAuth token is received as a URL fragment and does not hit - # the file server - # @option options {String} receiverFile the URL to the receiver page will be - # computed by replacing the file name (everything after the last /) of - # the current location with this parameter's value - constructor: (options) -> - super options - @receiverUrl = @computeUrl options - @tokenRe = new RegExp "(#|\\?|&)oauth_token=([^&#]+)(&|#|$)" - - # Removes credentials stuck in the REQUEST stage. - onAuthStateChange: (client, callback) -> - superCall = do => => super client, callback - @setStorageKey client - if client.authState is DropboxClient.RESET - @loadCredentials (credentials) => - if credentials and credentials.authState # Incomplete authentication. - # The authentication process broke down, start over. - return @forgetCredentials superCall - superCall() - else - superCall() - - # Shows the authorization URL in a pop-up, waits for it to send a message. - doAuthorize: (authUrl, token, tokenSecret, callback) -> - @listenForMessage token, callback - @openWindow authUrl - - # URL of the redirect receiver page, which posts a message back to this page. - url: -> - @receiverUrl - - # Pre-computes the return value of url. - computeUrl: (options) -> - if options - if options.receiverUrl - if options.noFragment or options.receiverUrl.indexOf('#') isnt -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('/') + '#' - Dropbox.Drivers.BrowserBase.currentLocation() - - # Creates a popup window. - # - # @param {String} url the URL that will be loaded in the popup window - # @return {?DOMRef} reference to the opened window, or null if the call - # failed - openWindow: (url) -> - window.open url, '_dropboxOauthSigninWindow', @popupWindowSpec(980, 700) - - # Spec string for window.open to create a nice popup. - # - # @param {Number} popupWidth the desired width of the popup window - # @param {Number} popupHeight the desired height of the popup window - # @return {String} spec string for the popup window - popupWindowSpec: (popupWidth, popupHeight) -> - # Metrics for the current browser window. - x0 = window.screenX ? window.screenLeft - y0 = window.screenY ? window.screenTop - width = window.outerWidth ? document.documentElement.clientWidth - height = window.outerHeight ? document.documentElement.clientHeight - - # Computed popup window metrics. - popupLeft = Math.round x0 + (width - popupWidth) / 2 - popupTop = Math.round y0 + (height - popupHeight) / 2.5 - popupLeft = x0 if popupLeft < x0 - popupTop = y0 if popupTop < y0 - - # The specification string. - "width=#{popupWidth},height=#{popupHeight}," + - "left=#{popupLeft},top=#{popupTop}" + - 'dialog=yes,dependent=yes,scrollbars=yes,location=yes' - - # Listens for a postMessage from a previously opened popup window. - # - # @param {String} token the token string that must be received from the popup - # window - # @param {function()} called when the received message matches the token - listenForMessage: (token, callback) -> - listener = (event) => - match = @tokenRe.exec event.data.toString() - if match and decodeURIComponent(match[2]) is token - window.removeEventListener 'message', listener - callback() - window.addEventListener 'message', listener, false - - # Communicates with the driver from the OAuth receiver page. - @oauthReceiver: -> - window.addEventListener 'load', -> - opener = window.opener - if window.parent isnt window.top - opener or= window.parent - if opener - try - opener.postMessage window.location.href, '*' - catch e - # IE 9 doesn't support opener.postMessage for popup windows. - window.close() diff --git a/lib/client/storage/dropbox/src/drivers-chrome.coffee b/lib/client/storage/dropbox/src/drivers-chrome.coffee deleted file mode 100644 index 2ead8094..00000000 --- a/lib/client/storage/dropbox/src/drivers-chrome.coffee +++ /dev/null @@ -1,202 +0,0 @@ -DropboxChromeOnMessage = null -DropboxChromeSendMessage = null - -if chrome? - # v2 manifest APIs. - if chrome.runtime - if chrome.runtime.onMessage - DropboxChromeOnMessage = chrome.runtime.onMessage - if chrome.runtime.sendMessage - DropboxChromeSendMessage = (m) -> chrome.runtime.sendMessage m - - # v1 manifest APIs. - if chrome.extension - if chrome.extension.onMessage - DropboxChromeOnMessage or= chrome.extension.onMessage - if chrome.extension.sendMessage - DropboxChromeSendMessage or= (m) -> chrome.extension.sendMessage m - - # Apps that use the v2 manifest don't get messenging in Chrome 25. - unless DropboxChromeOnMessage - do -> - pageHack = (page) -> - if page.Dropbox - Dropbox.Drivers.Chrome::onMessage = - page.Dropbox.Drivers.Chrome.onMessage - Dropbox.Drivers.Chrome::sendMessage = - page.Dropbox.Drivers.Chrome.sendMessage - else - page.Dropbox = Dropbox - Dropbox.Drivers.Chrome::onMessage = new Dropbox.EventSource - Dropbox.Drivers.Chrome::sendMessage = - (m) -> Dropbox.Drivers.Chrome::onMessage.dispatch m - - if chrome.extension and chrome.extension.getBackgroundPage - if page = chrome.extension.getBackgroundPage() - return pageHack(page) - - if chrome.runtime and chrome.runtime.getBackgroundPage - return chrome.runtime.getBackgroundPage (page) -> pageHack page - -# OAuth driver specialized for Chrome apps and extensions. -class Dropbox.Drivers.Chrome - # @property {Chrome.Event<>, Dropbox.EventSource<>} fires non-cancelable - # events when Dropbox.Drivers.Chrome#sendMessage is called - onMessage: DropboxChromeOnMessage - - # Sends a message across the Chrome extension / application. - # - # When a message is sent, the listeners registered to - # - # @param {Object} message the message to be sent - sendMessage: DropboxChromeSendMessage - - # Expans an URL relative to the Chrome extension / application root. - # - # @param {String} url a resource URL relative to the extension root - # @return {String} the absolute resource URL - expandUrl: (url) -> - if chrome.runtime and chrome.runtime.getURL - return chrome.runtime.getURL(url) - if chrome.extension and chrome.extension.getURL - return chrome.extension.getURL(url) - url - - # @param {?Object} options the settings below - # @option {String} receiverPath the path of page that receives the /authorize - # redirect and performs the postMessage; the path should be relative to the - # extension folder; by default, is 'chrome_oauth_receiver.html' - constructor: (options) -> - receiverPath = (options and options.receiverPath) or - 'chrome_oauth_receiver.html' - @receiverUrl = @expandUrl receiverPath - @tokenRe = new RegExp "(#|\\?|&)oauth_token=([^&#]+)(&|#|$)" - scope = (options and options.scope) or 'default' - @storageKey = "dropbox_js_#{scope}_credentials" - - # Saves token information when appropriate. - onAuthStateChange: (client, callback) -> - switch client.authState - when Dropbox.Client.RESET - @loadCredentials (credentials) => - if credentials - if credentials.authState - # Stuck authentication process, reset. - return @forgetCredentials(callback) - client.setCredentials credentials - callback() - when Dropbox.Client.DONE - @storeCredentials client.credentials(), callback - when Dropbox.Client.SIGNED_OFF - @forgetCredentials callback - when Dropbox.Client.ERROR - @forgetCredentials callback - else - callback() - - # Shows the authorization URL in a pop-up, waits for it to send a message. - doAuthorize: (authUrl, token, tokenSecret, callback) -> - window = handle: null - @listenForMessage token, window, callback - @openWindow authUrl, (handle) -> window.handle = handle - - # Creates a popup window. - # - # @param {String} url the URL that will be loaded in the popup window - # @param {function(Object)} callback called with a handle that can be passed - # to Dropbox.Driver.Chrome#closeWindow - # @return {Dropbox.Driver.Chrome} this - openWindow: (url, callback) -> - if chrome.tabs and chrome.tabs.create - chrome.tabs.create url: url, active: true, pinned: false, (tab) -> - callback tab - return @ - if chrome.app and chrome.app.window and chrome.app.window.create - chrome.app.window.create url, frame: 'none', id: 'dropbox-auth', - (window) -> callback window - return @ - @ - - # Closes a window that was previously opened with openWindow. - # - # @param {Object} handle the object passed to an openWindow callback - closeWindow: (handle) -> - if chrome.tabs and chrome.tabs.remove and handle.id - chrome.tabs.remove handle.id - return @ - if chrome.app and chrome.app.window and handle.close - handle.close() - return @ - @ - - # URL of the redirect receiver page that messages the app / extension. - url: -> - @receiverUrl - - # Listens for a postMessage from a previously opened tab. - # - # @param {String} token the token string that must be received from the tab - # @param {Object} window a JavaScript object whose "handle" property is a - # window handle passed to the callback of a - # Dropbox.Driver.Chrome#openWindow call - # @param {function()} called when the received message matches the token - listenForMessage: (token, window, callback) -> - listener = (message, sender) => - # Reject messages not coming from the OAuth receiver window. - if sender and sender.tab - unless sender.tab.url.substring(0, @receiverUrl.length) is @receiverUrl - return - - match = @tokenRe.exec message.dropbox_oauth_receiver_href or '' - if match and decodeURIComponent(match[2]) is token - @closeWindow window.handle if window.handle - @onMessage.removeListener listener - callback() - @onMessage.addListener listener - - # Stores a Dropbox.Client's credentials to local storage. - # - # @private - # onAuthStateChange calls this method during the authentication flow. - # - # @param {Object} credentials the result of a Drobpox.Client#credentials call - # @param {function()} callback called when the storing operation is complete - # @return {Dropbox.Drivers.BrowserBase} this, for easy call chaining - storeCredentials: (credentials, callback) -> - items= {} - items[@storageKey] = credentials - chrome.storage.local.set items, callback - @ - - # Retrieves a token and secret from localStorage. - # - # @private - # onAuthStateChange calls this method during the authentication flow. - # - # @param {function(?Object)} callback supplied with the credentials object - # stored by a previous call to - # Dropbox.Drivers.BrowserBase#storeCredentials; null if no credentials were - # stored, or if the previously stored credentials were deleted - # @return {Dropbox.Drivers.BrowserBase} this, for easy call chaining - loadCredentials: (callback) -> - chrome.storage.local.get @storageKey, (items) => - callback items[@storageKey] or null - @ - - # Deletes information previously stored by a call to storeCredentials. - # - # @private - # onAuthStateChange calls this method during the authentication flow. - # - # @param {function()} callback called after the credentials are deleted - # @return {Dropbox.Drivers.BrowserBase} this, for easy call chaining - forgetCredentials: (callback) -> - chrome.storage.local.remove @storageKey, callback - @ - - # Communicates with the driver from the OAuth receiver page. - @oauthReceiver: -> - window.addEventListener 'load', -> - driver = new Dropbox.Drivers.Chrome() - driver.sendMessage dropbox_oauth_receiver_href: window.location.href - window.close() if window.close diff --git a/lib/client/storage/dropbox/src/drivers-node.coffee b/lib/client/storage/dropbox/src/drivers-node.coffee deleted file mode 100644 index acba25af..00000000 --- a/lib/client/storage/dropbox/src/drivers-node.coffee +++ /dev/null @@ -1,87 +0,0 @@ -# OAuth driver that redirects the browser to a node app to complete the flow. -# -# This is useful for testing node.js libraries and applications. -class Dropbox.Drivers.NodeServer - # Starts up the node app that intercepts the browser redirect. - # - # @param {?Object} options one or more of the options below - # @option options {Number} port the number of the TCP port that will receive - # HTTP requests - # @param {String} faviconFile the path to a file that will be served at - # /favicon.ico - constructor: (options) -> - @port = options?.port or 8912 - @faviconFile = options?.favicon or null - # Calling require in the constructor because this doesn't work in browsers. - @fs = require 'fs' - @http = require 'http' - @open = require 'open' - - @callbacks = {} - @urlRe = new RegExp "^/oauth_callback\\?" - @tokenRe = new RegExp "(\\?|&)oauth_token=([^&]+)(&|$)" - @createApp() - - # URL to the node.js OAuth callback handler. - url: -> - "http://localhost:#{@port}/oauth_callback" - - # Opens the token - doAuthorize: (authUrl, token, tokenSecret, callback) -> - @callbacks[token] = callback - @openBrowser authUrl - - # Opens the given URL in a browser. - openBrowser: (url) -> - unless url.match /^https?:\/\// - throw new Error("Not a http/https URL: #{url}") - @open url - - # Creates and starts up an HTTP server that will intercept the redirect. - createApp: -> - @app = @http.createServer (request, response) => - @doRequest request, response - @app.listen @port - - # Shuts down the HTTP server. - # - # The driver will become unusable after this call. - closeServer: -> - @app.close() - - # Reads out an /authorize callback. - doRequest: (request, response) -> - if @urlRe.exec request.url - match = @tokenRe.exec request.url - if match - token = decodeURIComponent match[2] - if @callbacks[token] - @callbacks[token]() - delete @callbacks[token] - data = '' - request.on 'data', (dataFragment) -> data += dataFragment - request.on 'end', => - if @faviconFile and (request.url is '/favicon.ico') - @sendFavicon response - else - @closeBrowser response - - # Renders a response that will close the browser window used for OAuth. - closeBrowser: (response) -> - closeHtml = """ - - -

    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/package.json b/package.json index d3fbed19..f77c1efc 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "node": "0.6.17", "subdomain": "cloudcmd", "dependencies": { + "dropbox": "0.9.2", "minify": "0.1.9", "socket.io": "0.9.13" },