keeweb/app/scripts/storage/storage-webdav.js

143 lines
4.9 KiB
JavaScript
Raw Normal View History

2016-03-12 12:22:35 +01:00
'use strict';
var Logger = require('../util/logger');
var logger = new Logger('storage-webdav');
var StorageDropbox = {
name: 'webdav',
icon: 'server',
enabled: true,
openFields: [
2016-03-12 17:49:52 +01:00
{ id: 'path', title: 'openUrl', desc: 'openUrlDesc', type: 'text', required: true },
{ id: 'user', title: 'openUser', desc: 'openUserDesc', placeholder: 'openUserPlaceholder', type: 'text' },
{ id: 'password', title: 'openPass', desc: 'openPassDesc', placeholder: 'openPassPlaceholder', type: 'password' }
2016-03-12 12:22:35 +01:00
],
2016-03-12 17:49:52 +01:00
load: function(path, opts, callback) {
2016-03-12 12:22:35 +01:00
logger.debug('Load', path);
2016-03-12 17:49:52 +01:00
this._request({
op: 'Load',
method: 'GET',
path: path,
user: opts ? opts.user : null,
password: opts ? opts.password : null
}, callback ? function(err, xhr, stat) {
callback(err, xhr.response, stat);
} : null);
2016-03-12 12:22:35 +01:00
},
2016-03-12 17:49:52 +01:00
stat: function(path, opts, callback) {
2016-03-12 12:22:35 +01:00
logger.debug('Stat', path);
2016-03-12 17:49:52 +01:00
this._request({
op: 'Stat',
method: 'HEAD',
path: path,
user: opts ? opts.user : null,
password: opts ? opts.password : null
}, callback ? function(err, xhr, stat) {
callback(err, stat);
} : null);
2016-03-12 12:22:35 +01:00
},
2016-03-12 17:49:52 +01:00
save: function(path, opts, data, callback, rev) {
2016-03-12 12:22:35 +01:00
logger.debug('Save', path, rev);
2016-03-12 17:49:52 +01:00
var etag, lastModified;
if (rev && rev.charAt(0) === 'E') {
etag = rev.substr(1);
} else if (rev && rev.charAt(0) === 'T') {
lastModified = rev.substr(1);
}
var cb = callback ? function(err, xhr, stat) {
callback(err, stat);
} : null;
var saveOpts = {
op: 'Save',
method: 'POST',
path: path,
user: opts ? opts.user : null,
password: opts ? opts.password : null,
data: data,
etag: etag
};
if (lastModified) {
logger.debug('Stat before save', path, rev);
this.stat(path, opts, function(err, stat) {
if (err) { return cb(err); }
if (stat.rev !== rev) {
logger.debug('Save error', path, 'rev conflict', stat.rev, rev);
return cb({ revConflict: true });
}
this._request(saveOpts, cb);
});
} else {
this._request(saveOpts, cb);
}
},
_request: function(config, callback) {
2016-03-12 12:22:35 +01:00
var ts = logger.ts();
2016-03-12 17:49:52 +01:00
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', function() {
if (xhr.status !== 200) {
logger.debug(config.op + ' error', config.path, xhr.status, logger.ts(ts));
var err;
switch (xhr.status) {
case 404:
err = { notFound: true };
break;
case 412:
err = { revConflict: true };
break;
default:
err = 'HTTP status ' + xhr.status;
break;
}
if (callback) { callback(err); callback = null; }
return;
}
var rev = xhr.getResponseHeader('ETag');
if (rev) {
rev = 'E' + rev;
} else {
rev = xhr.getResponseHeader('Last-Modified');
if (rev) {
rev = 'T' + rev;
}
}
if (!rev) {
logger.debug(config.op + ' error', config.path, 'no headers', logger.ts(ts));
if (callback) { callback('No header ETag or Last-Modified'); callback = null; }
return;
}
logger.debug(config.op + 'ed', config.path, rev, logger.ts(ts));
if (callback) { callback(null, xhr, rev ? { rev: rev } : null); callback = null; }
});
xhr.addEventListener('error', function() {
logger.debug(config.op + ' error', config.path, logger.ts(ts));
if (callback) { callback('network error'); callback = null; }
});
xhr.addEventListener('abort', function() {
logger.debug(config.op + ' error', config.path, 'aborted', logger.ts(ts));
if (callback) { callback('aborted'); callback = null; }
});
xhr.responseType = 'arraybuffer';
xhr.open(config.method, config.path);
if (config.user) {
xhr.setRequestHeader('Authorization', 'Basic ' + btoa(config.user + ':' + config.password));
}
if (config.etag) {
xhr.setRequestHeader('If-Match', config.etag);
}
if (config.data) {
var blob = new Blob([config.data], {type: 'application/octet-stream'});
xhr.send(blob);
} else {
xhr.send();
}
2016-03-12 12:22:35 +01:00
}
};
module.exports = StorageDropbox;