summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/command/app/listapps.php17
-rw-r--r--core/js/core.json8
-rw-r--r--core/js/files/client.js691
-rw-r--r--core/js/files/fileinfo.js138
-rw-r--r--core/js/files/iedavclient.js169
-rw-r--r--core/js/js.js1
-rw-r--r--core/js/oc-dialogs.js2
-rw-r--r--core/js/tests/specHelper.js1
-rw-r--r--core/js/tests/specs/files/clientSpec.js711
-rw-r--r--core/l10n/hy.js4
-rw-r--r--core/l10n/hy.json4
-rw-r--r--core/l10n/lt_LT.js1
-rw-r--r--core/l10n/lt_LT.json1
-rw-r--r--core/l10n/nds.js4
-rw-r--r--core/l10n/nds.json4
-rw-r--r--core/l10n/tr.js10
-rw-r--r--core/l10n/tr.json10
-rw-r--r--core/vendor/.gitignore11
-rw-r--r--core/vendor/davclient.js/LICENSE27
-rw-r--r--core/vendor/davclient.js/lib/client.js296
-rw-r--r--core/vendor/es6-promise/.bower.json40
-rw-r--r--core/vendor/es6-promise/.npmignore11
-rw-r--r--core/vendor/es6-promise/.release.json17
-rw-r--r--core/vendor/es6-promise/.spmignore11
-rw-r--r--core/vendor/es6-promise/LICENSE19
-rw-r--r--core/vendor/es6-promise/dist/es6-promise.js972
26 files changed, 3172 insertions, 8 deletions
diff --git a/core/command/app/listapps.php b/core/command/app/listapps.php
index e483037d45d..542420ee6b7 100644
--- a/core/command/app/listapps.php
+++ b/core/command/app/listapps.php
@@ -25,6 +25,7 @@ namespace OC\Core\Command\App;
use OC\Core\Command\Base;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class ListApps extends Base {
@@ -34,16 +35,32 @@ class ListApps extends Base {
$this
->setName('app:list')
->setDescription('List all available apps')
+ ->addOption(
+ 'shipped',
+ null,
+ InputOption::VALUE_REQUIRED,
+ 'true - limit to shipped apps only, false - limit to non-shipped apps only'
+ )
;
}
protected function execute(InputInterface $input, OutputInterface $output) {
+ if ($input->getOption('shipped') === 'true' || $input->getOption('shipped') === 'false'){
+ $shouldFilterShipped = true;
+ $shippedFilter = $input->getOption('shipped') === 'true';
+ } else {
+ $shouldFilterShipped = false;
+ }
+
$apps = \OC_App::getAllApps();
$enabledApps = $disabledApps = [];
$versions = \OC_App::getAppVersions();
//sort enabled apps above disabled apps
foreach ($apps as $app) {
+ if ($shouldFilterShipped && \OC_App::isShipped($app) !== $shippedFilter){
+ continue;
+ }
if (\OC_App::isEnabled($app)) {
$enabledApps[] = $app;
} else {
diff --git a/core/js/core.json b/core/js/core.json
index a80636e8463..c7621a08d62 100644
--- a/core/js/core.json
+++ b/core/js/core.json
@@ -8,7 +8,9 @@
"handlebars/handlebars.js",
"blueimp-md5/js/md5.js",
"bootstrap/js/tooltip.js",
- "backbone/backbone.js"
+ "backbone/backbone.js",
+ "es6-promise/dist/es6-promise.js",
+ "davclient.js/lib/client.js"
],
"libraries": [
"jquery-showpassword.js",
@@ -39,6 +41,8 @@
"setupchecks.js",
"../search/js/search.js",
"mimetype.js",
- "mimetypelist.js"
+ "mimetypelist.js",
+ "files/fileinfo.js",
+ "files/client.js"
]
}
diff --git a/core/js/files/client.js b/core/js/files/client.js
new file mode 100644
index 00000000000..82cf3ff5121
--- /dev/null
+++ b/core/js/files/client.js
@@ -0,0 +1,691 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+/* global dav */
+
+(function(OC, FileInfo) {
+ /**
+ * @class OC.Files.Client
+ * @classdesc Client to access files on the server
+ *
+ * @param {Object} options
+ * @param {String} options.host host name
+ * @param {int} [options.port] port
+ * @param {boolean} [options.useHTTPS] whether to use https
+ * @param {String} [options.root] root path
+ * @param {String} [options.userName] user name
+ * @param {String} [options.password] password
+ *
+ * @since 8.2
+ */
+ var Client = function(options) {
+ this._root = options.root;
+ if (this._root.charAt(this._root.length - 1) === '/') {
+ this._root = this._root.substr(0, this._root.length - 1);
+ }
+
+ var url = 'http://';
+ if (options.useHTTPS) {
+ url = 'https://';
+ }
+ var credentials = '';
+ if (options.userName) {
+ credentials += encodeURIComponent(options.userName);
+ }
+ if (options.password) {
+ credentials += ':' + encodeURIComponent(options.password);
+ }
+ if (credentials.length > 0) {
+ url += credentials + '@';
+ }
+
+ url += options.host + this._root;
+ this._defaultHeaders = options.defaultHeaders || {'X-Requested-With': 'XMLHttpRequest'};
+ this._baseUrl = url;
+ this._client = new dav.Client({
+ baseUrl: this._baseUrl,
+ xmlNamespaces: {
+ 'DAV:': 'd',
+ 'http://owncloud.org/ns': 'oc'
+ }
+ });
+ this._client.xhrProvider = _.bind(this._xhrProvider, this);
+ };
+
+ Client.NS_OWNCLOUD = 'http://owncloud.org/ns';
+ Client.NS_DAV = 'DAV:';
+ Client._PROPFIND_PROPERTIES = [
+ /**
+ * Modified time
+ */
+ [Client.NS_DAV, 'getlastmodified'],
+ /**
+ * Etag
+ */
+ [Client.NS_DAV, 'getetag'],
+ /**
+ * Mime type
+ */
+ [Client.NS_DAV, 'getcontenttype'],
+ /**
+ * Resource type "collection" for folders, empty otherwise
+ */
+ [Client.NS_DAV, 'resourcetype'],
+ /**
+ * File id
+ */
+ [Client.NS_OWNCLOUD, 'fileid'],
+ /**
+ * Letter-coded permissions
+ */
+ [Client.NS_OWNCLOUD, 'permissions'],
+ //[Client.NS_OWNCLOUD, 'downloadURL'],
+ /**
+ * Folder sizes
+ */
+ [Client.NS_OWNCLOUD, 'size'],
+ /**
+ * File sizes
+ */
+ [Client.NS_DAV, 'getcontentlength']
+ ];
+
+ /**
+ * @memberof OC.Files
+ */
+ Client.prototype = {
+
+ /**
+ * Root path of the Webdav endpoint
+ *
+ * @type string
+ */
+ _root: null,
+
+ /**
+ * Client from the library
+ *
+ * @type dav.Client
+ */
+ _client: null,
+
+ /**
+ * Array of file info parsing functions.
+ *
+ * @type Array<OC.Files.Client~parseFileInfo>
+ */
+ _fileInfoParsers: [],
+
+ /**
+ * Returns the configured XHR provider for davclient
+ * @return {XMLHttpRequest}
+ */
+ _xhrProvider: function() {
+ var headers = this._defaultHeaders;
+ var xhr = new XMLHttpRequest();
+ var oldOpen = xhr.open;
+ // override open() method to add headers
+ xhr.open = function() {
+ var result = oldOpen.apply(this, arguments);
+ _.each(headers, function(value, key) {
+ xhr.setRequestHeader(key, value);
+ });
+ return result;
+ };
+ return xhr;
+ },
+
+ /**
+ * Prepends the base url to the given path sections
+ *
+ * @param {...String} path sections
+ *
+ * @return {String} base url + joined path, any leading or trailing slash
+ * will be kept
+ */
+ _buildUrl: function() {
+ var path = this._buildPath.apply(this, arguments);
+ if (path.charAt([path.length - 1]) === '/') {
+ path = path.substr(0, path.length - 1);
+ }
+ if (path.charAt(0) === '/') {
+ path = path.substr(1);
+ }
+ return this._baseUrl + '/' + path;
+ },
+
+ /**
+ * Append the path to the root and also encode path
+ * sections
+ *
+ * @param {...String} path sections
+ *
+ * @return {String} joined path, any leading or trailing slash
+ * will be kept
+ */
+ _buildPath: function() {
+ var path = OC.joinPaths.apply(this, arguments);
+ var sections = path.split('/');
+ var i;
+ for (i = 0; i < sections.length; i++) {
+ sections[i] = encodeURIComponent(sections[i]);
+ }
+ path = sections.join('/');
+ return path;
+ },
+
+ /**
+ * Parse headers string into a map
+ *
+ * @param {string} headersString headers list as string
+ *
+ * @return {Object.<String,Array>} map of header name to header contents
+ */
+ _parseHeaders: function(headersString) {
+ var headerRows = headersString.split('\n');
+ var headers = {};
+ for (var i = 0; i < headerRows.length; i++) {
+ var sepPos = headerRows[i].indexOf(':');
+ if (sepPos < 0) {
+ continue;
+ }
+
+ var headerName = headerRows[i].substr(0, sepPos);
+ var headerValue = headerRows[i].substr(sepPos + 2);
+
+ if (!headers[headerName]) {
+ // make it an array
+ headers[headerName] = [];
+ }
+
+ headers[headerName].push(headerValue);
+ }
+ return headers;
+ },
+
+ /**
+ * Parses the etag response which is in double quotes.
+ *
+ * @param {string} etag etag value in double quotes
+ *
+ * @return {string} etag without double quotes
+ */
+ _parseEtag: function(etag) {
+ if (etag.charAt(0) === '"') {
+ return etag.split('"')[1];
+ }
+ return etag;
+ },
+
+ /**
+ * Parse Webdav result
+ *
+ * @param {Object} response XML object
+ *
+ * @return {Array.<FileInfo>} array of file info
+ */
+ _parseFileInfo: function(response) {
+ var path = response.href;
+ if (path.substr(0, this._root.length) === this._root) {
+ path = path.substr(this._root.length);
+ }
+
+ if (path.charAt(path.length - 1) === '/') {
+ path = path.substr(0, path.length - 1);
+ }
+
+ path = '/' + decodeURIComponent(path);
+
+ if (response.propStat.length === 1 && response.propStat[0].status !== 200) {
+ return null;
+ }
+
+ var props = response.propStat[0].properties;
+
+ var data = {
+ id: props['{' + Client.NS_OWNCLOUD + '}fileid'],
+ path: OC.dirname(path) || '/',
+ name: OC.basename(path),
+ mtime: new Date(props['{' + Client.NS_DAV + '}getlastmodified'])
+ };
+
+ var etagProp = props['{' + Client.NS_DAV + '}getetag'];
+ if (!_.isUndefined(etagProp)) {
+ data.etag = this._parseEtag(etagProp);
+ }
+
+ var sizeProp = props['{' + Client.NS_DAV + '}getcontentlength'];
+ if (!_.isUndefined(sizeProp)) {
+ data.size = parseInt(sizeProp, 10);
+ }
+
+ sizeProp = props['{' + Client.NS_OWNCLOUD + '}size'];
+ if (!_.isUndefined(sizeProp)) {
+ data.size = parseInt(sizeProp, 10);
+ }
+
+ var contentType = props['{' + Client.NS_DAV + '}getcontenttype'];
+ if (!_.isUndefined(contentType)) {
+ data.mimetype = contentType;
+ }
+
+ var resType = props['{' + Client.NS_DAV + '}resourcetype'];
+ var isFile = true;
+ if (!data.mimetype && resType) {
+ var xmlvalue = resType[0];
+ if (xmlvalue.namespaceURI === Client.NS_DAV && xmlvalue.nodeName.split(':')[1] === 'collection') {
+ data.mimetype = 'httpd/unix-directory';
+ isFile = false;
+ }
+ }
+
+ data.permissions = OC.PERMISSION_READ;
+ var permissionProp = props['{' + Client.NS_OWNCLOUD + '}permissions'];
+ if (!_.isUndefined(permissionProp)) {
+ var permString = permissionProp || '';
+ data.mountType = null;
+ for (var i = 0; i < permString.length; i++) {
+ var c = permString.charAt(i);
+ switch (c) {
+ // FIXME: twisted permissions
+ case 'C':
+ case 'K':
+ data.permissions |= OC.PERMISSION_CREATE;
+ if (!isFile) {
+ data.permissions |= OC.PERMISSION_UPDATE;
+ }
+ break;
+ case 'W':
+ if (isFile) {
+ // also add create permissions
+ data.permissions |= OC.PERMISSION_CREATE;
+ }
+ data.permissions |= OC.PERMISSION_UPDATE;
+ break;
+ case 'D':
+ data.permissions |= OC.PERMISSION_DELETE;
+ break;
+ case 'R':
+ data.permissions |= OC.PERMISSION_SHARE;
+ break;
+ case 'M':
+ if (!data.mountType) {
+ // TODO: how to identify external-root ?
+ data.mountType = 'external';
+ }
+ break;
+ case 'S':
+ // TODO: how to identify shared-root ?
+ data.mountType = 'shared';
+ break;
+ }
+ }
+ }
+
+ // extend the parsed data using the custom parsers
+ _.each(this._fileInfoParsers, function(parserFunction) {
+ _.extend(data, parserFunction(response) || {});
+ });
+
+ return new FileInfo(data);
+ },
+
+ /**
+ * Parse Webdav multistatus
+ *
+ * @param {Array} responses
+ */
+ _parseResult: function(responses) {
+ var self = this;
+ return _.map(responses, function(response) {
+ return self._parseFileInfo(response);
+ });
+ },
+
+ /**
+ * Returns whether the given status code means success
+ *
+ * @param {int} status status code
+ *
+ * @return true if status code is between 200 and 299 included
+ */
+ _isSuccessStatus: function(status) {
+ return status >= 200 && status <= 299;
+ },
+
+ /**
+ * Returns the default PROPFIND properties to use during a call.
+ *
+ * @return {Array.<Object>} array of properties
+ */
+ getPropfindProperties: function() {
+ if (!this._propfindProperties) {
+ this._propfindProperties = _.map(Client._PROPFIND_PROPERTIES, function(propDef) {
+ return '{' + propDef[0] + '}' + propDef[1];
+ });
+ }
+ return this._propfindProperties;
+ },
+
+ /**
+ * Lists the contents of a directory
+ *
+ * @param {String} path path to retrieve
+ * @param {Object} [options] options
+ * @param {boolean} [options.includeParent=false] set to true to keep
+ * the parent folder in the result list
+ * @param {Array} [options.properties] list of Webdav properties to retrieve
+ *
+ * @return {Promise} promise
+ */
+ getFolderContents: function(path, options) {
+ if (!path) {
+ path = '';
+ }
+ options = options || {};
+ var self = this;
+ var deferred = $.Deferred();
+ var promise = deferred.promise();
+ var properties;
+ if (_.isUndefined(options.properties)) {
+ properties = this.getPropfindProperties();
+ } else {
+ properties = options.properties;
+ }
+
+ // TODO: headers
+ this._client.propFind(
+ this._buildUrl(path),
+ properties,
+ 1
+ ).then(function(result) {
+ if (self._isSuccessStatus(result.status)) {
+ var results = self._parseResult(result.body);
+ if (!options || !options.includeParent) {
+ // remove root dir, the first entry
+ results.shift();
+ }
+ deferred.resolve(result.status, results);
+ } else {
+ deferred.reject(result.status);
+ }
+ });
+ return promise;
+ },
+
+ /**
+ * Returns the file info of a given path.
+ *
+ * @param {String} path path
+ * @param {Array} [options.properties] list of Webdav properties to retrieve
+ *
+ * @return {Promise} promise
+ */
+ getFileInfo: function(path, options) {
+ if (!path) {
+ path = '';
+ }
+ options = options || {};
+ var self = this;
+ var deferred = $.Deferred();
+ var promise = deferred.promise();
+ var properties;
+ if (_.isUndefined(options.properties)) {
+ properties = this.getPropfindProperties();
+ } else {
+ properties = options.properties;
+ }
+
+ // TODO: headers
+ this._client.propFind(
+ this._buildUrl(path),
+ properties,
+ 0
+ ).then(
+ function(result) {
+ if (self._isSuccessStatus(result.status)) {
+ deferred.resolve(result.status, self._parseResult([result.body])[0]);
+ } else {
+ deferred.reject(result.status);
+ }
+ }
+ );
+ return promise;
+ },
+
+ /**
+ * Returns the contents of the given file.
+ *
+ * @param {String} path path to file
+ *
+ * @return {Promise}
+ */
+ getFileContents: function(path) {
+ if (!path) {
+ throw 'Missing argument "path"';
+ }
+ var self = this;
+ var deferred = $.Deferred();
+ var promise = deferred.promise();
+
+ this._client.request(
+ 'GET',
+ this._buildUrl(path),
+ this._defaultHeaders
+ ).then(
+ function(result) {
+ if (self._isSuccessStatus(result.status)) {
+ deferred.resolve(result.status, result.body);
+ } else {
+ deferred.reject(result.status);
+ }
+ }
+ );
+ return promise;
+ },
+
+ /**
+ * Puts the given data into the given file.
+ *
+ * @param {String} path path to file
+ * @param {String} body file body
+ * @param {Object} [options]
+ * @param {String} [options.contentType='text/plain'] content type
+ * @param {bool} [options.overwrite=true] whether to overwrite an existing file
+ *
+ * @return {Promise}
+ */
+ putFileContents: function(path, body, options) {
+ if (!path) {
+ throw 'Missing argument "path"';
+ }
+ var self = this;
+ var deferred = $.Deferred();
+ var promise = deferred.promise();
+ options = options || {};
+ var headers = _.extend({}, this._defaultHeaders);
+ var contentType = 'text/plain';
+ if (options.contentType) {
+ contentType = options.contentType;
+ }
+
+ headers['Content-Type'] = contentType;
+
+ if (_.isUndefined(options.overwrite) || options.overwrite) {
+ // will trigger 412 precondition failed if a file already exists
+ headers['If-None-Match'] = '*';
+ }
+
+ this._client.request(
+ 'PUT',
+ this._buildUrl(path),
+ headers,
+ body || ''
+ ).then(
+ function(result) {
+ if (self._isSuccessStatus(result.status)) {
+ deferred.resolve(result.status);
+ } else {
+ deferred.reject(result.status);
+ }
+ }
+ );
+ return promise;
+ },
+
+ _simpleCall: function(method, path) {
+ if (!path) {
+ throw 'Missing argument "path"';
+ }
+
+ var self = this;
+ var deferred = $.Deferred();
+ var promise = deferred.promise();
+
+ this._client.request(
+ method,
+ this._buildUrl(path),
+ this._defaultHeaders
+ ).then(
+ function(result) {
+ if (self._isSuccessStatus(result.status)) {
+ deferred.resolve(result.status);
+ } else {
+ deferred.reject(result.status);
+ }
+ }
+ );
+ return promise;
+ },
+
+ /**
+ * Creates a directory
+ *
+ * @param {String} path path to create
+ *
+ * @return {Promise}
+ */
+ createDirectory: function(path) {
+ return this._simpleCall('MKCOL', path);
+ },
+
+ /**
+ * Deletes a file or directory
+ *
+ * @param {String} path path to delete
+ *
+ * @return {Promise}
+ */
+ remove: function(path) {
+ return this._simpleCall('DELETE', path);
+ },
+
+ /**
+ * Moves path to another path
+ *
+ * @param {String} path path to move
+ * @param {String} destinationPath destination path
+ * @param {boolean} [allowOverwrite=false] true to allow overwriting,
+ * false otherwise
+ *
+ * @return {Promise} promise
+ */
+ move: function(path, destinationPath, allowOverwrite) {
+ if (!path) {
+ throw 'Missing argument "path"';
+ }
+ if (!destinationPath) {
+ throw 'Missing argument "destinationPath"';
+ }
+
+ var self = this;
+ var deferred = $.Deferred();
+ var promise = deferred.promise();
+ var headers =
+ _.extend({
+ 'Destination' : this._buildUrl(destinationPath)
+ }, this._defaultHeaders);
+
+ if (!allowOverwrite) {
+ headers['Overwrite'] = 'F';
+ }
+
+ this._client.request(
+ 'MOVE',
+ this._buildUrl(path),
+ headers
+ ).then(
+ function(response) {
+ if (self._isSuccessStatus(response.status)) {
+ deferred.resolve(response.status);
+ } else {
+ deferred.reject(response.status);
+ }
+ }
+ );
+ return promise;
+ },
+
+ /**
+ * Add a file info parser function
+ *
+ * @param {OC.Files.Client~parseFileInfo>}
+ */
+ addFileInfoParser: function(parserFunction) {
+ this._fileInfoParsers.push(parserFunction);
+ }
+
+ };
+
+ /**
+ * File info parser function
+ *
+ * This function receives a list of Webdav properties as input and
+ * should return a hash array of parsed properties, if applicable.
+ *
+ * @callback OC.Files.Client~parseFileInfo
+ * @param {Object} XML Webdav properties
+ * @return {Array} array of parsed property values
+ */
+
+ if (!OC.Files) {
+ /**
+ * @namespace OC.Files
+ *
+ * @since 8.2
+ */
+ OC.Files = {};
+ }
+
+ /**
+ * Returns the default instance of the files client
+ *
+ * @return {OC.Files.Client} default client
+ *
+ * @since 8.2
+ */
+ OC.Files.getClient = function() {
+ if (OC.Files._defaultClient) {
+ return OC.Files._defaultClient;
+ }
+
+ var client = new OC.Files.Client({
+ host: OC.getHost(),
+ port: OC.getPort(),
+ root: OC.linkToRemoteBase('webdav'),
+ useHTTPS: OC.getProtocol() === 'https'
+ });
+ OC.Files._defaultClient = client;
+ return client;
+ };
+
+ OC.Files.Client = Client;
+})(OC, OC.Files.FileInfo);
+
diff --git a/core/js/files/fileinfo.js b/core/js/files/fileinfo.js
new file mode 100644
index 00000000000..3bf68d88b15
--- /dev/null
+++ b/core/js/files/fileinfo.js
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function(OC) {
+
+ /**
+ * @class OC.Files.FileInfo
+ * @classdesc File information
+ *
+ * @param {Object} data file data, see attributes for details
+ *
+ * @since 8.2
+ */
+ var FileInfo = function(data) {
+ var self = this;
+ _.each(data, function(value, key) {
+ if (!_.isFunction(value)) {
+ self[key] = value;
+ }
+ });
+
+ if (!_.isUndefined(this.id)) {
+ this.id = parseInt(data.id, 10);
+ }
+
+ // TODO: normalize path
+ this.path = data.path || '';
+
+ if (this.type === 'dir') {
+ this.mimetype = 'httpd/unix-directory';
+ } else {
+ this.mimetype = this.mimetype || 'application/octet-stream';
+ }
+
+ if (!this.type) {
+ if (this.mimetype === 'httpd/unix-directory') {
+ this.type = 'dir';
+ } else {
+ this.type = 'file';
+ }
+ }
+ };
+
+ /**
+ * @memberof OC.Files
+ */
+ FileInfo.prototype = {
+ /**
+ * File id
+ *
+ * @type int
+ */
+ id: null,
+
+ /**
+ * File name
+ *
+ * @type String
+ */
+ name: null,
+
+ /**
+ * Path leading to the file, without the file name,
+ * and with a leading slash.
+ *
+ * @type String
+ */
+ path: null,
+
+ /**
+ * Mime type
+ *
+ * @type String
+ */
+ mimetype: null,
+
+ /**
+ * Icon URL.
+ *
+ * Can be used to override the mime type icon.
+ *
+ * @type String
+ */
+ icon: null,
+
+ /**
+ * File type. 'file' for files, 'dir' for directories.
+ *
+ * @type String
+ * @deprecated rely on mimetype instead
+ */
+ type: null,
+
+ /**
+ * Permissions.
+ *
+ * @see OC#PERMISSION_ALL for permissions
+ * @type int
+ */
+ permissions: null,
+
+ /**
+ * Modification time
+ *
+ * @type int
+ */
+ mtime: null,
+
+ /**
+ * Etag
+ *
+ * @type String
+ */
+ etag: null,
+
+ /**
+ * Mount type.
+ *
+ * One of null, "external-root", "shared" or "shared-root"
+ *
+ * @type string
+ */
+ mountType: null
+ };
+
+ if (!OC.Files) {
+ OC.Files = {};
+ }
+ OC.Files.FileInfo = FileInfo;
+})(OC);
+
diff --git a/core/js/files/iedavclient.js b/core/js/files/iedavclient.js
new file mode 100644
index 00000000000..bc6bce2f9ae
--- /dev/null
+++ b/core/js/files/iedavclient.js
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2015
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+/* global dav */
+(function(dav) {
+
+ /**
+ * Override davclient.js methods with IE-compatible logic
+ */
+ dav.Client.prototype = _.extend({}, dav.Client.prototype, {
+
+ /**
+ * Generates a propFind request.
+ *
+ * @param {string} url Url to do the propfind request on
+ * @param {Array} properties List of properties to retrieve.
+ * @return {Promise}
+ */
+ propFind : function(url, properties, depth) {
+
+ if(typeof depth == "undefined") {
+ depth = 0;
+ }
+
+ var headers = {
+ Depth : depth,
+ 'Content-Type' : 'application/xml; charset=utf-8'
+ };
+
+ var body =
+ '<?xml version="1.0"?>\n' +
+ '<d:propfind ';
+
+ var namespace;
+ for (namespace in this.xmlNamespaces) {
+ body += ' xmlns:' + this.xmlNamespaces[namespace] + '="' + namespace + '"';
+ }
+ body += '>\n' +
+ ' <d:prop>\n';
+
+ for(var ii in properties) {
+ var propText = properties[ii];
+ if (typeof propText !== 'string') {
+ // can happen on IE8
+ continue;
+ }
+ var property = this.parseClarkNotation(properties[ii]);
+ if (this.xmlNamespaces[property.namespace]) {
+ body+=' <' + this.xmlNamespaces[property.namespace] + ':' + property.name + ' />\n';
+ } else {
+ body+=' <x:' + property.name + ' xmlns:x="' + property.namespace + '" />\n';
+ }
+
+ }
+ body+=' </d:prop>\n';
+ body+='</d:propfind>';
+
+ return this.request('PROPFIND', url, headers, body).then(
+ function(result) {
+ var elements = this.parseMultiStatus(result.xhr.responseXML);
+ var response;
+ if (depth===0) {
+ response = {
+ status: result.status,
+ body: elements[0]
+ };
+ } else {
+ response = {
+ status: result.status,
+ body: elements
+ };
+ }
+ return response;
+
+ }.bind(this)
+ );
+
+ },
+
+
+ _getElementsByTagName: function(node, name, resolver) {
+ var parts = name.split(':');
+ var tagName = parts[1];
+ var namespace = resolver(parts[0]);
+ if (node.getElementsByTagNameNS) {
+ return node.getElementsByTagNameNS(namespace, tagName);
+ }
+ return node.getElementsByTagName(name);
+ },
+
+ /**
+ * Parses a multi-status response body.
+ *
+ * @param {string} xmlBody
+ * @param {Array}
+ */
+ parseMultiStatus : function(doc) {
+
+ var result = [];
+ var resolver = function(foo) {
+ var ii;
+ for(ii in this.xmlNamespaces) {
+ if (this.xmlNamespaces[ii] === foo) {
+ return ii;
+ }
+ }
+ }.bind(this);
+
+ var responses = this._getElementsByTagName(doc, 'd:response', resolver);
+ var i;
+ for (i = 0; i < responses.length; i++) {
+ var responseNode = responses[i];
+ var response = {
+ href : null,
+ propStat : []
+ };
+
+ var hrefNode = this._getElementsByTagName(responseNode, 'd:href', resolver)[0];
+
+ response.href = hrefNode.textContent || hrefNode.text;
+
+ var propStatNodes = this._getElementsByTagName(responseNode, 'd:propstat', resolver);
+ var j = 0;
+
+ for (j = 0; j < propStatNodes.length; j++) {
+ var propStatNode = propStatNodes[j];
+ var statusNode = this._getElementsByTagName(propStatNode, 'd:status', resolver)[0];
+
+ var propStat = {
+ status : statusNode.textContent || statusNode.text,
+ properties : []
+ };
+
+ var propNode = this._getElementsByTagName(propStatNode, 'd:prop', resolver)[0];
+ if (!propNode) {
+ continue;
+ }
+ var k = 0;
+ for (k = 0; k < propNode.childNodes.length; k++) {
+ var prop = propNode.childNodes[k];
+ var value = prop.textContent || prop.text;
+ if (prop.childNodes && prop.childNodes.length > 0 && prop.childNodes[0].nodeType === 1) {
+ value = prop.childNodes;
+ }
+ propStat.properties['{' + prop.namespaceURI + '}' + (prop.localName || prop.baseName)] = value;
+
+ }
+ response.propStat.push(propStat);
+ }
+
+ result.push(response);
+ }
+
+ return result;
+
+ }
+
+
+ });
+
+})(dav);
+
diff --git a/core/js/js.js b/core/js/js.js
index 57c9871233b..ce552bb8ea2 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -1428,7 +1428,6 @@ function initCore() {
$('body').delegate('#app-content', 'apprendered appresized', adjustControlsWidth);
}
-
}
$(document).ready(initCore);
diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js
index 4448b813021..fe93d0ea657 100644
--- a/core/js/oc-dialogs.js
+++ b/core/js/oc-dialogs.js
@@ -759,7 +759,7 @@ var OCdialogs = {
filename: entry.name,
date: OC.Util.relativeModifiedDate(entry.mtime)
});
- if (entry.isPreviewAvailable) {
+ if (entry.type === 'file') {
var urlSpec = {
file: dir + '/' + entry.name
};
diff --git a/core/js/tests/specHelper.js b/core/js/tests/specHelper.js
index cd387d76ce8..f09a7054c9f 100644
--- a/core/js/tests/specHelper.js
+++ b/core/js/tests/specHelper.js
@@ -86,6 +86,7 @@ window.firstDay = 0;
// setup dummy webroots
/* jshint camelcase: false */
window.oc_debug = true;
+// FIXME: oc_webroot is supposed to be only the path!!!
window.oc_webroot = location.href + '/';
window.oc_appswebroots = {
"files": window.oc_webroot + '/apps/files/'
diff --git a/core/js/tests/specs/files/clientSpec.js b/core/js/tests/specs/files/clientSpec.js
new file mode 100644
index 00000000000..3a3181d8426
--- /dev/null
+++ b/core/js/tests/specs/files/clientSpec.js
@@ -0,0 +1,711 @@
+/**
+* ownCloud
+*
+* @author Vincent Petry
+* @copyright 2015 Vincent Petry <pvince81@owncloud.com>
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+describe('OC.Files.Client tests', function() {
+ var Client = OC.Files.Client;
+ var baseUrl;
+ var client;
+
+ beforeEach(function() {
+ baseUrl = 'https://testhost/owncloud/remote.php/webdav/';
+
+ client = new Client({
+ host: 'testhost',
+ root: '/owncloud/remote.php/webdav',
+ useHTTPS: true
+ });
+ });
+ afterEach(function() {
+ client = null;
+ });
+
+ /**
+ * Send an status response and check that the given
+ * promise gets its success handler called with the error
+ * status code
+ *
+ * @param {Promise} promise promise
+ * @param {int} status status to test
+ */
+ function respondAndCheckStatus(promise, status) {
+ var successHandler = sinon.stub();
+ var failHandler = sinon.stub();
+ promise.done(successHandler);
+ promise.fail(failHandler);
+
+ fakeServer.requests[0].respond(
+ status,
+ {'Content-Type': 'application/xml'},
+ ''
+ );
+
+ promise.then(function() {
+ expect(successHandler.calledOnce).toEqual(true);
+ expect(successHandler.getCall(0).args[0]).toEqual(status);
+
+ expect(failHandler.notCalled).toEqual(true);
+ });
+
+ return promise;
+ }
+
+ /**
+ * Send an error response and check that the given
+ * promise gets its fail handler called with the error
+ * status code
+ *
+ * @param {Promise} promise promise object
+ * @param {int} status error status to test
+ */
+ function respondAndCheckError(promise, status) {
+ var successHandler = sinon.stub();
+ var failHandler = sinon.stub();
+ promise.done(successHandler);
+ promise.fail(failHandler);
+
+ fakeServer.requests[0].respond(
+ status,
+ {'Content-Type': 'application/xml'},
+ ''
+ );
+
+ promise.then(function() {
+ expect(failHandler.calledOnce).toEqual(true);
+ expect(failHandler.calledWith(status)).toEqual(true);
+
+ expect(successHandler.notCalled).toEqual(true);
+
+ fulfill();
+ });
+
+ return promise;
+ }
+
+ /**
+ * Returns a list of request properties parsed from the given request body.
+ *
+ * @param {string} requestBody request XML
+ *
+ * @return {Array.<String>} array of request properties in the format
+ * "{NS:}propname"
+ */
+ function getRequestedProperties(requestBody) {
+ var doc = (new window.DOMParser()).parseFromString(
+ requestBody,
+ 'application/xml'
+ );
+ var propRoots = doc.getElementsByTagNameNS('DAV:', 'prop');
+ var propsList = propRoots.item(0).childNodes;
+ return _.map(propsList, function(propNode) {
+ return '{' + propNode.namespaceURI + '}' + propNode.localName;
+ });
+ }
+
+ function makePropBlock(props) {
+ var s = '<d:prop>\n';
+
+ _.each(props, function(value, key) {
+ s += '<' + key + '>' + value + '</' + key + '>\n';
+ });
+
+ return s + '</d:prop>\n';
+ }
+
+ function makeResponseBlock(href, props, failedProps) {
+ var s = '<d:response>\n';
+ s += '<d:href>' + href + '</d:href>\n';
+ s += '<d:propstat>\n';
+ s += makePropBlock(props);
+ s += '<d:status>HTTP/1.1 200 OK</d:status>';
+ s += '</d:propstat>\n';
+ if (failedProps) {
+ s += '<d:propstat>\n';
+ _.each(failedProps, function(prop) {
+ s += '<' + prop + '/>\n';
+ });
+ s += '<d:status>HTTP/1.1 404 Not Found</d:status>\n';
+ s += '</d:propstat>\n';
+ }
+ return s + '</d:response>\n';
+ }
+
+ describe('file listing', function() {
+
+ var folderContentsXml =
+ '<?xml version="1.0" encoding="utf-8"?>' +
+ '<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
+ makeResponseBlock(
+ '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/',
+ {
+ 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT',
+ 'd:getetag': '"56cfcabd79abb"',
+ 'd:resourcetype': '<d:collection/>',
+ 'oc:id': '00000011oc2d13a6a068',
+ 'oc:permissions': 'RDNVCK',
+ 'oc:size': 120
+ },
+ [
+ 'd:getcontenttype',
+ 'd:getcontentlength'
+ ]
+ ) +
+ makeResponseBlock(
+ '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt',
+ {
+ 'd:getlastmodified': 'Fri, 10 Jul 2015 13:38:05 GMT',
+ 'd:getetag': '"559fcabd79a38"',
+ 'd:getcontenttype': 'text/plain',
+ 'd:getcontentlength': 250,
+ 'd:resourcetype': '',
+ 'oc:id': '00000051oc2d13a6a068',
+ 'oc:permissions': 'RDNVW'
+ },
+ [
+ 'oc:size',
+ ]
+ ) +
+ makeResponseBlock(
+ '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/sub',
+ {
+ 'd:getlastmodified': 'Fri, 10 Jul 2015 14:00:00 GMT',
+ 'd:getetag': '"66cfcabd79abb"',
+ 'd:resourcetype': '<d:collection/>',
+ 'oc:id': '00000015oc2d13a6a068',
+ 'oc:permissions': 'RDNVCK',
+ 'oc:size': 100
+ },
+ [
+ 'd:getcontenttype',
+ 'd:getcontentlength'
+ ]
+ ) +
+ '</d:multistatus>';
+
+ it('sends PROPFIND with explicit properties to get file list', function() {
+ client.getFolderContents('path/to space/文件夹');
+
+ expect(fakeServer.requests.length).toEqual(1);
+ expect(fakeServer.requests[0].method).toEqual('PROPFIND');
+ expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
+ expect(fakeServer.requests[0].requestHeaders.Depth).toEqual(1);
+
+ var props = getRequestedProperties(fakeServer.requests[0].requestBody);
+ expect(props).toContain('{DAV:}getlastmodified');
+ expect(props).toContain('{DAV:}getcontentlength');
+ expect(props).toContain('{DAV:}getcontenttype');
+ expect(props).toContain('{DAV:}getetag');
+ expect(props).toContain('{DAV:}resourcetype');
+ expect(props).toContain('{http://owncloud.org/ns}fileid');
+ expect(props).toContain('{http://owncloud.org/ns}size');
+ expect(props).toContain('{http://owncloud.org/ns}permissions');
+ });
+ it('sends PROPFIND to base url when empty path given', function() {
+ client.getFolderContents('');
+ expect(fakeServer.requests.length).toEqual(1);
+ expect(fakeServer.requests[0].url).toEqual(baseUrl);
+ });
+ it('sends PROPFIND to base url when root path given', function() {
+ client.getFolderContents('/');
+ expect(fakeServer.requests.length).toEqual(1);
+ expect(fakeServer.requests[0].url).toEqual(baseUrl);
+ });
+ it('parses the result list into a FileInfo array', function() {
+ var promise = client.getFolderContents('path/to space/文件夹');
+
+ expect(fakeServer.requests.length).toEqual(1);
+
+ fakeServer.requests[0].respond(
+ 207,
+ {'Content-Type': 'application/xml'},
+ folderContentsXml
+ );
+
+ promise.then(function(status, response) {
+ expect(status).toEqual(207);
+ expect(_.isArray(response)).toEqual(true);
+
+ expect(response.length).toEqual(2);
+
+ // file entry
+ var info = response[0];
+ expect(info instanceof OC.Files.FileInfo).toEqual(true);
+ expect(info.id).toEqual(51);
+ expect(info.path).toEqual('/path/to space/文件夹');
+ expect(info.name).toEqual('One.txt');
+ expect(info.permissions).toEqual(31);
+ expect(info.size).toEqual(250);
+ expect(info.mtime.getTime()).toEqual(1436535485000);
+ expect(info.mimetype).toEqual('text/plain');
+ expect(info.etag).toEqual('559fcabd79a38');
+
+ // sub entry
+ info = response[1];
+ expect(info instanceof OC.Files.FileInfo).toEqual(true);
+ expect(info.id).toEqual(15);
+ expect(info.path).toEqual('/path/to space/文件夹');
+ expect(info.name).toEqual('sub');
+ expect(info.permissions).toEqual(31);
+ expect(info.size).toEqual(100);
+ expect(info.mtime.getTime()).toEqual(1436536800000);
+ expect(info.mimetype).toEqual('httpd/unix-directory');
+ expect(info.etag).toEqual('66cfcabd79abb');
+ });
+ return promise.promise();
+ });
+ it('returns parent node in result if specified', function() {
+ var promise = client.getFolderContents('path/to space/文件夹', {includeParent: true});
+
+ expect(fakeServer.requests.length).toEqual(1);
+
+ fakeServer.requests[0].respond(
+ 207,
+ {'Content-Type': 'application/xml'},
+ folderContentsXml
+ );
+
+ promise.then(function(status, response) {
+ expect(status).toEqual(207);
+ expect(_.isArray(response)).toEqual(true);
+
+ expect(response.length).toEqual(3);
+
+ // root entry
+ var info = response[0];
+ expect(info instanceof OC.Files.FileInfo).toEqual(true);
+ expect(info.id).toEqual(11);
+ expect(info.path).toEqual('/path/to space');
+ expect(info.name).toEqual('文件夹');
+ expect(info.permissions).toEqual(31);
+ expect(info.size).toEqual(120);
+ expect(info.mtime.getTime()).toEqual(1436522405000);
+ expect(info.mimetype).toEqual('httpd/unix-directory');
+ expect(info.etag).toEqual('56cfcabd79abb');
+
+ // the two other entries follow
+ expect(response[1].id).toEqual(51);
+ expect(response[2].id).toEqual(15);
+ });
+
+ return promise;
+ });
+ it('rejects promise when an error occurred', function() {
+ var promise = client.getFolderContents('path/to space/文件夹', {includeParent: true});
+ return respondAndCheckError(promise, 404);
+ });
+ it('throws exception if arguments are missing', function() {
+ // TODO
+ });
+ });
+
+ describe('file info', function() {
+ var responseXml =
+ '<?xml version="1.0" encoding="utf-8"?>' +
+ '<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
+ makeResponseBlock(
+ '/owncloud/remote.php/webdav/path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/',
+ {
+ 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT',
+ 'd:getetag': '"56cfcabd79abb"',
+ 'd:resourcetype': '<d:collection/>',
+ 'oc:id': '00000011oc2d13a6a068',
+ 'oc:permissions': 'RDNVCK',
+ 'oc:size': 120
+ },
+ [
+ 'd:getcontenttype',
+ 'd:getcontentlength'
+ ]
+ ) +
+ '</d:multistatus>';
+
+ it('sends PROPFIND with zero depth to get single file info', function() {
+ client.getFileInfo('path/to space/文件夹');
+
+ expect(fakeServer.requests.length).toEqual(1);
+ expect(fakeServer.requests[0].method).toEqual('PROPFIND');
+ expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
+ expect(fakeServer.requests[0].requestHeaders.Depth).toEqual(0);
+
+ var props = getRequestedProperties(fakeServer.requests[0].requestBody);
+ expect(props).toContain('{DAV:}getlastmodified');
+ expect(props).toContain('{DAV:}getcontentlength');
+ expect(props).toContain('{DAV:}getcontenttype');
+ expect(props).toContain('{DAV:}getetag');
+ expect(props).toContain('{DAV:}resourcetype');
+ expect(props).toContain('{http://owncloud.org/ns}fileid');
+ expect(props).toContain('{http://owncloud.org/ns}size');
+ expect(props).toContain('{http://owncloud.org/ns}permissions');
+ });
+ it('parses the result into a FileInfo', function() {
+ var promise = client.getFileInfo('path/to space/文件夹');
+
+ expect(fakeServer.requests.length).toEqual(1);
+
+ fakeServer.requests[0].respond(
+ 207,
+ {'Content-Type': 'application/xml'},
+ responseXml
+ );
+
+ promise.then(function(status, response) {
+ expect(status).toEqual(207);
+ expect(_.isArray(response)).toEqual(false);
+
+ var info = response;
+ expect(info instanceof OC.Files.FileInfo).toEqual(true);
+ expect(info.id).toEqual(11);
+ expect(info.path).toEqual('/path/to space');
+ expect(info.name).toEqual('文件夹');
+ expect(info.permissions).toEqual(31);
+ expect(info.size).toEqual(120);
+ expect(info.mtime.getTime()).toEqual(1436522405000);
+ expect(info.mimetype).toEqual('httpd/unix-directory');
+ expect(info.etag).toEqual('56cfcabd79abb');
+ });
+
+ return promise;
+ });
+ it('properly parses entry inside root', function() {
+ var responseXml =
+ '<?xml version="1.0" encoding="utf-8"?>' +
+ '<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
+ makeResponseBlock(
+ '/owncloud/remote.php/webdav/in%20root',
+ {
+ 'd:getlastmodified': 'Fri, 10 Jul 2015 10:00:05 GMT',
+ 'd:getetag': '"56cfcabd79abb"',
+ 'd:resourcetype': '<d:collection/>',
+ 'oc:id': '00000011oc2d13a6a068',
+ 'oc:permissions': 'RDNVCK',
+ 'oc:size': 120
+ },
+ [
+ 'd:getcontenttype',
+ 'd:getcontentlength'
+ ]
+ ) +
+ '</d:multistatus>';
+
+ var promise = client.getFileInfo('in root');
+
+ expect(fakeServer.requests.length).toEqual(1);
+
+ fakeServer.requests[0].respond(
+ 207,
+ {'Content-Type': 'application/xml'},
+ responseXml
+ );
+
+ promise.then(function(status, response) {
+ expect(status).toEqual(207);
+ expect(_.isArray(response)).toEqual(false);
+
+ var info = response;
+ expect(info instanceof OC.Files.FileInfo).toEqual(true);
+ expect(info.id).toEqual(11);
+ expect(info.path).toEqual('/');
+ expect(info.name).toEqual('in root');
+ expect(info.permissions).toEqual(31);
+ expect(info.size).toEqual(120);
+ expect(info.mtime.getTime()).toEqual(1436522405000);
+ expect(info.mimetype).toEqual('httpd/unix-directory');
+ expect(info.etag).toEqual('56cfcabd79abb');
+ });
+
+ return promise;
+ });
+ it('rejects promise when an error occurred', function() {
+ var promise = client.getFileInfo('path/to space/文件夹');
+ return respondAndCheckError(promise, 404);
+ });
+ it('throws exception if arguments are missing', function() {
+ // TODO
+ });
+ });
+
+ describe('permissions', function() {
+
+ function getFileInfoWithPermission(webdavPerm, isFile) {
+ var props = {
+ 'd:getlastmodified': 'Fri, 10 Jul 2015 13:38:05 GMT',
+ 'd:getetag': '"559fcabd79a38"',
+ 'd:getcontentlength': 250,
+ 'oc:id': '00000051oc2d13a6a068',
+ 'oc:permissions': webdavPerm,
+ };
+
+ if (isFile) {
+ props['d:getcontenttype'] = 'text/plain';
+ } else {
+ props['d:resourcetype'] = '<d:collection/>';
+ }
+
+ var responseXml =
+ '<?xml version="1.0" encoding="utf-8"?>' +
+ '<d:multistatus xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:oc="http://owncloud.org/ns">' +
+ makeResponseBlock(
+ '/owncloud/remote.php/webdav/file.txt',
+ props
+ ) +
+ '</d:multistatus>';
+ var promise = client.getFileInfo('file.txt');
+
+ expect(fakeServer.requests.length).toEqual(1);
+ fakeServer.requests[0].respond(
+ 207,
+ {'Content-Type': 'application/xml'},
+ responseXml
+ );
+
+ fakeServer.restore();
+ fakeServer = sinon.fakeServer.create();
+
+ return promise;
+ }
+
+ function testPermission(permission, isFile, expectedPermissions) {
+ var promise = getFileInfoWithPermission(permission, isFile);
+ promise.then(function(result) {
+ expect(result.permissions).toEqual(expectedPermissions);
+ });
+ return promise;
+ }
+
+ function testMountType(permission, isFile, expectedMountType) {
+ var promise = getFileInfoWithPermission(permission, isFile);
+ promise.then(function(result) {
+ expect(result.mountType).toEqual(expectedMountType);
+ });
+ return promise;
+ }
+
+ it('properly parses file permissions', function() {
+ // permission, isFile, expectedPermissions
+ var testCases = [
+ ['', true, OC.PERMISSION_READ],
+ ['C', true, OC.PERMISSION_READ | OC.PERMISSION_CREATE],
+ ['K', true, OC.PERMISSION_READ | OC.PERMISSION_CREATE],
+ ['W', true, OC.PERMISSION_READ | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE],
+ ['D', true, OC.PERMISSION_READ | OC.PERMISSION_DELETE],
+ ['R', true, OC.PERMISSION_READ | OC.PERMISSION_SHARE],
+ ['CKWDR', true, OC.PERMISSION_ALL]
+ ];
+ return Promise.all(
+ _.map(testCases, function(testCase) {
+ return testPermission.apply(testCase);
+ })
+ );
+ });
+ it('properly parses folder permissions', function() {
+ var testCases = [
+ ['', false, OC.PERMISSION_READ],
+ ['C', false, OC.PERMISSION_READ | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE],
+ ['K', false, OC.PERMISSION_READ | OC.PERMISSION_CREATE | OC.PERMISSION_UPDATE],
+ ['W', false, OC.PERMISSION_READ | OC.PERMISSION_UPDATE],
+ ['D', false, OC.PERMISSION_READ | OC.PERMISSION_DELETE],
+ ['R', false, OC.PERMISSION_READ | OC.PERMISSION_SHARE],
+ ['CKWDR', false, OC.PERMISSION_ALL]
+ ];
+
+ return Promise.all(
+ _.map(testCases, function(testCase) {
+ return testPermission.apply(testCase);
+ })
+ );
+ });
+ it('properly parses mount types', function() {
+ var testCases = [
+ ['CKWDR', false, null],
+ ['M', false, 'external'],
+ ['S', false, 'shared'],
+ ['SM', false, 'shared']
+ ];
+
+ return Promise.all(
+ _.map(testCases, function(testCase) {
+ return testMountType.apply(testCase);
+ })
+ );
+ });
+ });
+
+ describe('get file contents', function() {
+ it('returns file contents', function() {
+ var promise = client.getFileContents('path/to space/文件夹/One.txt');
+
+ expect(fakeServer.requests.length).toEqual(1);
+ expect(fakeServer.requests[0].method).toEqual('GET');
+ expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
+
+ fakeServer.requests[0].respond(
+ 200,
+ {'Content-Type': 'text/plain'},
+ 'some contents'
+ );
+
+ promise.then(function(status, response) {
+ expect(status).toEqual(200);
+ expect(response).toEqual('some contents');
+ });
+
+ return promise;
+ });
+ it('rejects promise when an error occurred', function() {
+ var promise = client.getFileContents('path/to space/文件夹/One.txt');
+ return respondAndCheckError(promise, 409);
+ });
+ it('throws exception if arguments are missing', function() {
+ // TODO
+ });
+ });
+
+ describe('put file contents', function() {
+ it('sends PUT with file contents', function() {
+ var promise = client.putFileContents(
+ 'path/to space/文件夹/One.txt',
+ 'some contents'
+ );
+
+ expect(fakeServer.requests.length).toEqual(1);
+ expect(fakeServer.requests[0].method).toEqual('PUT');
+ expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
+ expect(fakeServer.requests[0].requestBody).toEqual('some contents');
+ expect(fakeServer.requests[0].requestHeaders['If-None-Match']).toEqual('*');
+ expect(fakeServer.requests[0].requestHeaders['Content-Type']).toEqual('text/plain;charset=utf-8');
+
+ return respondAndCheckStatus(promise, 201);
+ });
+ it('sends PUT with file contents with headers matching options', function() {
+ var promise = client.putFileContents(
+ 'path/to space/文件夹/One.txt',
+ 'some contents',
+ {
+ overwrite: false,
+ contentType: 'text/markdown'
+ }
+ );
+
+ expect(fakeServer.requests.length).toEqual(1);
+ expect(fakeServer.requests[0].method).toEqual('PUT');
+ expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/One.txt');
+ expect(fakeServer.requests[0].requestBody).toEqual('some contents');
+ expect(fakeServer.requests[0].requestHeaders['If-None-Match']).not.toBeDefined();
+ expect(fakeServer.requests[0].requestHeaders['Content-Type']).toEqual('text/markdown;charset=utf-8');
+
+ return respondAndCheckStatus(promise, 201);
+ });
+ it('rejects promise when an error occurred', function() {
+ var promise = client.putFileContents(
+ 'path/to space/文件夹/One.txt',
+ 'some contents'
+ );
+ return respondAndCheckError(promise, 409);
+ });
+ it('throws exception if arguments are missing', function() {
+ // TODO
+ });
+ });
+
+ describe('create directory', function() {
+ it('sends MKCOL with specified path', function() {
+ var promise = client.createDirectory('path/to space/文件夹/new dir');
+
+ expect(fakeServer.requests.length).toEqual(1);
+ expect(fakeServer.requests[0].method).toEqual('MKCOL');
+ expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9/new%20dir');
+
+ return respondAndCheckStatus(promise, 201);
+ });
+ it('rejects promise when an error occurred', function() {
+ var promise = client.createDirectory('path/to space/文件夹/new dir');
+ return respondAndCheckError(promise, 404);
+ });
+ it('throws exception if arguments are missing', function() {
+ // TODO
+ });
+ });
+
+ describe('deletion', function() {
+ it('sends DELETE with specified path', function() {
+ var promise = client.remove('path/to space/文件夹');
+
+ expect(fakeServer.requests.length).toEqual(1);
+ expect(fakeServer.requests[0].method).toEqual('DELETE');
+ expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
+
+ return respondAndCheckStatus(promise, 201);
+ });
+ it('rejects promise when an error occurred', function() {
+ var promise = client.remove('path/to space/文件夹');
+ return respondAndCheckError(promise, 404);
+ });
+ it('throws exception if arguments are missing', function() {
+ // TODO
+ });
+ });
+
+ describe('move', function() {
+ it('sends MOVE with specified paths with fail on overwrite by default', function() {
+ var promise = client.move(
+ 'path/to space/文件夹',
+ 'path/to space/anotherdir/文件夹'
+ );
+
+ expect(fakeServer.requests.length).toEqual(1);
+ expect(fakeServer.requests[0].method).toEqual('MOVE');
+ expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
+ expect(fakeServer.requests[0].requestHeaders.Destination)
+ .toEqual(baseUrl + 'path/to%20space/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9');
+ expect(fakeServer.requests[0].requestHeaders.Overwrite)
+ .toEqual('F');
+
+ return respondAndCheckStatus(promise, 201);
+ });
+ it('sends MOVE with silent overwrite mode when specified', function() {
+ var promise = client.move(
+ 'path/to space/文件夹',
+ 'path/to space/anotherdir/文件夹',
+ {allowOverwrite: true}
+ );
+
+ expect(fakeServer.requests.length).toEqual(1);
+ expect(fakeServer.requests[0].method).toEqual('MOVE');
+ expect(fakeServer.requests[0].url).toEqual(baseUrl + 'path/to%20space/%E6%96%87%E4%BB%B6%E5%A4%B9');
+ expect(fakeServer.requests[0].requestHeaders.Destination)
+ .toEqual(baseUrl + 'path/to%20space/anotherdir/%E6%96%87%E4%BB%B6%E5%A4%B9');
+ expect(fakeServer.requests[0].requestHeaders.Overwrite)
+ .not.toBeDefined();
+
+ return respondAndCheckStatus(promise, 201);
+ });
+ it('rejects promise when an error occurred', function() {
+ var promise = client.move(
+ 'path/to space/文件夹',
+ 'path/to space/anotherdir/文件夹',
+ {allowOverwrite: true}
+ );
+ return respondAndCheckError(promise, 404);
+ });
+ it('throws exception if arguments are missing', function() {
+ // TODO
+ });
+ });
+});
diff --git a/core/l10n/hy.js b/core/l10n/hy.js
index 841c9a0d4e7..a09ee8f0110 100644
--- a/core/l10n/hy.js
+++ b/core/l10n/hy.js
@@ -46,6 +46,7 @@ OC.L10N.register(
"Very weak password" : "Շատ թույլ գաղտնաբառ",
"Weak password" : "Թույլ գաղտնաբառ",
"Good password" : "Լավ գաղտնաբառ",
+ "Error" : "Սխալ",
"Share link" : "Կիսվել հղմամբ",
"Link" : "Հղում",
"Password" : "Գաղտնաբառ",
@@ -57,6 +58,7 @@ OC.L10N.register(
"Delete" : "Ջնջել",
"Add" : "Ավելացնել",
"New password" : "Նոր գաղտնաբառ",
- "Personal" : "Անձնական"
+ "Personal" : "Անձնական",
+ "Username" : "Օգտանուն"
},
"nplurals=2; plural=(n != 1);");
diff --git a/core/l10n/hy.json b/core/l10n/hy.json
index 722975e72e3..52bc1322a8e 100644
--- a/core/l10n/hy.json
+++ b/core/l10n/hy.json
@@ -44,6 +44,7 @@
"Very weak password" : "Շատ թույլ գաղտնաբառ",
"Weak password" : "Թույլ գաղտնաբառ",
"Good password" : "Լավ գաղտնաբառ",
+ "Error" : "Սխալ",
"Share link" : "Կիսվել հղմամբ",
"Link" : "Հղում",
"Password" : "Գաղտնաբառ",
@@ -55,6 +56,7 @@
"Delete" : "Ջնջել",
"Add" : "Ավելացնել",
"New password" : "Նոր գաղտնաբառ",
- "Personal" : "Անձնական"
+ "Personal" : "Անձնական",
+ "Username" : "Օգտանուն"
},"pluralForm" :"nplurals=2; plural=(n != 1);"
} \ No newline at end of file
diff --git a/core/l10n/lt_LT.js b/core/l10n/lt_LT.js
index 1b9d4842913..829e6f9e957 100644
--- a/core/l10n/lt_LT.js
+++ b/core/l10n/lt_LT.js
@@ -6,6 +6,7 @@ OC.L10N.register(
"Turned on maintenance mode" : "Įjungta priežiūros veiksena",
"Turned off maintenance mode" : "Išjungta priežiūros veiksena",
"Maintenance mode is kept active" : "Priežiūros veiksena yra aktyvi",
+ "Updating database schema" : "Atnaujinama duomenų bazės struktūra",
"Updated database" : "Atnaujinta duomenų bazė",
"Checked database schema update" : "Tikrinama duomenų bazės struktūra",
"Checked database schema update for apps" : "Tikrinama duomenų bazės struktūra įskiepiams",
diff --git a/core/l10n/lt_LT.json b/core/l10n/lt_LT.json
index 8df5dc1ff48..f67b9d6cc00 100644
--- a/core/l10n/lt_LT.json
+++ b/core/l10n/lt_LT.json
@@ -4,6 +4,7 @@
"Turned on maintenance mode" : "Įjungta priežiūros veiksena",
"Turned off maintenance mode" : "Išjungta priežiūros veiksena",
"Maintenance mode is kept active" : "Priežiūros veiksena yra aktyvi",
+ "Updating database schema" : "Atnaujinama duomenų bazės struktūra",
"Updated database" : "Atnaujinta duomenų bazė",
"Checked database schema update" : "Tikrinama duomenų bazės struktūra",
"Checked database schema update for apps" : "Tikrinama duomenų bazės struktūra įskiepiams",
diff --git a/core/l10n/nds.js b/core/l10n/nds.js
index ed29474b797..2051b30361a 100644
--- a/core/l10n/nds.js
+++ b/core/l10n/nds.js
@@ -104,7 +104,11 @@ OC.L10N.register(
"Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "Dein Webserver ist für die Dateisynchronisierung noch nicht ordentlich eingerichtet, da die WebDAV-Schnittstelle fehlerhaft scheint. ",
"This server has no working Internet connection. This means that some of the features like mounting external storage, notifications about updates or installation of third-party apps will not work. Accessing files remotely and sending of notification emails might not work, either. We suggest to enable Internet connection for this server if you want to have all features." : "Dieser Server ist nicht mit dem Internet verbunden. Das bedeutet, dass manche Funktionen, wie das Einbinden von externen Speichern, Benachrichtigungen über Aktualisierungen oder die Installation von Drittanbieter Apps nicht zur Verfügung stehen. Auch der Fernzugriff auf Dateien und das Senden von Hinweis-E-Mails könnte nicht funktionieren. Wir empfehlen die Internetverbindung dieses Servers zu aktivieren, wenn Du diese Funktionen nutzen möchtest.",
"Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "Der Zugriff auf Dein Datenverzeichnis und Deine Dateien ist über das Internet vermutlich möglich. Die .htaccess-Datei greift nicht. Wir empfehlen dringend den Webserver derart zu konfigurieren, dass das Datenverzeichnis nicht mehr zugreifbar ist oder das Datenverzeichnis nach außerhalb des Dokumentenwurzelverzeichnisses des Webservers zu verschieben.",
+ "Error" : "Fehler",
"Password" : "Passwort",
+ "Send" : "Senden",
+ "can share" : "kann teilen",
+ "can edit" : "kann editieren",
"Share" : "Teilen",
"Delete" : "Löschen",
"Personal" : "Persönlich",
diff --git a/core/l10n/nds.json b/core/l10n/nds.json
index bc8f8d2510c..cb2f908da76 100644
--- a/core/l10n/nds.json
+++ b/core/l10n/nds.json
@@ -102,7 +102,11 @@
"Your web server is not yet set up properly to allow file synchronization because the WebDAV interface seems to be broken." : "Dein Webserver ist für die Dateisynchronisierung noch nicht ordentlich eingerichtet, da die WebDAV-Schnittstelle fehlerhaft scheint. ",
"This server has no working Internet connection. This means that some of the features like mounting external storage, notifications about updates or installation of third-party apps will not work. Accessing files remotely and sending of notification emails might not work, either. We suggest to enable Internet connection for this server if you want to have all features." : "Dieser Server ist nicht mit dem Internet verbunden. Das bedeutet, dass manche Funktionen, wie das Einbinden von externen Speichern, Benachrichtigungen über Aktualisierungen oder die Installation von Drittanbieter Apps nicht zur Verfügung stehen. Auch der Fernzugriff auf Dateien und das Senden von Hinweis-E-Mails könnte nicht funktionieren. Wir empfehlen die Internetverbindung dieses Servers zu aktivieren, wenn Du diese Funktionen nutzen möchtest.",
"Your data directory and your files are probably accessible from the Internet. The .htaccess file is not working. We strongly suggest that you configure your web server in a way that the data directory is no longer accessible or you move the data directory outside the web server document root." : "Der Zugriff auf Dein Datenverzeichnis und Deine Dateien ist über das Internet vermutlich möglich. Die .htaccess-Datei greift nicht. Wir empfehlen dringend den Webserver derart zu konfigurieren, dass das Datenverzeichnis nicht mehr zugreifbar ist oder das Datenverzeichnis nach außerhalb des Dokumentenwurzelverzeichnisses des Webservers zu verschieben.",
+ "Error" : "Fehler",
"Password" : "Passwort",
+ "Send" : "Senden",
+ "can share" : "kann teilen",
+ "can edit" : "kann editieren",
"Share" : "Teilen",
"Delete" : "Löschen",
"Personal" : "Persönlich",
diff --git a/core/l10n/tr.js b/core/l10n/tr.js
index 257550ecd4b..9a92eac50a7 100644
--- a/core/l10n/tr.js
+++ b/core/l10n/tr.js
@@ -6,9 +6,12 @@ OC.L10N.register(
"Turned on maintenance mode" : "Bakım kipi etkinleştirildi",
"Turned off maintenance mode" : "Bakım kipi kapatıldı",
"Maintenance mode is kept active" : "Bakım kipi etkin tutuldu",
+ "Updating database schema" : "Veritabanı şeması güncelleniyor",
"Updated database" : "Veritabanı güncellendi",
+ "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Veritabanı şeması güncellenebilirliği denetleniyor (Veritabanının büyüklüğüne göre uzun sürebilir)",
"Checked database schema update" : "Veritabanı şema güncellemesi denetlendi",
- "Checking updates of apps" : "Uygulamaların güncellemelerini kontrol et",
+ "Checking updates of apps" : "Uygulamaların güncellemeleri denetleniyor",
+ "Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)" : "%s için veritabanı güncellenebilirliği denetleniyor (Veritabanının büyüklüğüne göre uzun sürebilir)",
"Checked database schema update for apps" : "Uygulamalar için veritabanı şema güncellemesi denetlendi",
"Updated \"%s\" to %s" : "\"%s\", %s sürümüne güncellendi",
"Repair warning: " : "Onarım uyarısı:",
@@ -24,6 +27,7 @@ OC.L10N.register(
"No image or file provided" : "Resim veya dosya belirtilmedi",
"Unknown filetype" : "Bilinmeyen dosya türü",
"Invalid image" : "Geçersiz resim",
+ "An error occurred. Please contact your admin." : "Bir hata oluştu. Lütfen yöneticinize başvurun.",
"No temporary profile picture available, try again" : "Kullanılabilir geçici profil resmi yok, tekrar deneyin",
"No crop data provided" : "Kesme verisi sağlanmamış",
"No valid crop data provided" : "Geçerli kırpma verisi sağlanmadı",
@@ -111,6 +115,7 @@ OC.L10N.register(
"/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "Güvenlik sebepleri ile şiddetle kaçınılması gereken /dev/urandom PHP tarafından okunamıyor. Daha fazla bilgi <a href=\"{docLink}\">belgelendirmemizde</a> bulunabilir.",
"Your PHP version ({version}) is no longer <a href=\"{phpLink}\">supported by PHP</a>. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by PHP." : "Kullandığınız PHP sürümü ({version}) artık <a href=\"{phpLink}\">PHP tarafından desteklenmiyor</a>. PHP tarafından sağlanan performans ve güvenlik güncellemelerinden faydalanmak için PHP sürümünüzü güncellemenizi öneririz.",
"The reverse proxy headers configuration is incorrect, or you are accessing ownCloud from a trusted proxy. If you are not accessing ownCloud from a trusted proxy, this is a security issue and can allow an attacker to spoof their IP address as visible to ownCloud. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "Ters vekil sunucu başlık yapılandırması hatalı veya ownCloud'a güvenilen bir vekil sunucusundan erişiyorsunuz. ownCloud'a güvenilen bir vekil sunucusundan erişmiyorsanız bu bir güvenlik problemidir ve bir saldırganın IP adresinizi taklit etmesine izin verebilir. Ayrıntılı bilgiyi <a href=\"{docLink}\">belgelendirmemizde</a> bulabilirsiniz.",
+ "Memcached is configured as distributed cache, but the wrong PHP module \"memcache\" is installed. \\OC\\Memcache\\Memcached only supports \"memcached\" and not \"memcache\". See the <a href=\"{wikiLink}\">memcached wiki about both modules</a>." : "Memcached ayrılmış önbellek olarak yapılandırıldı, ancak yanlış PHP modülü \"memcache\" olarak yüklendi. \\OC\\Memcache\\Memcached sadece \"memcached\" olarak desteklenir, \"memcache\" olarak kullanamazsınız. <a href=\"{wikiLink}\">memcached wiki about both modules</a> linkine bakınız.",
"Error occurred while checking server setup" : "Sunucu yapılandırması denetlenirken hata oluştu",
"The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" HTTP başlığı \"{expected}\" ile eşleşmek üzere yapılandırılmamış. Bu muhtemel bir güvenlik veya gizlilik riski olduğundan bu ayarı düzeltmenizi öneririz.",
"The \"Strict-Transport-Security\" HTTP header is not configured to least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our <a href=\"{docUrl}\">security tips</a>." : "\"Strict-Transport-Security\" HTTP başlığı en az \"{seconds}\" saniye olarak ayarlanmış. İyileştirilmiş güvenlik için <a href=\"{docUrl}\">güvenlik ipuçlarımızda</a> belirtilen HSTS etkinleştirmesini öneririz.",
@@ -172,7 +177,9 @@ OC.L10N.register(
"Hello {name}" : "Merhaba {name}",
"_download %n file_::_download %n files_" : ["%n dosya indir","%n dosya indir"],
"{version} is available. Get more information on how to update." : "Sürüm {version} hazır. Nasıl güncelleyeceğinizle ilgili daha fazla bilgi alın.",
+ "The upgrade is in progress, leaving this page might interrupt the process in some environments." : "Güncelleme yapılıyor, sayfadan ayrılmak bazı işlemleri kesebilir.",
"Updating {productName} to version {version}, this may take a while." : "{productName}, {version} sürümüne güncelleniyor, bu biraz zaman alabilir.",
+ "An error occurred." : "Bir hata oluştu",
"Please reload the page." : "Lütfen sayfayı yeniden yükleyin.",
"The update was unsuccessful. " : "Güncelleştirme başarısız.",
"The update was successful. There were warnings." : "Güncelleme başarılı. Uyarılar mevcut.",
@@ -262,6 +269,7 @@ OC.L10N.register(
"Contact your system administrator if this message persists or appeared unexpectedly." : "Eğer bu ileti görünmeye devam ederse veya beklenmedik şekilde ortaya çıkmışsa sistem yöneticinizle iletişime geçin.",
"Thank you for your patience." : "Sabrınız için teşekkür ederiz.",
"You are accessing the server from an untrusted domain." : "Sunucuya güvenilmeyen bir alan adından ulaşıyorsunuz.",
+ "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Lütfen yöneticiniz ile iletişime geçin. Eğer bu örneğin bir yöneticisi iseniz, config/config.php dosyası içerisindeki \"trusted_domain\" ayarını yapılandırın. Bu yapılandırmanın bir örneği config/config.sample.php dosyasında verilmiştir.",
"Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Yapılandırmanıza bağlı olarak, bir yönetici olarak bu alan adına güvenmek için aşağıdaki düğmeyi de kullanabilirsiniz.",
"Add \"%s\" as trusted domain" : "\"%s\" alan adını güvenilir olarak ekle",
"App update required" : "Uygulama güncellemesi gerekli",
diff --git a/core/l10n/tr.json b/core/l10n/tr.json
index 66f3a83f7ed..bb547a1a5f3 100644
--- a/core/l10n/tr.json
+++ b/core/l10n/tr.json
@@ -4,9 +4,12 @@
"Turned on maintenance mode" : "Bakım kipi etkinleştirildi",
"Turned off maintenance mode" : "Bakım kipi kapatıldı",
"Maintenance mode is kept active" : "Bakım kipi etkin tutuldu",
+ "Updating database schema" : "Veritabanı şeması güncelleniyor",
"Updated database" : "Veritabanı güncellendi",
+ "Checking whether the database schema can be updated (this can take a long time depending on the database size)" : "Veritabanı şeması güncellenebilirliği denetleniyor (Veritabanının büyüklüğüne göre uzun sürebilir)",
"Checked database schema update" : "Veritabanı şema güncellemesi denetlendi",
- "Checking updates of apps" : "Uygulamaların güncellemelerini kontrol et",
+ "Checking updates of apps" : "Uygulamaların güncellemeleri denetleniyor",
+ "Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)" : "%s için veritabanı güncellenebilirliği denetleniyor (Veritabanının büyüklüğüne göre uzun sürebilir)",
"Checked database schema update for apps" : "Uygulamalar için veritabanı şema güncellemesi denetlendi",
"Updated \"%s\" to %s" : "\"%s\", %s sürümüne güncellendi",
"Repair warning: " : "Onarım uyarısı:",
@@ -22,6 +25,7 @@
"No image or file provided" : "Resim veya dosya belirtilmedi",
"Unknown filetype" : "Bilinmeyen dosya türü",
"Invalid image" : "Geçersiz resim",
+ "An error occurred. Please contact your admin." : "Bir hata oluştu. Lütfen yöneticinize başvurun.",
"No temporary profile picture available, try again" : "Kullanılabilir geçici profil resmi yok, tekrar deneyin",
"No crop data provided" : "Kesme verisi sağlanmamış",
"No valid crop data provided" : "Geçerli kırpma verisi sağlanmadı",
@@ -109,6 +113,7 @@
"/dev/urandom is not readable by PHP which is highly discouraged for security reasons. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "Güvenlik sebepleri ile şiddetle kaçınılması gereken /dev/urandom PHP tarafından okunamıyor. Daha fazla bilgi <a href=\"{docLink}\">belgelendirmemizde</a> bulunabilir.",
"Your PHP version ({version}) is no longer <a href=\"{phpLink}\">supported by PHP</a>. We encourage you to upgrade your PHP version to take advantage of performance and security updates provided by PHP." : "Kullandığınız PHP sürümü ({version}) artık <a href=\"{phpLink}\">PHP tarafından desteklenmiyor</a>. PHP tarafından sağlanan performans ve güvenlik güncellemelerinden faydalanmak için PHP sürümünüzü güncellemenizi öneririz.",
"The reverse proxy headers configuration is incorrect, or you are accessing ownCloud from a trusted proxy. If you are not accessing ownCloud from a trusted proxy, this is a security issue and can allow an attacker to spoof their IP address as visible to ownCloud. Further information can be found in our <a href=\"{docLink}\">documentation</a>." : "Ters vekil sunucu başlık yapılandırması hatalı veya ownCloud'a güvenilen bir vekil sunucusundan erişiyorsunuz. ownCloud'a güvenilen bir vekil sunucusundan erişmiyorsanız bu bir güvenlik problemidir ve bir saldırganın IP adresinizi taklit etmesine izin verebilir. Ayrıntılı bilgiyi <a href=\"{docLink}\">belgelendirmemizde</a> bulabilirsiniz.",
+ "Memcached is configured as distributed cache, but the wrong PHP module \"memcache\" is installed. \\OC\\Memcache\\Memcached only supports \"memcached\" and not \"memcache\". See the <a href=\"{wikiLink}\">memcached wiki about both modules</a>." : "Memcached ayrılmış önbellek olarak yapılandırıldı, ancak yanlış PHP modülü \"memcache\" olarak yüklendi. \\OC\\Memcache\\Memcached sadece \"memcached\" olarak desteklenir, \"memcache\" olarak kullanamazsınız. <a href=\"{wikiLink}\">memcached wiki about both modules</a> linkine bakınız.",
"Error occurred while checking server setup" : "Sunucu yapılandırması denetlenirken hata oluştu",
"The \"{header}\" HTTP header is not configured to equal to \"{expected}\". This is a potential security or privacy risk and we recommend adjusting this setting." : "\"{header}\" HTTP başlığı \"{expected}\" ile eşleşmek üzere yapılandırılmamış. Bu muhtemel bir güvenlik veya gizlilik riski olduğundan bu ayarı düzeltmenizi öneririz.",
"The \"Strict-Transport-Security\" HTTP header is not configured to least \"{seconds}\" seconds. For enhanced security we recommend enabling HSTS as described in our <a href=\"{docUrl}\">security tips</a>." : "\"Strict-Transport-Security\" HTTP başlığı en az \"{seconds}\" saniye olarak ayarlanmış. İyileştirilmiş güvenlik için <a href=\"{docUrl}\">güvenlik ipuçlarımızda</a> belirtilen HSTS etkinleştirmesini öneririz.",
@@ -170,7 +175,9 @@
"Hello {name}" : "Merhaba {name}",
"_download %n file_::_download %n files_" : ["%n dosya indir","%n dosya indir"],
"{version} is available. Get more information on how to update." : "Sürüm {version} hazır. Nasıl güncelleyeceğinizle ilgili daha fazla bilgi alın.",
+ "The upgrade is in progress, leaving this page might interrupt the process in some environments." : "Güncelleme yapılıyor, sayfadan ayrılmak bazı işlemleri kesebilir.",
"Updating {productName} to version {version}, this may take a while." : "{productName}, {version} sürümüne güncelleniyor, bu biraz zaman alabilir.",
+ "An error occurred." : "Bir hata oluştu",
"Please reload the page." : "Lütfen sayfayı yeniden yükleyin.",
"The update was unsuccessful. " : "Güncelleştirme başarısız.",
"The update was successful. There were warnings." : "Güncelleme başarılı. Uyarılar mevcut.",
@@ -260,6 +267,7 @@
"Contact your system administrator if this message persists or appeared unexpectedly." : "Eğer bu ileti görünmeye devam ederse veya beklenmedik şekilde ortaya çıkmışsa sistem yöneticinizle iletişime geçin.",
"Thank you for your patience." : "Sabrınız için teşekkür ederiz.",
"You are accessing the server from an untrusted domain." : "Sunucuya güvenilmeyen bir alan adından ulaşıyorsunuz.",
+ "Please contact your administrator. If you are an administrator of this instance, configure the \"trusted_domains\" setting in config/config.php. An example configuration is provided in config/config.sample.php." : "Lütfen yöneticiniz ile iletişime geçin. Eğer bu örneğin bir yöneticisi iseniz, config/config.php dosyası içerisindeki \"trusted_domain\" ayarını yapılandırın. Bu yapılandırmanın bir örneği config/config.sample.php dosyasında verilmiştir.",
"Depending on your configuration, as an administrator you might also be able to use the button below to trust this domain." : "Yapılandırmanıza bağlı olarak, bir yönetici olarak bu alan adına güvenmek için aşağıdaki düğmeyi de kullanabilirsiniz.",
"Add \"%s\" as trusted domain" : "\"%s\" alan adını güvenilir olarak ekle",
"App update required" : "Uygulama güncellemesi gerekli",
diff --git a/core/vendor/.gitignore b/core/vendor/.gitignore
index bcbb59b6f24..09b6a47c72d 100644
--- a/core/vendor/.gitignore
+++ b/core/vendor/.gitignore
@@ -122,3 +122,14 @@ bootstrap/js/*
# backbone
backbone/backbone-min*
+
+# davclient.js
+davclient.js/**
+!davclient.js/lib/*
+!davclient.js/LICENSE
+
+# es6-promise
+es6-promise/**
+!es6-promise/LICENSE
+!es6-promise/dist/es6-promise.js
+
diff --git a/core/vendor/davclient.js/LICENSE b/core/vendor/davclient.js/LICENSE
new file mode 100644
index 00000000000..fd7293e8f32
--- /dev/null
+++ b/core/vendor/davclient.js/LICENSE
@@ -0,0 +1,27 @@
+Copyright (C) 2013-2014 fruux GmbH (https://fruux.com/)
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name Sabre nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
diff --git a/core/vendor/davclient.js/lib/client.js b/core/vendor/davclient.js/lib/client.js
new file mode 100644
index 00000000000..121b5dcab5f
--- /dev/null
+++ b/core/vendor/davclient.js/lib/client.js
@@ -0,0 +1,296 @@
+if (typeof dav == 'undefined') { dav = {}; };
+
+dav.Client = function(options) {
+ var i;
+ for(i in options) {
+ this[i] = options[i];
+ }
+
+};
+
+dav.Client.prototype = {
+
+ baseUrl : null,
+
+ userName : null,
+
+ password : null,
+
+
+ xmlNamespaces : {
+ 'DAV:' : 'd'
+ },
+
+ /**
+ * Generates a propFind request.
+ *
+ * @param {string} url Url to do the propfind request on
+ * @param {Array} properties List of properties to retrieve.
+ * @return {Promise}
+ */
+ propFind : function(url, properties, depth) {
+
+ if(typeof depth == "undefined") {
+ depth = 0;
+ }
+
+ var headers = {
+ Depth : depth,
+ 'Content-Type' : 'application/xml; charset=utf-8'
+ };
+
+ var body =
+ '<?xml version="1.0"?>\n' +
+ '<d:propfind ';
+ var namespace;
+ for (namespace in this.xmlNamespaces) {
+ body += ' xmlns:' + this.xmlNamespaces[namespace] + '="' + namespace + '"';
+ }
+ body += '>\n' +
+ ' <d:prop>\n';
+
+ for(var ii in properties) {
+
+ var property = this.parseClarkNotation(properties[ii]);
+ if (this.xmlNamespaces[property.namespace]) {
+ body+=' <' + this.xmlNamespaces[property.namespace] + ':' + property.name + ' />\n';
+ } else {
+ body+=' <x:' + property.name + ' xmlns:x="' + property.namespace + '" />\n';
+ }
+
+ }
+ body+=' </d:prop>\n';
+ body+='</d:propfind>';
+
+ return this.request('PROPFIND', url, headers, body).then(
+ function(result) {
+
+ var resultBody = this.parseMultiStatus(result.body);
+ if (depth===0) {
+ return {
+ status: result.status,
+ body: resultBody[0],
+ xhr: result.xhr
+ };
+ } else {
+ return {
+ status: result.status,
+ body: resultBody,
+ xhr: result.xhr
+ };
+ }
+
+ }.bind(this)
+ );
+
+ },
+
+ /**
+ * Performs a HTTP request, and returns a Promise
+ *
+ * @param {string} method HTTP method
+ * @param {string} url Relative or absolute url
+ * @param {Object} headers HTTP headers as an object.
+ * @param {string} body HTTP request body.
+ * @return {Promise}
+ */
+ request : function(method, url, headers, body) {
+
+ var xhr = this.xhrProvider();
+
+ if (this.userName) {
+ headers['Authorization'] = 'Basic ' + btoa(this.userName + ':' + this.password);
+ // xhr.open(method, this.resolveUrl(url), true, this.userName, this.password);
+ }
+ xhr.open(method, this.resolveUrl(url), true);
+ var ii;
+ for(ii in headers) {
+ xhr.setRequestHeader(ii, headers[ii]);
+ }
+ xhr.send(body);
+
+ return new Promise(function(fulfill, reject) {
+
+ xhr.onreadystatechange = function() {
+
+ if (xhr.readyState !== 4) {
+ return;
+ }
+
+ fulfill({
+ body: xhr.response,
+ status: xhr.status,
+ xhr: xhr
+ });
+
+ };
+
+ xhr.ontimeout = function() {
+
+ reject(new Error('Timeout exceeded'));
+
+ };
+
+ });
+
+ },
+
+ /**
+ * Returns an XMLHttpRequest object.
+ *
+ * This is in its own method, so it can be easily overridden.
+ *
+ * @return {XMLHttpRequest}
+ */
+ xhrProvider : function() {
+
+ return new XMLHttpRequest();
+
+ },
+
+
+ /**
+ * Parses a multi-status response body.
+ *
+ * @param {string} xmlBody
+ * @param {Array}
+ */
+ parseMultiStatus : function(xmlBody) {
+
+ var parser = new DOMParser();
+ var doc = parser.parseFromString(xmlBody, "application/xml");
+
+ var resolver = function(foo) {
+ var ii;
+ for(ii in this.xmlNamespaces) {
+ if (this.xmlNamespaces[ii] === foo) {
+ return ii;
+ }
+ }
+ }.bind(this);
+
+ var responseIterator = doc.evaluate('/d:multistatus/d:response', doc, resolver, XPathResult.ANY_TYPE, null);
+
+ var result = [];
+ var responseNode = responseIterator.iterateNext();
+
+ while(responseNode) {
+
+ var response = {
+ href : null,
+ propStat : []
+ };
+
+ response.href = doc.evaluate('string(d:href)', responseNode, resolver, XPathResult.ANY_TYPE, null).stringValue;
+
+ var propStatIterator = doc.evaluate('d:propstat', responseNode, resolver, XPathResult.ANY_TYPE, null);
+ var propStatNode = propStatIterator.iterateNext();
+
+ while(propStatNode) {
+
+ var propStat = {
+ status : doc.evaluate('string(d:status)', propStatNode, resolver, XPathResult.ANY_TYPE, null).stringValue,
+ properties : [],
+ };
+
+ var propIterator = doc.evaluate('d:prop/*', propStatNode, resolver, XPathResult.ANY_TYPE, null);
+
+ var propNode = propIterator.iterateNext();
+ while(propNode) {
+ var content = propNode.textContent;
+ if (propNode.childNodes && propNode.childNodes.length > 0 && propNode.childNodes[0].nodeType === 1) {
+ content = propNode.childNodes;
+ }
+
+ propStat.properties['{' + propNode.namespaceURI + '}' + propNode.localName] = content;
+ propNode = propIterator.iterateNext();
+
+ }
+ response.propStat.push(propStat);
+ propStatNode = propStatIterator.iterateNext();
+
+
+ }
+
+ result.push(response);
+ responseNode = responseIterator.iterateNext();
+
+ }
+
+ return result;
+
+ },
+
+ /**
+ * Takes a relative url, and maps it to an absolute url, using the baseUrl
+ *
+ * @param {string} url
+ * @return {string}
+ */
+ resolveUrl : function(url) {
+
+ // Note: this is rudamentary.. not sure yet if it handles every case.
+ if (/^https?:\/\//i.test(url)) {
+ // absolute
+ return url;
+ }
+
+ var baseParts = this.parseUrl(this.baseUrl);
+ if (url.charAt('/')) {
+ // Url starts with a slash
+ return baseParts.root + url;
+ }
+
+ // Url does not start with a slash, we need grab the base url right up until the last slash.
+ var newUrl = baseParts.root + '/';
+ if (baseParts.path.lastIndexOf('/')!==-1) {
+ newUrl = newUrl = baseParts.path.subString(0, baseParts.path.lastIndexOf('/')) + '/';
+ }
+ newUrl+=url;
+ return url;
+
+ },
+
+ /**
+ * Parses a url and returns its individual components.
+ *
+ * @param {String} url
+ * @return {Object}
+ */
+ parseUrl : function(url) {
+
+ var parts = url.match(/^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/);
+ var result = {
+ url : parts[0],
+ scheme : parts[1],
+ host : parts[3],
+ port : parts[4],
+ path : parts[5],
+ query : parts[6],
+ fragment : parts[7],
+ };
+ result.root =
+ result.scheme + '://' +
+ result.host +
+ (result.port ? ':' + result.port : '');
+
+ return result;
+
+ },
+
+ parseClarkNotation : function(propertyName) {
+
+ var result = propertyName.match(/^{([^}]+)}(.*)$/);
+ if (!result) {
+ return;
+ }
+
+ return {
+ name : result[2],
+ namespace : result[1]
+ };
+
+ }
+
+};
+
diff --git a/core/vendor/es6-promise/.bower.json b/core/vendor/es6-promise/.bower.json
new file mode 100644
index 00000000000..f8c28b04e53
--- /dev/null
+++ b/core/vendor/es6-promise/.bower.json
@@ -0,0 +1,40 @@
+{
+ "name": "es6-promise",
+ "namespace": "Promise",
+ "version": "2.3.0",
+ "description": "A polyfill for ES6-style Promises, tracking rsvp",
+ "authors": [
+ "Stefan Penner <stefan.penner@gmail.com>"
+ ],
+ "main": "dist/es6-promise.js",
+ "keywords": [
+ "promise"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/jakearchibald/ES6-Promises.git"
+ },
+ "bugs": {
+ "url": "https://github.com/jakearchibald/ES6-Promises/issues"
+ },
+ "license": "MIT",
+ "ignore": [
+ "node_modules",
+ "bower_components",
+ "test",
+ "tests",
+ "vendor",
+ "tasks"
+ ],
+ "homepage": "https://github.com/jakearchibald/es6-promise",
+ "_release": "2.3.0",
+ "_resolution": {
+ "type": "version",
+ "tag": "2.3.0",
+ "commit": "fcbab11a1a981eb2290bfff89017cb764335a2a5"
+ },
+ "_source": "https://github.com/jakearchibald/es6-promise.git",
+ "_target": "~2.3.0",
+ "_originalSource": "https://github.com/jakearchibald/es6-promise.git",
+ "_direct": true
+} \ No newline at end of file
diff --git a/core/vendor/es6-promise/.npmignore b/core/vendor/es6-promise/.npmignore
new file mode 100644
index 00000000000..7a758111e9e
--- /dev/null
+++ b/core/vendor/es6-promise/.npmignore
@@ -0,0 +1,11 @@
+/node_modules/
+/tmp
+/tasks
+/test
+/vendor
+/.jshintrc
+/.npmignore
+/.travis.yml
+/Gruntfile.js
+/component.json
+/index.html
diff --git a/core/vendor/es6-promise/.release.json b/core/vendor/es6-promise/.release.json
new file mode 100644
index 00000000000..dee8cbc5d92
--- /dev/null
+++ b/core/vendor/es6-promise/.release.json
@@ -0,0 +1,17 @@
+{
+ "non-interactive": true,
+ "dry-run": false,
+ "verbose": false,
+ "force": false,
+ "pkgFiles": ["package.json", "bower.json"],
+ "increment": "patch",
+ "commitMessage": "Release %s",
+ "tagName": "%s",
+ "tagAnnotation": "Release %s",
+ "buildCommand": "npm run-script build-all",
+ "distRepo": "git@github.com:components/rsvp.js.git",
+ "distStageDir": "tmp/stage",
+ "distBase": "dist",
+ "distFiles": ["**/*", "../package.json", "../bower.json"],
+ "publish": false
+}
diff --git a/core/vendor/es6-promise/.spmignore b/core/vendor/es6-promise/.spmignore
new file mode 100644
index 00000000000..7a758111e9e
--- /dev/null
+++ b/core/vendor/es6-promise/.spmignore
@@ -0,0 +1,11 @@
+/node_modules/
+/tmp
+/tasks
+/test
+/vendor
+/.jshintrc
+/.npmignore
+/.travis.yml
+/Gruntfile.js
+/component.json
+/index.html
diff --git a/core/vendor/es6-promise/LICENSE b/core/vendor/es6-promise/LICENSE
new file mode 100644
index 00000000000..954ec5992df
--- /dev/null
+++ b/core/vendor/es6-promise/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/core/vendor/es6-promise/dist/es6-promise.js b/core/vendor/es6-promise/dist/es6-promise.js
new file mode 100644
index 00000000000..aff0482ee5e
--- /dev/null
+++ b/core/vendor/es6-promise/dist/es6-promise.js
@@ -0,0 +1,972 @@
+/*!
+ * @overview es6-promise - a tiny implementation of Promises/A+.
+ * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
+ * @license Licensed under MIT license
+ * See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE
+ * @version 2.3.0
+ */
+
+(function() {
+ "use strict";
+ function lib$es6$promise$utils$$objectOrFunction(x) {
+ return typeof x === 'function' || (typeof x === 'object' && x !== null);
+ }
+
+ function lib$es6$promise$utils$$isFunction(x) {
+ return typeof x === 'function';
+ }
+
+ function lib$es6$promise$utils$$isMaybeThenable(x) {
+ return typeof x === 'object' && x !== null;
+ }
+
+ var lib$es6$promise$utils$$_isArray;
+ if (!Array.isArray) {
+ lib$es6$promise$utils$$_isArray = function (x) {
+ return Object.prototype.toString.call(x) === '[object Array]';
+ };
+ } else {
+ lib$es6$promise$utils$$_isArray = Array.isArray;
+ }
+
+ var lib$es6$promise$utils$$isArray = lib$es6$promise$utils$$_isArray;
+ var lib$es6$promise$asap$$len = 0;
+ var lib$es6$promise$asap$$toString = {}.toString;
+ var lib$es6$promise$asap$$vertxNext;
+ var lib$es6$promise$asap$$customSchedulerFn;
+
+ var lib$es6$promise$asap$$asap = function asap(callback, arg) {
+ lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len] = callback;
+ lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len + 1] = arg;
+ lib$es6$promise$asap$$len += 2;
+ if (lib$es6$promise$asap$$len === 2) {
+ // If len is 2, that means that we need to schedule an async flush.
+ // If additional callbacks are queued before the queue is flushed, they
+ // will be processed by this flush that we are scheduling.
+ if (lib$es6$promise$asap$$customSchedulerFn) {
+ lib$es6$promise$asap$$customSchedulerFn(lib$es6$promise$asap$$flush);
+ } else {
+ lib$es6$promise$asap$$scheduleFlush();
+ }
+ }
+ }
+
+ function lib$es6$promise$asap$$setScheduler(scheduleFn) {
+ lib$es6$promise$asap$$customSchedulerFn = scheduleFn;
+ }
+
+ function lib$es6$promise$asap$$setAsap(asapFn) {
+ lib$es6$promise$asap$$asap = asapFn;
+ }
+
+ var lib$es6$promise$asap$$browserWindow = (typeof window !== 'undefined') ? window : undefined;
+ var lib$es6$promise$asap$$browserGlobal = lib$es6$promise$asap$$browserWindow || {};
+ var lib$es6$promise$asap$$BrowserMutationObserver = lib$es6$promise$asap$$browserGlobal.MutationObserver || lib$es6$promise$asap$$browserGlobal.WebKitMutationObserver;
+ var lib$es6$promise$asap$$isNode = typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';
+
+ // test for web worker but not in IE10
+ var lib$es6$promise$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' &&
+ typeof importScripts !== 'undefined' &&
+ typeof MessageChannel !== 'undefined';
+
+ // node
+ function lib$es6$promise$asap$$useNextTick() {
+ var nextTick = process.nextTick;
+ // node version 0.10.x displays a deprecation warning when nextTick is used recursively
+ // setImmediate should be used instead instead
+ var version = process.versions.node.match(/^(?:(\d+)\.)?(?:(\d+)\.)?(\*|\d+)$/);
+ if (Array.isArray(version) && version[1] === '0' && version[2] === '10') {
+ nextTick = setImmediate;
+ }
+ return function() {
+ nextTick(lib$es6$promise$asap$$flush);
+ };
+ }
+
+ // vertx
+ function lib$es6$promise$asap$$useVertxTimer() {
+ return function() {
+ lib$es6$promise$asap$$vertxNext(lib$es6$promise$asap$$flush);
+ };
+ }
+
+ function lib$es6$promise$asap$$useMutationObserver() {
+ var iterations = 0;
+ var observer = new lib$es6$promise$asap$$BrowserMutationObserver(lib$es6$promise$asap$$flush);
+ var node = document.createTextNode('');
+ observer.observe(node, { characterData: true });
+
+ return function() {
+ node.data = (iterations = ++iterations % 2);
+ };
+ }
+
+ // web worker
+ function lib$es6$promise$asap$$useMessageChannel() {
+ var channel = new MessageChannel();
+ channel.port1.onmessage = lib$es6$promise$asap$$flush;
+ return function () {
+ channel.port2.postMessage(0);
+ };
+ }
+
+ function lib$es6$promise$asap$$useSetTimeout() {
+ return function() {
+ setTimeout(lib$es6$promise$asap$$flush, 1);
+ };
+ }
+
+ var lib$es6$promise$asap$$queue = new Array(1000);
+ function lib$es6$promise$asap$$flush() {
+ for (var i = 0; i < lib$es6$promise$asap$$len; i+=2) {
+ var callback = lib$es6$promise$asap$$queue[i];
+ var arg = lib$es6$promise$asap$$queue[i+1];
+
+ callback(arg);
+
+ lib$es6$promise$asap$$queue[i] = undefined;
+ lib$es6$promise$asap$$queue[i+1] = undefined;
+ }
+
+ lib$es6$promise$asap$$len = 0;
+ }
+
+ function lib$es6$promise$asap$$attemptVertex() {
+ try {
+ var r = require;
+ var vertx = r('vertx');
+ lib$es6$promise$asap$$vertxNext = vertx.runOnLoop || vertx.runOnContext;
+ return lib$es6$promise$asap$$useVertxTimer();
+ } catch(e) {
+ return lib$es6$promise$asap$$useSetTimeout();
+ }
+ }
+
+ var lib$es6$promise$asap$$scheduleFlush;
+ // Decide what async method to use to triggering processing of queued callbacks:
+ if (lib$es6$promise$asap$$isNode) {
+ lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useNextTick();
+ } else if (lib$es6$promise$asap$$BrowserMutationObserver) {
+ lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMutationObserver();
+ } else if (lib$es6$promise$asap$$isWorker) {
+ lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMessageChannel();
+ } else if (lib$es6$promise$asap$$browserWindow === undefined && typeof require === 'function') {
+ lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$attemptVertex();
+ } else {
+ lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useSetTimeout();
+ }
+
+ function lib$es6$promise$$internal$$noop() {}
+
+ var lib$es6$promise$$internal$$PENDING = void 0;
+ var lib$es6$promise$$internal$$FULFILLED = 1;
+ var lib$es6$promise$$internal$$REJECTED = 2;
+
+ var lib$es6$promise$$internal$$GET_THEN_ERROR = new lib$es6$promise$$internal$$ErrorObject();
+
+ function lib$es6$promise$$internal$$selfFullfillment() {
+ return new TypeError("You cannot resolve a promise with itself");
+ }
+
+ function lib$es6$promise$$internal$$cannotReturnOwn() {
+ return new TypeError('A promises callback cannot return that same promise.');
+ }
+
+ function lib$es6$promise$$internal$$getThen(promise) {
+ try {
+ return promise.then;
+ } catch(error) {
+ lib$es6$promise$$internal$$GET_THEN_ERROR.error = error;
+ return lib$es6$promise$$internal$$GET_THEN_ERROR;
+ }
+ }
+
+ function lib$es6$promise$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) {
+ try {
+ then.call(value, fulfillmentHandler, rejectionHandler);
+ } catch(e) {
+ return e;
+ }
+ }
+
+ function lib$es6$promise$$internal$$handleForeignThenable(promise, thenable, then) {
+ lib$es6$promise$asap$$asap(function(promise) {
+ var sealed = false;
+ var error = lib$es6$promise$$internal$$tryThen(then, thenable, function(value) {
+ if (sealed) { return; }
+ sealed = true;
+ if (thenable !== value) {
+ lib$es6$promise$$internal$$resolve(promise, value);
+ } else {
+ lib$es6$promise$$internal$$fulfill(promise, value);
+ }
+ }, function(reason) {
+ if (sealed) { return; }
+ sealed = true;
+
+ lib$es6$promise$$internal$$reject(promise, reason);
+ }, 'Settle: ' + (promise._label || ' unknown promise'));
+
+ if (!sealed && error) {
+ sealed = true;
+ lib$es6$promise$$internal$$reject(promise, error);
+ }
+ }, promise);
+ }
+
+ function lib$es6$promise$$internal$$handleOwnThenable(promise, thenable) {
+ if (thenable._state === lib$es6$promise$$internal$$FULFILLED) {
+ lib$es6$promise$$internal$$fulfill(promise, thenable._result);
+ } else if (thenable._state === lib$es6$promise$$internal$$REJECTED) {
+ lib$es6$promise$$internal$$reject(promise, thenable._result);
+ } else {
+ lib$es6$promise$$internal$$subscribe(thenable, undefined, function(value) {
+ lib$es6$promise$$internal$$resolve(promise, value);
+ }, function(reason) {
+ lib$es6$promise$$internal$$reject(promise, reason);
+ });
+ }
+ }
+
+ function lib$es6$promise$$internal$$handleMaybeThenable(promise, maybeThenable) {
+ if (maybeThenable.constructor === promise.constructor) {
+ lib$es6$promise$$internal$$handleOwnThenable(promise, maybeThenable);
+ } else {
+ var then = lib$es6$promise$$internal$$getThen(maybeThenable);
+
+ if (then === lib$es6$promise$$internal$$GET_THEN_ERROR) {
+ lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$GET_THEN_ERROR.error);
+ } else if (then === undefined) {
+ lib$es6$promise$$internal$$fulfill(promise, maybeThenable);
+ } else if (lib$es6$promise$utils$$isFunction(then)) {
+ lib$es6$promise$$internal$$handleForeignThenable(promise, maybeThenable, then);
+ } else {
+ lib$es6$promise$$internal$$fulfill(promise, maybeThenable);
+ }
+ }
+ }
+
+ function lib$es6$promise$$internal$$resolve(promise, value) {
+ if (promise === value) {
+ lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$selfFullfillment());
+ } else if (lib$es6$promise$utils$$objectOrFunction(value)) {
+ lib$es6$promise$$internal$$handleMaybeThenable(promise, value);
+ } else {
+ lib$es6$promise$$internal$$fulfill(promise, value);
+ }
+ }
+
+ function lib$es6$promise$$internal$$publishRejection(promise) {
+ if (promise._onerror) {
+ promise._onerror(promise._result);
+ }
+
+ lib$es6$promise$$internal$$publish(promise);
+ }
+
+ function lib$es6$promise$$internal$$fulfill(promise, value) {
+ if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; }
+
+ promise._result = value;
+ promise._state = lib$es6$promise$$internal$$FULFILLED;
+
+ if (promise._subscribers.length !== 0) {
+ lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, promise);
+ }
+ }
+
+ function lib$es6$promise$$internal$$reject(promise, reason) {
+ if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; }
+ promise._state = lib$es6$promise$$internal$$REJECTED;
+ promise._result = reason;
+
+ lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publishRejection, promise);
+ }
+
+ function lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection) {
+ var subscribers = parent._subscribers;
+ var length = subscribers.length;
+
+ parent._onerror = null;
+
+ subscribers[length] = child;
+ subscribers[length + lib$es6$promise$$internal$$FULFILLED] = onFulfillment;
+ subscribers[length + lib$es6$promise$$internal$$REJECTED] = onRejection;
+
+ if (length === 0 && parent._state) {
+ lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, parent);
+ }
+ }
+
+ function lib$es6$promise$$internal$$publish(promise) {
+ var subscribers = promise._subscribers;
+ var settled = promise._state;
+
+ if (subscribers.length === 0) { return; }
+
+ var child, callback, detail = promise._result;
+
+ for (var i = 0; i < subscribers.length; i += 3) {
+ child = subscribers[i];
+ callback = subscribers[i + settled];
+
+ if (child) {
+ lib$es6$promise$$internal$$invokeCallback(settled, child, callback, detail);
+ } else {
+ callback(detail);
+ }
+ }
+
+ promise._subscribers.length = 0;
+ }
+
+ function lib$es6$promise$$internal$$ErrorObject() {
+ this.error = null;
+ }
+
+ var lib$es6$promise$$internal$$TRY_CATCH_ERROR = new lib$es6$promise$$internal$$ErrorObject();
+
+ function lib$es6$promise$$internal$$tryCatch(callback, detail) {
+ try {
+ return callback(detail);
+ } catch(e) {
+ lib$es6$promise$$internal$$TRY_CATCH_ERROR.error = e;
+ return lib$es6$promise$$internal$$TRY_CATCH_ERROR;
+ }
+ }
+
+ function lib$es6$promise$$internal$$invokeCallback(settled, promise, callback, detail) {
+ var hasCallback = lib$es6$promise$utils$$isFunction(callback),
+ value, error, succeeded, failed;
+
+ if (hasCallback) {
+ value = lib$es6$promise$$internal$$tryCatch(callback, detail);
+
+ if (value === lib$es6$promise$$internal$$TRY_CATCH_ERROR) {
+ failed = true;
+ error = value.error;
+ value = null;
+ } else {
+ succeeded = true;
+ }
+
+ if (promise === value) {
+ lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$cannotReturnOwn());
+ return;
+ }
+
+ } else {
+ value = detail;
+ succeeded = true;
+ }
+
+ if (promise._state !== lib$es6$promise$$internal$$PENDING) {
+ // noop
+ } else if (hasCallback && succeeded) {
+ lib$es6$promise$$internal$$resolve(promise, value);
+ } else if (failed) {
+ lib$es6$promise$$internal$$reject(promise, error);
+ } else if (settled === lib$es6$promise$$internal$$FULFILLED) {
+ lib$es6$promise$$internal$$fulfill(promise, value);
+ } else if (settled === lib$es6$promise$$internal$$REJECTED) {
+ lib$es6$promise$$internal$$reject(promise, value);
+ }
+ }
+
+ function lib$es6$promise$$internal$$initializePromise(promise, resolver) {
+ try {
+ resolver(function resolvePromise(value){
+ lib$es6$promise$$internal$$resolve(promise, value);
+ }, function rejectPromise(reason) {
+ lib$es6$promise$$internal$$reject(promise, reason);
+ });
+ } catch(e) {
+ lib$es6$promise$$internal$$reject(promise, e);
+ }
+ }
+
+ function lib$es6$promise$enumerator$$Enumerator(Constructor, input) {
+ var enumerator = this;
+
+ enumerator._instanceConstructor = Constructor;
+ enumerator.promise = new Constructor(lib$es6$promise$$internal$$noop);
+
+ if (enumerator._validateInput(input)) {
+ enumerator._input = input;
+ enumerator.length = input.length;
+ enumerator._remaining = input.length;
+
+ enumerator._init();
+
+ if (enumerator.length === 0) {
+ lib$es6$promise$$internal$$fulfill(enumerator.promise, enumerator._result);
+ } else {
+ enumerator.length = enumerator.length || 0;
+ enumerator._enumerate();
+ if (enumerator._remaining === 0) {
+ lib$es6$promise$$internal$$fulfill(enumerator.promise, enumerator._result);
+ }
+ }
+ } else {
+ lib$es6$promise$$internal$$reject(enumerator.promise, enumerator._validationError());
+ }
+ }
+
+ lib$es6$promise$enumerator$$Enumerator.prototype._validateInput = function(input) {
+ return lib$es6$promise$utils$$isArray(input);
+ };
+
+ lib$es6$promise$enumerator$$Enumerator.prototype._validationError = function() {
+ return new Error('Array Methods must be provided an Array');
+ };
+
+ lib$es6$promise$enumerator$$Enumerator.prototype._init = function() {
+ this._result = new Array(this.length);
+ };
+
+ var lib$es6$promise$enumerator$$default = lib$es6$promise$enumerator$$Enumerator;
+
+ lib$es6$promise$enumerator$$Enumerator.prototype._enumerate = function() {
+ var enumerator = this;
+
+ var length = enumerator.length;
+ var promise = enumerator.promise;
+ var input = enumerator._input;
+
+ for (var i = 0; promise._state === lib$es6$promise$$internal$$PENDING && i < length; i++) {
+ enumerator._eachEntry(input[i], i);
+ }
+ };
+
+ lib$es6$promise$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) {
+ var enumerator = this;
+ var c = enumerator._instanceConstructor;
+
+ if (lib$es6$promise$utils$$isMaybeThenable(entry)) {
+ if (entry.constructor === c && entry._state !== lib$es6$promise$$internal$$PENDING) {
+ entry._onerror = null;
+ enumerator._settledAt(entry._state, i, entry._result);
+ } else {
+ enumerator._willSettleAt(c.resolve(entry), i);
+ }
+ } else {
+ enumerator._remaining--;
+ enumerator._result[i] = entry;
+ }
+ };
+
+ lib$es6$promise$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) {
+ var enumerator = this;
+ var promise = enumerator.promise;
+
+ if (promise._state === lib$es6$promise$$internal$$PENDING) {
+ enumerator._remaining--;
+
+ if (state === lib$es6$promise$$internal$$REJECTED) {
+ lib$es6$promise$$internal$$reject(promise, value);
+ } else {
+ enumerator._result[i] = value;
+ }
+ }
+
+ if (enumerator._remaining === 0) {
+ lib$es6$promise$$internal$$fulfill(promise, enumerator._result);
+ }
+ };
+
+ lib$es6$promise$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) {
+ var enumerator = this;
+
+ lib$es6$promise$$internal$$subscribe(promise, undefined, function(value) {
+ enumerator._settledAt(lib$es6$promise$$internal$$FULFILLED, i, value);
+ }, function(reason) {
+ enumerator._settledAt(lib$es6$promise$$internal$$REJECTED, i, reason);
+ });
+ };
+ function lib$es6$promise$promise$all$$all(entries) {
+ return new lib$es6$promise$enumerator$$default(this, entries).promise;
+ }
+ var lib$es6$promise$promise$all$$default = lib$es6$promise$promise$all$$all;
+ function lib$es6$promise$promise$race$$race(entries) {
+ /*jshint validthis:true */
+ var Constructor = this;
+
+ var promise = new Constructor(lib$es6$promise$$internal$$noop);
+
+ if (!lib$es6$promise$utils$$isArray(entries)) {
+ lib$es6$promise$$internal$$reject(promise, new TypeError('You must pass an array to race.'));
+ return promise;
+ }
+
+ var length = entries.length;
+
+ function onFulfillment(value) {
+ lib$es6$promise$$internal$$resolve(promise, value);
+ }
+
+ function onRejection(reason) {
+ lib$es6$promise$$internal$$reject(promise, reason);
+ }
+
+ for (var i = 0; promise._state === lib$es6$promise$$internal$$PENDING && i < length; i++) {
+ lib$es6$promise$$internal$$subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection);
+ }
+
+ return promise;
+ }
+ var lib$es6$promise$promise$race$$default = lib$es6$promise$promise$race$$race;
+ function lib$es6$promise$promise$resolve$$resolve(object) {
+ /*jshint validthis:true */
+ var Constructor = this;
+
+ if (object && typeof object === 'object' && object.constructor === Constructor) {
+ return object;
+ }
+
+ var promise = new Constructor(lib$es6$promise$$internal$$noop);
+ lib$es6$promise$$internal$$resolve(promise, object);
+ return promise;
+ }
+ var lib$es6$promise$promise$resolve$$default = lib$es6$promise$promise$resolve$$resolve;
+ function lib$es6$promise$promise$reject$$reject(reason) {
+ /*jshint validthis:true */
+ var Constructor = this;
+ var promise = new Constructor(lib$es6$promise$$internal$$noop);
+ lib$es6$promise$$internal$$reject(promise, reason);
+ return promise;
+ }
+ var lib$es6$promise$promise$reject$$default = lib$es6$promise$promise$reject$$reject;
+
+ var lib$es6$promise$promise$$counter = 0;
+
+ function lib$es6$promise$promise$$needsResolver() {
+ throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
+ }
+
+ function lib$es6$promise$promise$$needsNew() {
+ throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
+ }
+
+ var lib$es6$promise$promise$$default = lib$es6$promise$promise$$Promise;
+ /**
+ Promise objects represent the eventual result of an asynchronous operation. The
+ primary way of interacting with a promise is through its `then` method, which
+ registers callbacks to receive either a promise's eventual value or the reason
+ why the promise cannot be fulfilled.
+
+ Terminology
+ -----------
+
+ - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
+ - `thenable` is an object or function that defines a `then` method.
+ - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
+ - `exception` is a value that is thrown using the throw statement.
+ - `reason` is a value that indicates why a promise was rejected.
+ - `settled` the final resting state of a promise, fulfilled or rejected.
+
+ A promise can be in one of three states: pending, fulfilled, or rejected.
+
+ Promises that are fulfilled have a fulfillment value and are in the fulfilled
+ state. Promises that are rejected have a rejection reason and are in the
+ rejected state. A fulfillment value is never a thenable.
+
+ Promises can also be said to *resolve* a value. If this value is also a
+ promise, then the original promise's settled state will match the value's
+ settled state. So a promise that *resolves* a promise that rejects will
+ itself reject, and a promise that *resolves* a promise that fulfills will
+ itself fulfill.
+
+
+ Basic Usage:
+ ------------
+
+ ```js
+ var promise = new Promise(function(resolve, reject) {
+ // on success
+ resolve(value);
+
+ // on failure
+ reject(reason);
+ });
+
+ promise.then(function(value) {
+ // on fulfillment
+ }, function(reason) {
+ // on rejection
+ });
+ ```
+
+ Advanced Usage:
+ ---------------
+
+ Promises shine when abstracting away asynchronous interactions such as
+ `XMLHttpRequest`s.
+
+ ```js
+ function getJSON(url) {
+ return new Promise(function(resolve, reject){
+ var xhr = new XMLHttpRequest();
+
+ xhr.open('GET', url);
+ xhr.onreadystatechange = handler;
+ xhr.responseType = 'json';
+ xhr.setRequestHeader('Accept', 'application/json');
+ xhr.send();
+
+ function handler() {
+ if (this.readyState === this.DONE) {
+ if (this.status === 200) {
+ resolve(this.response);
+ } else {
+ reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
+ }
+ }
+ };
+ });
+ }
+
+ getJSON('/posts.json').then(function(json) {
+ // on fulfillment
+ }, function(reason) {
+ // on rejection
+ });
+ ```
+
+ Unlike callbacks, promises are great composable primitives.
+
+ ```js
+ Promise.all([
+ getJSON('/posts'),
+ getJSON('/comments')
+ ]).then(function(values){
+ values[0] // => postsJSON
+ values[1] // => commentsJSON
+
+ return values;
+ });
+ ```
+
+ @class Promise
+ @param {function} resolver
+ Useful for tooling.
+ @constructor
+ */
+ function lib$es6$promise$promise$$Promise(resolver) {
+ this._id = lib$es6$promise$promise$$counter++;
+ this._state = undefined;
+ this._result = undefined;
+ this._subscribers = [];
+
+ if (lib$es6$promise$$internal$$noop !== resolver) {
+ if (!lib$es6$promise$utils$$isFunction(resolver)) {
+ lib$es6$promise$promise$$needsResolver();
+ }
+
+ if (!(this instanceof lib$es6$promise$promise$$Promise)) {
+ lib$es6$promise$promise$$needsNew();
+ }
+
+ lib$es6$promise$$internal$$initializePromise(this, resolver);
+ }
+ }
+
+ lib$es6$promise$promise$$Promise.all = lib$es6$promise$promise$all$$default;
+ lib$es6$promise$promise$$Promise.race = lib$es6$promise$promise$race$$default;
+ lib$es6$promise$promise$$Promise.resolve = lib$es6$promise$promise$resolve$$default;
+ lib$es6$promise$promise$$Promise.reject = lib$es6$promise$promise$reject$$default;
+ lib$es6$promise$promise$$Promise._setScheduler = lib$es6$promise$asap$$setScheduler;
+ lib$es6$promise$promise$$Promise._setAsap = lib$es6$promise$asap$$setAsap;
+ lib$es6$promise$promise$$Promise._asap = lib$es6$promise$asap$$asap;
+
+ lib$es6$promise$promise$$Promise.prototype = {
+ constructor: lib$es6$promise$promise$$Promise,
+
+ /**
+ The primary way of interacting with a promise is through its `then` method,
+ which registers callbacks to receive either a promise's eventual value or the
+ reason why the promise cannot be fulfilled.
+
+ ```js
+ findUser().then(function(user){
+ // user is available
+ }, function(reason){
+ // user is unavailable, and you are given the reason why
+ });
+ ```
+
+ Chaining
+ --------
+
+ The return value of `then` is itself a promise. This second, 'downstream'
+ promise is resolved with the return value of the first promise's fulfillment
+ or rejection handler, or rejected if the handler throws an exception.
+
+ ```js
+ findUser().then(function (user) {
+ return user.name;
+ }, function (reason) {
+ return 'default name';
+ }).then(function (userName) {
+ // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
+ // will be `'default name'`
+ });
+
+ findUser().then(function (user) {
+ throw new Error('Found user, but still unhappy');
+ }, function (reason) {
+ throw new Error('`findUser` rejected and we're unhappy');
+ }).then(function (value) {
+ // never reached
+ }, function (reason) {
+ // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
+ // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
+ });
+ ```
+ If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
+
+ ```js
+ findUser().then(function (user) {
+ throw new PedagogicalException('Upstream error');
+ }).then(function (value) {
+ // never reached
+ }).then(function (value) {
+ // never reached
+ }, function (reason) {
+ // The `PedgagocialException` is propagated all the way down to here
+ });
+ ```
+
+ Assimilation
+ ------------
+
+ Sometimes the value you want to propagate to a downstream promise can only be
+ retrieved asynchronously. This can be achieved by returning a promise in the
+ fulfillment or rejection handler. The downstream promise will then be pending
+ until the returned promise is settled. This is called *assimilation*.
+
+ ```js
+ findUser().then(function (user) {
+ return findCommentsByAuthor(user);
+ }).then(function (comments) {
+ // The user's comments are now available
+ });
+ ```
+
+ If the assimliated promise rejects, then the downstream promise will also reject.
+
+ ```js
+ findUser().then(function (user) {
+ return findCommentsByAuthor(user);
+ }).then(function (comments) {
+ // If `findCommentsByAuthor` fulfills, we'll have the value here
+ }, function (reason) {
+ // If `findCommentsByAuthor` rejects, we'll have the reason here
+ });
+ ```
+
+ Simple Example
+ --------------
+
+ Synchronous Example
+
+ ```javascript
+ var result;
+
+ try {
+ result = findResult();
+ // success
+ } catch(reason) {
+ // failure
+ }
+ ```
+
+ Errback Example
+
+ ```js
+ findResult(function(result, err){
+ if (err) {
+ // failure
+ } else {
+ // success
+ }
+ });
+ ```
+
+ Promise Example;
+
+ ```javascript
+ findResult().then(function(result){
+ // success
+ }, function(reason){
+ // failure
+ });
+ ```
+
+ Advanced Example
+ --------------
+
+ Synchronous Example
+
+ ```javascript
+ var author, books;
+
+ try {
+ author = findAuthor();
+ books = findBooksByAuthor(author);
+ // success
+ } catch(reason) {
+ // failure
+ }
+ ```
+
+ Errback Example
+
+ ```js
+
+ function foundBooks(books) {
+
+ }
+
+ function failure(reason) {
+
+ }
+
+ findAuthor(function(author, err){
+ if (err) {
+ failure(err);
+ // failure
+ } else {
+ try {
+ findBoooksByAuthor(author, function(books, err) {
+ if (err) {
+ failure(err);
+ } else {
+ try {
+ foundBooks(books);
+ } catch(reason) {
+ failure(reason);
+ }
+ }
+ });
+ } catch(error) {
+ failure(err);
+ }
+ // success
+ }
+ });
+ ```
+
+ Promise Example;
+
+ ```javascript
+ findAuthor().
+ then(findBooksByAuthor).
+ then(function(books){
+ // found books
+ }).catch(function(reason){
+ // something went wrong
+ });
+ ```
+
+ @method then
+ @param {Function} onFulfilled
+ @param {Function} onRejected
+ Useful for tooling.
+ @return {Promise}
+ */
+ then: function(onFulfillment, onRejection) {
+ var parent = this;
+ var state = parent._state;
+
+ if (state === lib$es6$promise$$internal$$FULFILLED && !onFulfillment || state === lib$es6$promise$$internal$$REJECTED && !onRejection) {
+ return this;
+ }
+
+ var child = new this.constructor(lib$es6$promise$$internal$$noop);
+ var result = parent._result;
+
+ if (state) {
+ var callback = arguments[state - 1];
+ lib$es6$promise$asap$$asap(function(){
+ lib$es6$promise$$internal$$invokeCallback(state, child, callback, result);
+ });
+ } else {
+ lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection);
+ }
+
+ return child;
+ },
+
+ /**
+ `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
+ as the catch block of a try/catch statement.
+
+ ```js
+ function findAuthor(){
+ throw new Error('couldn't find that author');
+ }
+
+ // synchronous
+ try {
+ findAuthor();
+ } catch(reason) {
+ // something went wrong
+ }
+
+ // async with promises
+ findAuthor().catch(function(reason){
+ // something went wrong
+ });
+ ```
+
+ @method catch
+ @param {Function} onRejection
+ Useful for tooling.
+ @return {Promise}
+ */
+ 'catch': function(onRejection) {
+ return this.then(null, onRejection);
+ }
+ };
+ function lib$es6$promise$polyfill$$polyfill() {
+ var local;
+
+ if (typeof global !== 'undefined') {
+ local = global;
+ } else if (typeof self !== 'undefined') {
+ local = self;
+ } else {
+ try {
+ local = Function('return this')();
+ } catch (e) {
+ throw new Error('polyfill failed because global object is unavailable in this environment');
+ }
+ }
+
+ var P = local.Promise;
+
+ if (P && Object.prototype.toString.call(P.resolve()) === '[object Promise]' && !P.cast) {
+ return;
+ }
+
+ local.Promise = lib$es6$promise$promise$$default;
+ }
+ var lib$es6$promise$polyfill$$default = lib$es6$promise$polyfill$$polyfill;
+
+ var lib$es6$promise$umd$$ES6Promise = {
+ 'Promise': lib$es6$promise$promise$$default,
+ 'polyfill': lib$es6$promise$polyfill$$default
+ };
+
+ /* global define:true module:true window: true */
+ if (typeof define === 'function' && define['amd']) {
+ define(function() { return lib$es6$promise$umd$$ES6Promise; });
+ } else if (typeof module !== 'undefined' && module['exports']) {
+ module['exports'] = lib$es6$promise$umd$$ES6Promise;
+ } else if (typeof this !== 'undefined') {
+ this['ES6Promise'] = lib$es6$promise$umd$$ES6Promise;
+ }
+
+ lib$es6$promise$polyfill$$default();
+}).call(this);
+