mirror of
				https://github.com/telekom-security/tpotce.git
				synced 2025-10-28 02:52:54 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			908 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			908 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| /*
 | |
|  * 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 including 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 = Client.PROTOCOL_HTTP + '://';
 | |
| 		if (options.useHTTPS) {
 | |
| 			url = Client.PROTOCOL_HTTPS + '://';
 | |
| 		}
 | |
| 
 | |
| 		url += options.host + this._root;
 | |
| 		this._host = options.host;
 | |
| 		this._defaultHeaders = options.defaultHeaders || {
 | |
| 				'X-Requested-With': 'XMLHttpRequest',
 | |
| 				'requesttoken': OC.requestToken
 | |
| 			};
 | |
| 		this._baseUrl = url;
 | |
| 
 | |
| 		this._rootSections = _.filter(this._root.split('/'), function(section) { return section !== '';});
 | |
| 		this._rootSections = _.map(this._rootSections, window.decodeURIComponent);
 | |
| 
 | |
| 		var clientOptions = {
 | |
| 			baseUrl: this._baseUrl,
 | |
| 			xmlNamespaces: {
 | |
| 				'DAV:': 'd',
 | |
| 				'http://owncloud.org/ns': 'oc'
 | |
| 			}
 | |
| 		};
 | |
| 		if (options.userName) {
 | |
| 			clientOptions.userName = options.userName;
 | |
| 		}
 | |
| 		if (options.password) {
 | |
| 			clientOptions.password = options.password;
 | |
| 		}
 | |
| 		this._client = new dav.Client(clientOptions);
 | |
| 		this._client.xhrProvider = _.bind(this._xhrProvider, this);
 | |
| 	};
 | |
| 
 | |
| 	Client.NS_OWNCLOUD = 'http://owncloud.org/ns';
 | |
| 	Client.NS_DAV = 'DAV:';
 | |
| 
 | |
| 	Client.PROPERTY_GETLASTMODIFIED	= '{' + Client.NS_DAV + '}getlastmodified';
 | |
| 	Client.PROPERTY_GETETAG	= '{' + Client.NS_DAV + '}getetag';
 | |
| 	Client.PROPERTY_GETCONTENTTYPE	= '{' + Client.NS_DAV + '}getcontenttype';
 | |
| 	Client.PROPERTY_RESOURCETYPE	= '{' + Client.NS_DAV + '}resourcetype';
 | |
| 	Client.PROPERTY_INTERNAL_FILEID	= '{' + Client.NS_OWNCLOUD + '}fileid';
 | |
| 	Client.PROPERTY_PERMISSIONS	= '{' + Client.NS_OWNCLOUD + '}permissions';
 | |
| 	Client.PROPERTY_SIZE	= '{' + Client.NS_OWNCLOUD + '}size';
 | |
| 	Client.PROPERTY_GETCONTENTLENGTH	= '{' + Client.NS_DAV + '}getcontentlength';
 | |
| 
 | |
| 	Client.PROTOCOL_HTTP	= 'http';
 | |
| 	Client.PROTOCOL_HTTPS	= 'https';
 | |
| 
 | |
| 	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;
 | |
| 			};
 | |
| 
 | |
| 			OC.registerXHRForErrorProcessing(xhr);
 | |
| 			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 sub-path from href
 | |
| 		 *
 | |
| 		 * @param {String} path href path
 | |
| 		 * @return {String} sub-path section
 | |
| 		 */
 | |
| 		_extractPath: function(path) {
 | |
| 			var pathSections = path.split('/');
 | |
| 			pathSections = _.filter(pathSections, function(section) { return section !== '';});
 | |
| 
 | |
| 			var i = 0;
 | |
| 			for (i = 0; i < this._rootSections.length; i++) {
 | |
| 				if (this._rootSections[i] !== decodeURIComponent(pathSections[i])) {
 | |
| 					// mismatch
 | |
| 					return null;
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			// build the sub-path from the remaining sections
 | |
| 			var subPath = '';
 | |
| 			while (i < pathSections.length) {
 | |
| 				subPath += '/' + decodeURIComponent(pathSections[i]);
 | |
| 				i++;
 | |
| 			}
 | |
| 			return subPath;
 | |
| 		},
 | |
| 
 | |
| 		/**
 | |
| 		 * Parse Webdav result
 | |
| 		 *
 | |
| 		 * @param {Object} response XML object
 | |
| 		 *
 | |
| 		 * @return {Array.<FileInfo>} array of file info
 | |
| 		 */
 | |
| 		_parseFileInfo: function(response) {
 | |
| 			var path = this._extractPath(response.href);
 | |
| 			// invalid subpath
 | |
| 			if (path === null) {
 | |
| 				return null;
 | |
| 			}
 | |
| 
 | |
| 			if (response.propStat.length === 0 || response.propStat[0].status !== 'HTTP/1.1 200 OK') {
 | |
| 				return null;
 | |
| 			}
 | |
| 
 | |
| 			var props = response.propStat[0].properties;
 | |
| 
 | |
| 			var data = {
 | |
| 				id: props[Client.PROPERTY_INTERNAL_FILEID],
 | |
| 				path: OC.dirname(path) || '/',
 | |
| 				name: OC.basename(path),
 | |
| 				mtime: (new Date(props[Client.PROPERTY_GETLASTMODIFIED])).getTime()
 | |
| 			};
 | |
| 
 | |
| 			var etagProp = props[Client.PROPERTY_GETETAG];
 | |
| 			if (!_.isUndefined(etagProp)) {
 | |
| 				data.etag = this._parseEtag(etagProp);
 | |
| 			}
 | |
| 
 | |
| 			var sizeProp = props[Client.PROPERTY_GETCONTENTLENGTH];
 | |
| 			if (!_.isUndefined(sizeProp)) {
 | |
| 				data.size = parseInt(sizeProp, 10);
 | |
| 			}
 | |
| 
 | |
| 			sizeProp = props[Client.PROPERTY_SIZE];
 | |
| 			if (!_.isUndefined(sizeProp)) {
 | |
| 				data.size = parseInt(sizeProp, 10);
 | |
| 			}
 | |
| 
 | |
| 			var contentType = props[Client.PROPERTY_GETCONTENTTYPE];
 | |
| 			if (!_.isUndefined(contentType)) {
 | |
| 				data.mimetype = contentType;
 | |
| 			}
 | |
| 
 | |
| 			var resType = props[Client.PROPERTY_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.PROPERTY_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':
 | |
| 							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;
 | |
| 			var fileInfos = [];
 | |
| 			for (var i = 0; i < responses.length; i++) {
 | |
| 				var fileInfo = self._parseFileInfo(responses[i]);
 | |
| 				if (fileInfo !== null) {
 | |
| 					fileInfos.push(fileInfo);
 | |
| 				}
 | |
| 			}
 | |
| 			return fileInfos;
 | |
| 		},
 | |
| 
 | |
| 		/**
 | |
| 		 * 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;
 | |
| 		},
 | |
| 
 | |
| 		/**
 | |
| 		 * Parse the Sabre exception out of the given response, if any
 | |
| 		 *
 | |
| 		 * @param {Object} response object
 | |
| 		 * @return {Object} array of parsed message and exception (only the first one)
 | |
| 		 */
 | |
| 		_getSabreException: function(response) {
 | |
| 			var result = {};
 | |
| 			if (!response.body) {
 | |
| 				return result;
 | |
| 			}
 | |
| 			var xml = response.xhr.responseXML;
 | |
| 			var messages = xml.getElementsByTagNameNS('http://sabredav.org/ns', 'message');
 | |
| 			var exceptions = xml.getElementsByTagNameNS('http://sabredav.org/ns', 'exception');
 | |
| 			if (messages.length) {
 | |
| 				result.message = messages[0].textContent;
 | |
| 			}
 | |
| 			if (exceptions.length) {
 | |
| 				result.exception = exceptions[0].textContent;
 | |
| 			}
 | |
| 			return result;
 | |
| 		},
 | |
| 
 | |
| 		/**
 | |
| 		 * 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;
 | |
| 			}
 | |
| 
 | |
| 			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 {
 | |
| 					result = _.extend(result, self._getSabreException(result));
 | |
| 					deferred.reject(result.status, result);
 | |
| 				}
 | |
| 			});
 | |
| 			return promise;
 | |
| 		},
 | |
| 
 | |
| 		/**
 | |
| 		 * Fetches a flat list of files filtered by a given filter criteria.
 | |
| 		 * (currently only system tags is supported)
 | |
| 		 *
 | |
| 		 * @param {Object} filter filter criteria
 | |
| 		 * @param {Object} [filter.systemTagIds] list of system tag ids to filter by
 | |
| 		 * @param {bool} [filter.favorite] set it to filter by favorites
 | |
| 		 * @param {Object} [options] options
 | |
| 		 * @param {Array} [options.properties] list of Webdav properties to retrieve
 | |
| 		 *
 | |
| 		 * @return {Promise} promise
 | |
| 		 */
 | |
| 		getFilteredFiles: function(filter, options) {
 | |
| 			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;
 | |
| 			}
 | |
| 
 | |
| 			if (!filter || (!filter.systemTagIds && _.isUndefined(filter.favorite))) {
 | |
| 				throw 'Missing filter argument';
 | |
| 			}
 | |
| 
 | |
| 			// root element with namespaces
 | |
|             var body = '<oc:filter-files ';
 | |
| 			var namespace;
 | |
| 			for (namespace in this._client.xmlNamespaces) {
 | |
| 				body += ' xmlns:' + this._client.xmlNamespaces[namespace] + '="' + namespace + '"';
 | |
| 			}
 | |
| 			body += '>\n';
 | |
| 
 | |
| 			// properties query
 | |
| 			body += '    <' + this._client.xmlNamespaces['DAV:'] + ':prop>\n';
 | |
| 			_.each(properties, function(prop) {
 | |
| 				var property = self._client.parseClarkNotation(prop);
 | |
|                 body += '        <' + self._client.xmlNamespaces[property.namespace] + ':' + property.name + ' />\n';
 | |
| 			});
 | |
| 
 | |
| 			body += '    </' + this._client.xmlNamespaces['DAV:'] + ':prop>\n';
 | |
| 
 | |
| 			// rules block
 | |
| 			body +=	'    <oc:filter-rules>\n';
 | |
| 			_.each(filter.systemTagIds, function(systemTagIds) {
 | |
| 				body += '        <oc:systemtag>' + escapeHTML(systemTagIds) + '</oc:systemtag>\n';
 | |
| 			});
 | |
| 			if (filter.favorite) {
 | |
| 				body += '        <oc:favorite>' + (filter.favorite ? '1': '0') + '</oc:favorite>\n';
 | |
| 			}
 | |
| 			body += '    </oc:filter-rules>\n';
 | |
| 
 | |
| 			// end of root
 | |
| 			body += '</oc:filter-files>\n';
 | |
| 
 | |
| 			this._client.request(
 | |
| 				'REPORT',
 | |
| 				this._buildUrl(),
 | |
| 				{},
 | |
| 				body
 | |
| 			).then(function(result) {
 | |
| 				if (self._isSuccessStatus(result.status)) {
 | |
| 					var results = self._parseResult(result.body);
 | |
| 					deferred.resolve(result.status, results);
 | |
| 				} else {
 | |
| 					result = _.extend(result, self._getSabreException(result));
 | |
| 					deferred.reject(result.status, result);
 | |
| 				}
 | |
| 			});
 | |
| 			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 {
 | |
| 						result = _.extend(result, self._getSabreException(result));
 | |
| 						deferred.reject(result.status, result);
 | |
| 					}
 | |
| 				}
 | |
| 			);
 | |
| 			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)
 | |
| 			).then(
 | |
| 				function(result) {
 | |
| 					if (self._isSuccessStatus(result.status)) {
 | |
| 						deferred.resolve(result.status, result.body);
 | |
| 					} else {
 | |
| 						result = _.extend(result, self._getSabreException(result));
 | |
| 						deferred.reject(result.status, result);
 | |
| 					}
 | |
| 				}
 | |
| 			);
 | |
| 			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 = {};
 | |
| 			var contentType = 'text/plain;charset=utf-8';
 | |
| 			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 {
 | |
| 						result = _.extend(result, self._getSabreException(result));
 | |
| 						deferred.reject(result.status, result);
 | |
| 					}
 | |
| 				}
 | |
| 			);
 | |
| 			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)
 | |
| 			).then(
 | |
| 				function(result) {
 | |
| 					if (self._isSuccessStatus(result.status)) {
 | |
| 						deferred.resolve(result.status);
 | |
| 					} else {
 | |
| 						result = _.extend(result, self._getSabreException(result));
 | |
| 						deferred.reject(result.status, result);
 | |
| 					}
 | |
| 				}
 | |
| 			);
 | |
| 			return promise;
 | |
| 		},
 | |
| 
 | |
| 		_moveOrCopy: function(operation, path, destinationPath, allowOverwrite, headers, options) {
 | |
| 			if (!path) {
 | |
| 				throw 'Missing argument "path"';
 | |
| 			}
 | |
| 			if (!destinationPath) {
 | |
| 				throw 'Missing argument "destinationPath"';
 | |
| 			}
 | |
| 			if (operation !== 'MOVE' && operation !== 'COPY') {
 | |
| 				throw 'Invalid operation';
 | |
| 			}
 | |
| 
 | |
| 			var self = this;
 | |
| 			var deferred = $.Deferred();
 | |
| 			var promise = deferred.promise();
 | |
| 			options = _.extend({
 | |
| 				'pathIsUrl' : false,
 | |
| 				'destinationPathIsUrl' : false
 | |
| 			}, options);
 | |
| 			headers = _.extend({}, headers, {
 | |
| 				'Destination' : options.destinationPathIsUrl ? destinationPath : this._buildUrl(destinationPath)
 | |
| 			});
 | |
| 
 | |
| 			if (!allowOverwrite) {
 | |
| 				headers['Overwrite'] = 'F';
 | |
| 			}
 | |
| 
 | |
| 			this._client.request(
 | |
| 				operation,
 | |
| 				options.pathIsUrl ? path : this._buildUrl(path),
 | |
| 				headers
 | |
| 			).then(
 | |
| 				function(result) {
 | |
| 					if (self._isSuccessStatus(result.status)) {
 | |
| 						deferred.resolve(result.status);
 | |
| 					} else {
 | |
| 						result = _.extend(result, self._getSabreException(result));
 | |
| 						deferred.reject(result.status, result);
 | |
| 					}
 | |
| 				}
 | |
| 			);
 | |
| 			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
 | |
| 		 * @param {Object} [headers=null] additional headers
 | |
| 		 *
 | |
| 		 * @return {Promise} promise
 | |
| 		 */
 | |
| 		move: function(path, destinationPath, allowOverwrite, headers, options) {
 | |
| 			return this._moveOrCopy('MOVE', path, destinationPath, allowOverwrite, headers, options);
 | |
| 		},
 | |
| 
 | |
| 		/**
 | |
| 		 * Copies path to another path
 | |
| 		 *
 | |
| 		 * @param {String} path path to copy
 | |
| 		 * @param {String} destinationPath destination path
 | |
| 		 * @param {boolean} [allowOverwrite=false] true to allow overwriting,
 | |
| 		 * false otherwise
 | |
| 		 * @param {Object} [headers=null] additional headers
 | |
| 		 *
 | |
| 		 * @return {Promise} promise
 | |
| 		 * @since 10.0.5
 | |
| 		 */
 | |
| 		copy: function(path, destinationPath, allowOverwrite, headers, options) {
 | |
| 			return this._moveOrCopy('COPY', path, destinationPath, allowOverwrite, headers, options);
 | |
| 		},
 | |
| 
 | |
| 		/**
 | |
| 		 * Add a file info parser function
 | |
| 		 *
 | |
| 		 * @param {OC.Files.Client~parseFileInfo>}
 | |
| 		 */
 | |
| 		addFileInfoParser: function(parserFunction) {
 | |
| 			this._fileInfoParsers.push(parserFunction);
 | |
| 		},
 | |
| 
 | |
| 		/**
 | |
| 		 * Returns the dav.Client instance used internally
 | |
| 		 *
 | |
| 		 * @since 10.0
 | |
| 		 * @return {dav.Client}
 | |
| 		 */
 | |
| 		getClient: function() {
 | |
| 			return this._client;
 | |
| 		},
 | |
| 
 | |
| 		/**
 | |
| 		 * Returns the user name
 | |
| 		 *
 | |
| 		 * @since 10.0
 | |
| 		 * @return {String} userName
 | |
| 		 */
 | |
| 		getUserName: function() {
 | |
| 			return this._client.userName;
 | |
| 		},
 | |
| 
 | |
| 		/**
 | |
| 		 * Returns the password
 | |
| 		 *
 | |
| 		 * @since 10.0
 | |
| 		 * @return {String} password
 | |
| 		 */
 | |
| 		getPassword: function() {
 | |
| 			return this._client.password;
 | |
| 		},
 | |
| 
 | |
| 		/**
 | |
| 		 * Returns the base URL
 | |
| 		 *
 | |
| 		 * @since 10.0
 | |
| 		 * @return {String} base URL
 | |
| 		 */
 | |
| 		getBaseUrl: function() {
 | |
| 			return this._client.baseUrl;
 | |
| 		},
 | |
| 
 | |
| 		/**
 | |
| 		 * Returns the host
 | |
| 		 *
 | |
| 		 * @since 10.0.3
 | |
| 		 * @return {String} base URL
 | |
| 		 */
 | |
| 		getHost: function() {
 | |
| 			return this._host;
 | |
| 		}
 | |
| 	};
 | |
| 
 | |
| 	/**
 | |
| 	 * 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(),
 | |
| 			root: OC.linkToRemoteBase('webdav'),
 | |
| 			useHTTPS: OC.getProtocol() === 'https'
 | |
| 		});
 | |
| 		OC.Files._defaultClient = client;
 | |
| 		return client;
 | |
| 	};
 | |
| 
 | |
| 	OC.Files.Client = Client;
 | |
| })(OC, OC.Files.FileInfo);
 | 
