2020-05-15 11:37:08 +03:00
|
|
|
/* eslint-disable */
|
2015-07-13 18:31:47 +03:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2015
|
|
|
|
*
|
|
|
|
* This file is licensed under the Affero General Public License version 3
|
|
|
|
* or later.
|
|
|
|
*
|
|
|
|
* See the COPYING-README file.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
import escapeHTML from 'escape-html'
|
|
|
|
|
2015-07-13 18:31:47 +03:00
|
|
|
/* 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) {
|
2020-05-15 11:37:08 +03:00
|
|
|
this._root = options.root
|
2015-07-13 18:31:47 +03:00
|
|
|
if (this._root.charAt(this._root.length - 1) === '/') {
|
2020-05-15 11:37:08 +03:00
|
|
|
this._root = this._root.substr(0, this._root.length - 1)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
let url = Client.PROTOCOL_HTTP + '://'
|
2015-07-13 18:31:47 +03:00
|
|
|
if (options.useHTTPS) {
|
2020-05-15 11:37:08 +03:00
|
|
|
url = Client.PROTOCOL_HTTPS + '://'
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
url += options.host + this._root
|
|
|
|
this._host = options.host
|
2016-02-16 15:16:52 +03:00
|
|
|
this._defaultHeaders = options.defaultHeaders || {
|
2020-05-15 11:37:08 +03:00
|
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
|
|
'requesttoken': OC.requestToken,
|
|
|
|
}
|
|
|
|
this._baseUrl = url
|
2015-12-14 19:42:13 +03:00
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const clientOptions = {
|
2015-07-13 18:31:47 +03:00
|
|
|
baseUrl: this._baseUrl,
|
|
|
|
xmlNamespaces: {
|
|
|
|
'DAV:': 'd',
|
2016-07-26 14:40:44 +03:00
|
|
|
'http://owncloud.org/ns': 'oc',
|
2018-03-08 21:52:37 +03:00
|
|
|
'http://nextcloud.org/ns': 'nc',
|
2020-05-15 11:37:08 +03:00
|
|
|
'http://open-collaboration-services.org/ns': 'ocs',
|
|
|
|
},
|
|
|
|
}
|
2015-12-14 19:42:13 +03:00
|
|
|
if (options.userName) {
|
2020-05-15 11:37:08 +03:00
|
|
|
clientOptions.userName = options.userName
|
2015-12-14 19:42:13 +03:00
|
|
|
}
|
|
|
|
if (options.password) {
|
2020-05-15 11:37:08 +03:00
|
|
|
clientOptions.password = options.password
|
2015-12-14 19:42:13 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
this._client = new dav.Client(clientOptions)
|
|
|
|
this._client.xhrProvider = _.bind(this._xhrProvider, this)
|
|
|
|
this._fileInfoParsers = []
|
|
|
|
}
|
|
|
|
|
|
|
|
Client.NS_OWNCLOUD = 'http://owncloud.org/ns'
|
|
|
|
Client.NS_NEXTCLOUD = 'http://nextcloud.org/ns'
|
|
|
|
Client.NS_DAV = 'DAV:'
|
|
|
|
Client.NS_OCS = 'http://open-collaboration-services.org/ns'
|
|
|
|
|
|
|
|
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.PROPERTY_ISENCRYPTED = '{' + Client.NS_DAV + '}is-encrypted'
|
|
|
|
Client.PROPERTY_SHARE_PERMISSIONS = '{' + Client.NS_OCS + '}share-permissions'
|
2020-10-16 15:22:47 +03:00
|
|
|
Client.PROPERTY_QUOTA_AVAILABLE_BYTES = '{' + Client.NS_DAV + '}quota-available-bytes'
|
2020-05-15 11:37:08 +03:00
|
|
|
|
|
|
|
Client.PROTOCOL_HTTP = 'http'
|
|
|
|
Client.PROTOCOL_HTTPS = 'https'
|
2016-11-21 17:03:45 +03:00
|
|
|
|
2015-07-13 18:31:47 +03:00
|
|
|
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'],
|
|
|
|
/**
|
2015-11-18 17:18:00 +03:00
|
|
|
* File id
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
2015-11-18 17:18:00 +03:00
|
|
|
[Client.NS_OWNCLOUD, 'fileid'],
|
2015-07-13 18:31:47 +03:00
|
|
|
/**
|
|
|
|
* Letter-coded permissions
|
|
|
|
*/
|
|
|
|
[Client.NS_OWNCLOUD, 'permissions'],
|
2020-05-15 11:37:08 +03:00
|
|
|
// [Client.NS_OWNCLOUD, 'downloadURL'],
|
2015-07-13 18:31:47 +03:00
|
|
|
/**
|
|
|
|
* Folder sizes
|
|
|
|
*/
|
|
|
|
[Client.NS_OWNCLOUD, 'size'],
|
|
|
|
/**
|
|
|
|
* File sizes
|
|
|
|
*/
|
2016-07-26 14:40:44 +03:00
|
|
|
[Client.NS_DAV, 'getcontentlength'],
|
2020-10-16 15:22:47 +03:00
|
|
|
[Client.NS_DAV, 'quota-available-bytes'],
|
2016-07-26 14:40:44 +03:00
|
|
|
/**
|
|
|
|
* Preview availability
|
|
|
|
*/
|
2017-04-26 15:53:11 +03:00
|
|
|
[Client.NS_NEXTCLOUD, 'has-preview'],
|
|
|
|
/**
|
|
|
|
* Mount type
|
|
|
|
*/
|
|
|
|
[Client.NS_NEXTCLOUD, 'mount-type'],
|
2017-09-19 13:53:35 +03:00
|
|
|
/**
|
|
|
|
* Encryption state
|
|
|
|
*/
|
|
|
|
[Client.NS_NEXTCLOUD, 'is-encrypted'],
|
2018-03-08 21:52:37 +03:00
|
|
|
/**
|
|
|
|
* Share permissions
|
|
|
|
*/
|
2020-05-15 11:37:08 +03:00
|
|
|
[Client.NS_OCS, 'share-permissions'],
|
|
|
|
]
|
2015-07-13 18:31:47 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @memberof OC.Files
|
|
|
|
*/
|
|
|
|
Client.prototype = {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Root path of the Webdav endpoint
|
|
|
|
*
|
|
|
|
* @type string
|
|
|
|
*/
|
|
|
|
_root: null,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Client from the library
|
|
|
|
*
|
2015-11-02 16:17:49 +03:00
|
|
|
* @type dav.Client
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
|
|
|
_client: null,
|
|
|
|
|
2015-11-02 16:17:49 +03:00
|
|
|
/**
|
|
|
|
* Array of file info parsing functions.
|
|
|
|
*
|
|
|
|
* @type Array<OC.Files.Client~parseFileInfo>
|
|
|
|
*/
|
|
|
|
_fileInfoParsers: [],
|
|
|
|
|
2015-07-13 18:31:47 +03:00
|
|
|
/**
|
|
|
|
* Returns the configured XHR provider for davclient
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {XMLHttpRequest}
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
|
|
|
_xhrProvider: function() {
|
2020-05-15 11:37:08 +03:00
|
|
|
const headers = this._defaultHeaders
|
|
|
|
const xhr = new XMLHttpRequest()
|
|
|
|
const oldOpen = xhr.open
|
2015-07-13 18:31:47 +03:00
|
|
|
// override open() method to add headers
|
|
|
|
xhr.open = function() {
|
2020-05-15 11:37:08 +03:00
|
|
|
const result = oldOpen.apply(this, arguments)
|
2015-07-13 18:31:47 +03:00
|
|
|
_.each(headers, function(value, key) {
|
2020-05-15 11:37:08 +03:00
|
|
|
xhr.setRequestHeader(key, value)
|
|
|
|
})
|
|
|
|
return result
|
|
|
|
}
|
2015-12-10 20:08:40 +03:00
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
OC.registerXHRForErrorProcessing(xhr)
|
|
|
|
return xhr
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Prepends the base url to the given path sections
|
|
|
|
*
|
|
|
|
* @param {...String} path sections
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {String} base url + joined path, any leading or trailing slash
|
2015-07-13 18:31:47 +03:00
|
|
|
* will be kept
|
|
|
|
*/
|
|
|
|
_buildUrl: function() {
|
2020-05-15 11:37:08 +03:00
|
|
|
let path = this._buildPath.apply(this, arguments)
|
2015-07-13 18:31:47 +03:00
|
|
|
if (path.charAt([path.length - 1]) === '/') {
|
2020-05-15 11:37:08 +03:00
|
|
|
path = path.substr(0, path.length - 1)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
if (path.charAt(0) === '/') {
|
2020-05-15 11:37:08 +03:00
|
|
|
path = path.substr(1)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
return this._baseUrl + '/' + path
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Append the path to the root and also encode path
|
|
|
|
* sections
|
|
|
|
*
|
|
|
|
* @param {...String} path sections
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {String} joined path, any leading or trailing slash
|
2015-07-13 18:31:47 +03:00
|
|
|
* will be kept
|
|
|
|
*/
|
|
|
|
_buildPath: function() {
|
2020-05-15 11:37:08 +03:00
|
|
|
let path = OC.joinPaths.apply(this, arguments)
|
|
|
|
const sections = path.split('/')
|
|
|
|
let i
|
2015-07-13 18:31:47 +03:00
|
|
|
for (i = 0; i < sections.length; i++) {
|
2020-05-15 11:37:08 +03:00
|
|
|
sections[i] = encodeURIComponent(sections[i])
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
path = sections.join('/')
|
|
|
|
return path
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parse headers string into a map
|
|
|
|
*
|
|
|
|
* @param {string} headersString headers list as string
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {Object.<String,Array>} map of header name to header contents
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
|
|
|
_parseHeaders: function(headersString) {
|
2020-05-15 11:37:08 +03:00
|
|
|
const headerRows = headersString.split('\n')
|
|
|
|
const headers = {}
|
|
|
|
for (let i = 0; i < headerRows.length; i++) {
|
|
|
|
const sepPos = headerRows[i].indexOf(':')
|
2015-07-13 18:31:47 +03:00
|
|
|
if (sepPos < 0) {
|
2020-05-15 11:37:08 +03:00
|
|
|
continue
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const headerName = headerRows[i].substr(0, sepPos)
|
|
|
|
const headerValue = headerRows[i].substr(sepPos + 2)
|
2015-07-13 18:31:47 +03:00
|
|
|
|
|
|
|
if (!headers[headerName]) {
|
|
|
|
// make it an array
|
2020-05-15 11:37:08 +03:00
|
|
|
headers[headerName] = []
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
headers[headerName].push(headerValue)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
return headers
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parses the etag response which is in double quotes.
|
|
|
|
*
|
|
|
|
* @param {string} etag etag value in double quotes
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {string} etag without double quotes
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
|
|
|
_parseEtag: function(etag) {
|
|
|
|
if (etag.charAt(0) === '"') {
|
2020-05-15 11:37:08 +03:00
|
|
|
return etag.split('"')[1]
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
return etag
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parse Webdav result
|
|
|
|
*
|
|
|
|
* @param {Object} response XML object
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {Array.<FileInfo>} array of file info
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
|
|
|
_parseFileInfo: function(response) {
|
2020-05-15 11:37:08 +03:00
|
|
|
let path = decodeURIComponent(response.href)
|
2015-07-13 18:31:47 +03:00
|
|
|
if (path.substr(0, this._root.length) === this._root) {
|
2020-05-15 11:37:08 +03:00
|
|
|
path = path.substr(this._root.length)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (path.charAt(path.length - 1) === '/') {
|
2020-05-15 11:37:08 +03:00
|
|
|
path = path.substr(0, path.length - 1)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2016-02-08 13:43:42 +03:00
|
|
|
if (response.propStat.length === 0 || response.propStat[0].status !== 'HTTP/1.1 200 OK') {
|
2020-05-15 11:37:08 +03:00
|
|
|
return null
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const props = response.propStat[0].properties
|
2015-07-13 18:31:47 +03:00
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const data = {
|
2016-11-21 17:03:45 +03:00
|
|
|
id: props[Client.PROPERTY_INTERNAL_FILEID],
|
2015-07-13 18:31:47 +03:00
|
|
|
path: OC.dirname(path) || '/',
|
|
|
|
name: OC.basename(path),
|
2020-05-15 11:37:08 +03:00
|
|
|
mtime: (new Date(props[Client.PROPERTY_GETLASTMODIFIED])).getTime(),
|
|
|
|
}
|
2015-07-13 18:31:47 +03:00
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const etagProp = props[Client.PROPERTY_GETETAG]
|
2015-07-13 18:31:47 +03:00
|
|
|
if (!_.isUndefined(etagProp)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
data.etag = this._parseEtag(etagProp)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
let sizeProp = props[Client.PROPERTY_GETCONTENTLENGTH]
|
2015-07-13 18:31:47 +03:00
|
|
|
if (!_.isUndefined(sizeProp)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
data.size = parseInt(sizeProp, 10)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
sizeProp = props[Client.PROPERTY_SIZE]
|
2015-07-13 18:31:47 +03:00
|
|
|
if (!_.isUndefined(sizeProp)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
data.size = parseInt(sizeProp, 10)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const hasPreviewProp = props['{' + Client.NS_NEXTCLOUD + '}has-preview']
|
2016-07-26 14:40:44 +03:00
|
|
|
if (!_.isUndefined(hasPreviewProp)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
data.hasPreview = hasPreviewProp === 'true'
|
2016-07-26 14:40:44 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
data.hasPreview = true
|
2016-07-26 14:40:44 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const isEncryptedProp = props['{' + Client.NS_NEXTCLOUD + '}is-encrypted']
|
2017-09-19 13:53:35 +03:00
|
|
|
if (!_.isUndefined(isEncryptedProp)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
data.isEncrypted = isEncryptedProp === '1'
|
2017-09-19 13:53:35 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
data.isEncrypted = false
|
2017-09-19 13:53:35 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const isFavouritedProp = props['{' + Client.NS_OWNCLOUD + '}favorite']
|
2019-05-23 18:03:04 +03:00
|
|
|
if (!_.isUndefined(isFavouritedProp)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
data.isFavourited = isFavouritedProp === '1'
|
2019-05-23 18:03:04 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
data.isFavourited = false
|
2019-05-23 18:03:04 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const contentType = props[Client.PROPERTY_GETCONTENTTYPE]
|
2015-07-13 18:31:47 +03:00
|
|
|
if (!_.isUndefined(contentType)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
data.mimetype = contentType
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const resType = props[Client.PROPERTY_RESOURCETYPE]
|
2015-07-13 18:31:47 +03:00
|
|
|
if (!data.mimetype && resType) {
|
2020-05-15 11:37:08 +03:00
|
|
|
const xmlvalue = resType[0]
|
2015-07-13 18:31:47 +03:00
|
|
|
if (xmlvalue.namespaceURI === Client.NS_DAV && xmlvalue.nodeName.split(':')[1] === 'collection') {
|
2020-05-15 11:37:08 +03:00
|
|
|
data.mimetype = 'httpd/unix-directory'
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
data.permissions = OC.PERMISSION_NONE
|
|
|
|
const permissionProp = props[Client.PROPERTY_PERMISSIONS]
|
2015-07-13 18:31:47 +03:00
|
|
|
if (!_.isUndefined(permissionProp)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
const permString = permissionProp || ''
|
|
|
|
data.mountType = null
|
|
|
|
for (let i = 0; i < permString.length; i++) {
|
|
|
|
const c = permString.charAt(i)
|
2015-07-13 18:31:47 +03:00
|
|
|
switch (c) {
|
2020-05-15 11:37:08 +03:00
|
|
|
// FIXME: twisted permissions
|
|
|
|
case 'C':
|
|
|
|
case 'K':
|
|
|
|
data.permissions |= OC.PERMISSION_CREATE
|
|
|
|
break
|
|
|
|
case 'G':
|
|
|
|
data.permissions |= OC.PERMISSION_READ
|
|
|
|
break
|
|
|
|
case 'W':
|
|
|
|
case 'N':
|
|
|
|
case 'V':
|
|
|
|
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
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const sharePermissionsProp = props[Client.PROPERTY_SHARE_PERMISSIONS]
|
2018-03-08 21:52:37 +03:00
|
|
|
if (!_.isUndefined(sharePermissionsProp)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
data.sharePermissions = parseInt(sharePermissionsProp)
|
2018-03-08 21:52:37 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const mounTypeProp = props['{' + Client.NS_NEXTCLOUD + '}mount-type']
|
2017-04-26 15:53:11 +03:00
|
|
|
if (!_.isUndefined(mounTypeProp)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
data.mountType = mounTypeProp
|
2017-04-26 15:53:11 +03:00
|
|
|
}
|
|
|
|
|
2020-10-16 15:22:47 +03:00
|
|
|
const quotaAvailableBytes = props['{' + Client.NS_DAV + '}quota-available-bytes']
|
|
|
|
if (!_.isUndefined(quotaAvailableBytes)) {
|
|
|
|
data.quotaAvailableBytes = quotaAvailableBytes
|
|
|
|
}
|
|
|
|
|
2015-11-02 16:17:49 +03:00
|
|
|
// extend the parsed data using the custom parsers
|
|
|
|
_.each(this._fileInfoParsers, function(parserFunction) {
|
2020-05-15 11:37:08 +03:00
|
|
|
_.extend(data, parserFunction(response, data) || {})
|
|
|
|
})
|
2015-11-02 16:17:49 +03:00
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
return new FileInfo(data)
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Parse Webdav multistatus
|
|
|
|
*
|
|
|
|
* @param {Array} responses
|
|
|
|
*/
|
|
|
|
_parseResult: function(responses) {
|
2020-05-15 11:37:08 +03:00
|
|
|
const self = this
|
2015-07-13 18:31:47 +03:00
|
|
|
return _.map(responses, function(response) {
|
2020-05-15 11:37:08 +03:00
|
|
|
return self._parseFileInfo(response)
|
|
|
|
})
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns whether the given status code means success
|
|
|
|
*
|
|
|
|
* @param {int} status status code
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns true if status code is between 200 and 299 included
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
|
|
|
_isSuccessStatus: function(status) {
|
2020-05-15 11:37:08 +03:00
|
|
|
return status >= 200 && status <= 299
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
2017-08-08 17:37:14 +03:00
|
|
|
/**
|
|
|
|
* Parse the Sabre exception out of the given response, if any
|
|
|
|
*
|
|
|
|
* @param {Object} response object
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {Object} array of parsed message and exception (only the first one)
|
2017-08-08 17:37:14 +03:00
|
|
|
*/
|
|
|
|
_getSabreException: function(response) {
|
2020-05-15 11:37:08 +03:00
|
|
|
const result = {}
|
|
|
|
const xml = response.xhr.responseXML
|
2018-11-15 19:51:03 +03:00
|
|
|
if (xml === null) {
|
2020-05-15 11:37:08 +03:00
|
|
|
return result
|
2018-11-15 19:51:03 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
const messages = xml.getElementsByTagNameNS('http://sabredav.org/ns', 'message')
|
|
|
|
const exceptions = xml.getElementsByTagNameNS('http://sabredav.org/ns', 'exception')
|
2017-08-08 17:37:14 +03:00
|
|
|
if (messages.length) {
|
2020-05-15 11:37:08 +03:00
|
|
|
result.message = messages[0].textContent
|
2017-08-08 17:37:14 +03:00
|
|
|
}
|
|
|
|
if (exceptions.length) {
|
2020-05-15 11:37:08 +03:00
|
|
|
result.exception = exceptions[0].textContent
|
2017-08-08 17:37:14 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
return result
|
2017-08-08 17:37:14 +03:00
|
|
|
},
|
|
|
|
|
2015-07-13 18:31:47 +03:00
|
|
|
/**
|
|
|
|
* Returns the default PROPFIND properties to use during a call.
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {Array.<Object>} array of properties
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
2015-11-02 16:17:49 +03:00
|
|
|
getPropfindProperties: function() {
|
2015-07-13 18:31:47 +03:00
|
|
|
if (!this._propfindProperties) {
|
|
|
|
this._propfindProperties = _.map(Client._PROPFIND_PROPERTIES, function(propDef) {
|
2020-05-15 11:37:08 +03:00
|
|
|
return '{' + propDef[0] + '}' + propDef[1]
|
|
|
|
})
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
return this._propfindProperties
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
2015-11-02 16:17:49 +03:00
|
|
|
* @param {Array} [options.properties] list of Webdav properties to retrieve
|
2015-07-13 18:31:47 +03:00
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {Promise} promise
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
|
|
|
getFolderContents: function(path, options) {
|
|
|
|
if (!path) {
|
2020-05-15 11:37:08 +03:00
|
|
|
path = ''
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
options = options || {}
|
|
|
|
const self = this
|
|
|
|
const deferred = $.Deferred()
|
|
|
|
const promise = deferred.promise()
|
|
|
|
let properties
|
2015-11-02 16:17:49 +03:00
|
|
|
if (_.isUndefined(options.properties)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
properties = this.getPropfindProperties()
|
2015-11-02 16:17:49 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
properties = options.properties
|
2015-11-02 16:17:49 +03:00
|
|
|
}
|
2015-07-13 18:31:47 +03:00
|
|
|
|
|
|
|
this._client.propFind(
|
|
|
|
this._buildUrl(path),
|
2015-11-02 16:17:49 +03:00
|
|
|
properties,
|
2015-07-13 18:31:47 +03:00
|
|
|
1
|
|
|
|
).then(function(result) {
|
|
|
|
if (self._isSuccessStatus(result.status)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
const results = self._parseResult(result.body)
|
2015-07-13 18:31:47 +03:00
|
|
|
if (!options || !options.includeParent) {
|
|
|
|
// remove root dir, the first entry
|
2020-05-15 11:37:08 +03:00
|
|
|
results.shift()
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
deferred.resolve(result.status, results)
|
2015-07-13 18:31:47 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
result = _.extend(result, self._getSabreException(result))
|
|
|
|
deferred.reject(result.status, result)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
})
|
|
|
|
return promise
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
2016-02-08 13:43:42 +03:00
|
|
|
/**
|
|
|
|
* Fetches a flat list of files filtered by a given filter criteria.
|
2017-09-30 00:43:04 +03:00
|
|
|
* (currently system tags and circles are supported)
|
2016-02-08 13:43:42 +03:00
|
|
|
*
|
|
|
|
* @param {Object} filter filter criteria
|
|
|
|
* @param {Object} [filter.systemTagIds] list of system tag ids to filter by
|
2016-09-12 18:09:46 +03:00
|
|
|
* @param {bool} [filter.favorite] set it to filter by favorites
|
2016-02-08 13:43:42 +03:00
|
|
|
* @param {Object} [options] options
|
|
|
|
* @param {Array} [options.properties] list of Webdav properties to retrieve
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {Promise} promise
|
2016-02-08 13:43:42 +03:00
|
|
|
*/
|
|
|
|
getFilteredFiles: function(filter, options) {
|
2020-05-15 11:37:08 +03:00
|
|
|
options = options || {}
|
|
|
|
const self = this
|
|
|
|
const deferred = $.Deferred()
|
|
|
|
const promise = deferred.promise()
|
|
|
|
let properties
|
2016-02-08 13:43:42 +03:00
|
|
|
if (_.isUndefined(options.properties)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
properties = this.getPropfindProperties()
|
2016-02-08 13:43:42 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
properties = options.properties
|
2016-02-08 13:43:42 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
if (!filter
|
|
|
|
|| (!filter.systemTagIds && _.isUndefined(filter.favorite) && !filter.circlesIds)) {
|
|
|
|
throw 'Missing filter argument'
|
2016-02-08 13:43:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// root element with namespaces
|
2020-05-15 11:37:08 +03:00
|
|
|
let body = '<oc:filter-files '
|
|
|
|
let namespace
|
2016-02-08 13:43:42 +03:00
|
|
|
for (namespace in this._client.xmlNamespaces) {
|
2020-05-15 11:37:08 +03:00
|
|
|
body += ' xmlns:' + this._client.xmlNamespaces[namespace] + '="' + namespace + '"'
|
2016-02-08 13:43:42 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
body += '>\n'
|
2016-02-08 13:43:42 +03:00
|
|
|
|
|
|
|
// properties query
|
2020-05-15 11:37:08 +03:00
|
|
|
body += ' <' + this._client.xmlNamespaces['DAV:'] + ':prop>\n'
|
2016-02-08 13:43:42 +03:00
|
|
|
_.each(properties, function(prop) {
|
2020-05-15 11:37:08 +03:00
|
|
|
const property = self._client.parseClarkNotation(prop)
|
|
|
|
body += ' <' + self._client.xmlNamespaces[property.namespace] + ':' + property.name + ' />\n'
|
|
|
|
})
|
2016-02-08 13:43:42 +03:00
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
body += ' </' + this._client.xmlNamespaces['DAV:'] + ':prop>\n'
|
2016-02-08 13:43:42 +03:00
|
|
|
|
|
|
|
// rules block
|
2020-05-15 11:37:08 +03:00
|
|
|
body += ' <oc:filter-rules>\n'
|
2016-02-08 13:43:42 +03:00
|
|
|
_.each(filter.systemTagIds, function(systemTagIds) {
|
2020-05-15 11:37:08 +03:00
|
|
|
body += ' <oc:systemtag>' + escapeHTML(systemTagIds) + '</oc:systemtag>\n'
|
|
|
|
})
|
2017-09-30 00:43:04 +03:00
|
|
|
_.each(filter.circlesIds, function(circlesIds) {
|
2020-05-15 11:37:08 +03:00
|
|
|
body += ' <oc:circle>' + escapeHTML(circlesIds) + '</oc:circle>\n'
|
|
|
|
})
|
2016-09-12 18:09:46 +03:00
|
|
|
if (filter.favorite) {
|
2020-05-15 11:37:08 +03:00
|
|
|
body += ' <oc:favorite>' + (filter.favorite ? '1' : '0') + '</oc:favorite>\n'
|
2016-09-12 18:09:46 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
body += ' </oc:filter-rules>\n'
|
2016-02-08 13:43:42 +03:00
|
|
|
|
|
|
|
// end of root
|
2020-05-15 11:37:08 +03:00
|
|
|
body += '</oc:filter-files>\n'
|
2016-02-08 13:43:42 +03:00
|
|
|
|
|
|
|
this._client.request(
|
|
|
|
'REPORT',
|
|
|
|
this._buildUrl(),
|
2016-02-16 19:28:35 +03:00
|
|
|
{},
|
2016-02-08 13:43:42 +03:00
|
|
|
body
|
|
|
|
).then(function(result) {
|
|
|
|
if (self._isSuccessStatus(result.status)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
const results = self._parseResult(result.body)
|
|
|
|
deferred.resolve(result.status, results)
|
2016-02-08 13:43:42 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
result = _.extend(result, self._getSabreException(result))
|
|
|
|
deferred.reject(result.status, result)
|
2016-02-08 13:43:42 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
})
|
|
|
|
return promise
|
2016-02-08 13:43:42 +03:00
|
|
|
},
|
|
|
|
|
2015-07-13 18:31:47 +03:00
|
|
|
/**
|
|
|
|
* Returns the file info of a given path.
|
|
|
|
*
|
|
|
|
* @param {String} path path
|
2015-11-02 16:17:49 +03:00
|
|
|
* @param {Array} [options.properties] list of Webdav properties to retrieve
|
2015-07-13 18:31:47 +03:00
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {Promise} promise
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
2015-11-02 16:17:49 +03:00
|
|
|
getFileInfo: function(path, options) {
|
2015-07-13 18:31:47 +03:00
|
|
|
if (!path) {
|
2020-05-15 11:37:08 +03:00
|
|
|
path = ''
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
options = options || {}
|
|
|
|
const self = this
|
|
|
|
const deferred = $.Deferred()
|
|
|
|
const promise = deferred.promise()
|
|
|
|
let properties
|
2015-11-02 16:17:49 +03:00
|
|
|
if (_.isUndefined(options.properties)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
properties = this.getPropfindProperties()
|
2015-11-02 16:17:49 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
properties = options.properties
|
2015-11-02 16:17:49 +03:00
|
|
|
}
|
2015-07-13 18:31:47 +03:00
|
|
|
|
|
|
|
// TODO: headers
|
|
|
|
this._client.propFind(
|
|
|
|
this._buildUrl(path),
|
2015-11-02 16:17:49 +03:00
|
|
|
properties,
|
2015-07-13 18:31:47 +03:00
|
|
|
0
|
|
|
|
).then(
|
|
|
|
function(result) {
|
|
|
|
if (self._isSuccessStatus(result.status)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
deferred.resolve(result.status, self._parseResult([result.body])[0])
|
2015-07-13 18:31:47 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
result = _.extend(result, self._getSabreException(result))
|
|
|
|
deferred.reject(result.status, result)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
)
|
|
|
|
return promise
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the contents of the given file.
|
|
|
|
*
|
|
|
|
* @param {String} path path to file
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {Promise}
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
|
|
|
getFileContents: function(path) {
|
|
|
|
if (!path) {
|
2020-05-15 11:37:08 +03:00
|
|
|
throw 'Missing argument "path"'
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
const self = this
|
|
|
|
const deferred = $.Deferred()
|
|
|
|
const promise = deferred.promise()
|
2015-07-13 18:31:47 +03:00
|
|
|
|
|
|
|
this._client.request(
|
|
|
|
'GET',
|
2016-02-16 19:28:35 +03:00
|
|
|
this._buildUrl(path)
|
2015-07-13 18:31:47 +03:00
|
|
|
).then(
|
|
|
|
function(result) {
|
|
|
|
if (self._isSuccessStatus(result.status)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
deferred.resolve(result.status, result.body)
|
2015-07-13 18:31:47 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
result = _.extend(result, self._getSabreException(result))
|
|
|
|
deferred.reject(result.status, result)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
)
|
|
|
|
return promise
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {Promise}
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
|
|
|
putFileContents: function(path, body, options) {
|
|
|
|
if (!path) {
|
2020-05-15 11:37:08 +03:00
|
|
|
throw 'Missing argument "path"'
|
|
|
|
}
|
|
|
|
const self = this
|
|
|
|
const deferred = $.Deferred()
|
|
|
|
const promise = deferred.promise()
|
|
|
|
options = options || {}
|
|
|
|
const headers = {}
|
|
|
|
let contentType = 'text/plain;charset=utf-8'
|
2015-07-13 18:31:47 +03:00
|
|
|
if (options.contentType) {
|
2020-05-15 11:37:08 +03:00
|
|
|
contentType = options.contentType
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
headers['Content-Type'] = contentType
|
2015-07-13 18:31:47 +03:00
|
|
|
|
|
|
|
if (_.isUndefined(options.overwrite) || options.overwrite) {
|
|
|
|
// will trigger 412 precondition failed if a file already exists
|
2020-05-15 11:37:08 +03:00
|
|
|
headers['If-None-Match'] = '*'
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
this._client.request(
|
|
|
|
'PUT',
|
|
|
|
this._buildUrl(path),
|
|
|
|
headers,
|
|
|
|
body || ''
|
|
|
|
).then(
|
|
|
|
function(result) {
|
|
|
|
if (self._isSuccessStatus(result.status)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
deferred.resolve(result.status)
|
2015-07-13 18:31:47 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
result = _.extend(result, self._getSabreException(result))
|
|
|
|
deferred.reject(result.status, result)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
)
|
|
|
|
return promise
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
_simpleCall: function(method, path) {
|
|
|
|
if (!path) {
|
2020-05-15 11:37:08 +03:00
|
|
|
throw 'Missing argument "path"'
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const self = this
|
|
|
|
const deferred = $.Deferred()
|
|
|
|
const promise = deferred.promise()
|
2015-07-13 18:31:47 +03:00
|
|
|
|
|
|
|
this._client.request(
|
|
|
|
method,
|
2016-02-16 19:28:35 +03:00
|
|
|
this._buildUrl(path)
|
2015-07-13 18:31:47 +03:00
|
|
|
).then(
|
|
|
|
function(result) {
|
|
|
|
if (self._isSuccessStatus(result.status)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
deferred.resolve(result.status)
|
2015-07-13 18:31:47 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
result = _.extend(result, self._getSabreException(result))
|
|
|
|
deferred.reject(result.status, result)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
)
|
|
|
|
return promise
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a directory
|
|
|
|
*
|
|
|
|
* @param {String} path path to create
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {Promise}
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
|
|
|
createDirectory: function(path) {
|
2020-05-15 11:37:08 +03:00
|
|
|
return this._simpleCall('MKCOL', path)
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deletes a file or directory
|
|
|
|
*
|
|
|
|
* @param {String} path path to delete
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {Promise}
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
|
|
|
remove: function(path) {
|
2020-05-15 11:37:08 +03:00
|
|
|
return this._simpleCall('DELETE', path)
|
2015-07-13 18:31:47 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
2016-10-07 17:27:54 +03:00
|
|
|
* @param {Object} [headers=null] additional headers
|
2015-07-13 18:31:47 +03:00
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {Promise} promise
|
2015-07-13 18:31:47 +03:00
|
|
|
*/
|
2016-10-07 17:27:54 +03:00
|
|
|
move: function(path, destinationPath, allowOverwrite, headers) {
|
2015-07-13 18:31:47 +03:00
|
|
|
if (!path) {
|
2020-05-15 11:37:08 +03:00
|
|
|
throw 'Missing argument "path"'
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
if (!destinationPath) {
|
2020-05-15 11:37:08 +03:00
|
|
|
throw 'Missing argument "destinationPath"'
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const self = this
|
|
|
|
const deferred = $.Deferred()
|
|
|
|
const promise = deferred.promise()
|
2016-10-07 17:27:54 +03:00
|
|
|
headers = _.extend({}, headers, {
|
2020-05-15 11:37:08 +03:00
|
|
|
'Destination': this._buildUrl(destinationPath),
|
|
|
|
})
|
2015-07-13 18:31:47 +03:00
|
|
|
|
|
|
|
if (!allowOverwrite) {
|
2020-05-15 11:37:08 +03:00
|
|
|
headers.Overwrite = 'F'
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
this._client.request(
|
|
|
|
'MOVE',
|
|
|
|
this._buildUrl(path),
|
2017-08-27 16:28:26 +03:00
|
|
|
headers
|
|
|
|
).then(
|
2017-08-08 17:37:14 +03:00
|
|
|
function(result) {
|
|
|
|
if (self._isSuccessStatus(result.status)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
deferred.resolve(result.status)
|
2017-08-27 16:28:26 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
result = _.extend(result, self._getSabreException(result))
|
|
|
|
deferred.reject(result.status, result)
|
2017-08-27 16:28:26 +03:00
|
|
|
}
|
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
)
|
|
|
|
return promise
|
2017-08-27 16:28:26 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {Promise} promise
|
2017-08-27 16:28:26 +03:00
|
|
|
*/
|
2020-05-15 11:37:08 +03:00
|
|
|
copy: function(path, destinationPath, allowOverwrite) {
|
2017-08-27 16:28:26 +03:00
|
|
|
if (!path) {
|
2020-05-15 11:37:08 +03:00
|
|
|
throw 'Missing argument "path"'
|
2017-08-27 16:28:26 +03:00
|
|
|
}
|
|
|
|
if (!destinationPath) {
|
2020-05-15 11:37:08 +03:00
|
|
|
throw 'Missing argument "destinationPath"'
|
2017-08-27 16:28:26 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const self = this
|
|
|
|
const deferred = $.Deferred()
|
|
|
|
const promise = deferred.promise()
|
|
|
|
const headers = {
|
|
|
|
'Destination': this._buildUrl(destinationPath),
|
|
|
|
}
|
2017-08-27 16:28:26 +03:00
|
|
|
|
|
|
|
if (!allowOverwrite) {
|
2020-05-15 11:37:08 +03:00
|
|
|
headers.Overwrite = 'F'
|
2017-08-27 16:28:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
this._client.request(
|
|
|
|
'COPY',
|
|
|
|
this._buildUrl(path),
|
2015-07-13 18:31:47 +03:00
|
|
|
headers
|
|
|
|
).then(
|
|
|
|
function(response) {
|
|
|
|
if (self._isSuccessStatus(response.status)) {
|
2020-05-15 11:37:08 +03:00
|
|
|
deferred.resolve(response.status)
|
2015-07-13 18:31:47 +03:00
|
|
|
} else {
|
2020-05-15 11:37:08 +03:00
|
|
|
deferred.reject(response.status)
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
}
|
2020-05-15 11:37:08 +03:00
|
|
|
)
|
|
|
|
return promise
|
2015-11-02 16:17:49 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a file info parser function
|
|
|
|
*
|
2018-10-24 17:24:16 +03:00
|
|
|
* @param {OC.Files.Client~parseFileInfo} parserFunction
|
2015-11-02 16:17:49 +03:00
|
|
|
*/
|
|
|
|
addFileInfoParser: function(parserFunction) {
|
2020-05-15 11:37:08 +03:00
|
|
|
this._fileInfoParsers.push(parserFunction)
|
2016-09-03 19:06:35 +03:00
|
|
|
},
|
2015-07-13 18:31:47 +03:00
|
|
|
|
2016-09-03 19:06:35 +03:00
|
|
|
/**
|
|
|
|
* Returns the dav.Client instance used internally
|
|
|
|
*
|
2016-11-15 20:51:52 +03:00
|
|
|
* @since 11.0.0
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {dav.Client}
|
2016-09-03 19:06:35 +03:00
|
|
|
*/
|
|
|
|
getClient: function() {
|
2020-05-15 11:37:08 +03:00
|
|
|
return this._client
|
2016-09-03 19:06:35 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the user name
|
|
|
|
*
|
2016-11-15 20:51:52 +03:00
|
|
|
* @since 11.0.0
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {String} userName
|
2016-09-03 19:06:35 +03:00
|
|
|
*/
|
|
|
|
getUserName: function() {
|
2020-05-15 11:37:08 +03:00
|
|
|
return this._client.userName
|
2016-09-03 19:06:35 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2016-11-21 17:03:45 +03:00
|
|
|
* Returns the password
|
2016-09-03 19:06:35 +03:00
|
|
|
*
|
2016-11-15 20:51:52 +03:00
|
|
|
* @since 11.0.0
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {String} password
|
2016-09-03 19:06:35 +03:00
|
|
|
*/
|
|
|
|
getPassword: function() {
|
2020-05-15 11:37:08 +03:00
|
|
|
return this._client.password
|
2016-09-03 19:06:35 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the base URL
|
|
|
|
*
|
2016-11-15 20:51:52 +03:00
|
|
|
* @since 11.0.0
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {String} base URL
|
2016-09-03 19:06:35 +03:00
|
|
|
*/
|
|
|
|
getBaseUrl: function() {
|
2020-05-15 11:37:08 +03:00
|
|
|
return this._client.baseUrl
|
2016-10-07 17:27:54 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the host
|
|
|
|
*
|
|
|
|
* @since 13.0.0
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {String} base URL
|
2016-10-07 17:27:54 +03:00
|
|
|
*/
|
|
|
|
getHost: function() {
|
2020-05-15 11:37:08 +03:00
|
|
|
return this._host
|
|
|
|
},
|
|
|
|
}
|
2015-07-13 18:31:47 +03:00
|
|
|
|
2015-11-02 16:17:49 +03:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2015-07-13 18:31:47 +03:00
|
|
|
if (!OC.Files) {
|
|
|
|
/**
|
|
|
|
* @namespace OC.Files
|
|
|
|
*
|
|
|
|
* @since 8.2
|
|
|
|
*/
|
2020-05-15 11:37:08 +03:00
|
|
|
OC.Files = {}
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the default instance of the files client
|
|
|
|
*
|
2020-05-15 11:37:08 +03:00
|
|
|
* @returns {OC.Files.Client} default client
|
2015-07-13 18:31:47 +03:00
|
|
|
*
|
|
|
|
* @since 8.2
|
|
|
|
*/
|
|
|
|
OC.Files.getClient = function() {
|
|
|
|
if (OC.Files._defaultClient) {
|
2020-05-15 11:37:08 +03:00
|
|
|
return OC.Files._defaultClient
|
2015-07-13 18:31:47 +03:00
|
|
|
}
|
|
|
|
|
2020-05-15 11:37:08 +03:00
|
|
|
const client = new OC.Files.Client({
|
2015-07-13 18:31:47 +03:00
|
|
|
host: OC.getHost(),
|
|
|
|
port: OC.getPort(),
|
2018-05-09 00:02:19 +03:00
|
|
|
root: OC.linkToRemoteBase('dav') + '/files/' + OC.getCurrentUser().uid,
|
2020-05-15 11:37:08 +03:00
|
|
|
useHTTPS: OC.getProtocol() === 'https',
|
|
|
|
})
|
|
|
|
OC.Files._defaultClient = client
|
|
|
|
return client
|
|
|
|
}
|
|
|
|
|
|
|
|
OC.Files.Client = Client
|
|
|
|
})(OC, OC.Files.FileInfo)
|