|
|
|
/*jshint esversion: 6 */
|
|
|
|
const Block = module.exports;
|
|
|
|
const Util = require("../common-util");
|
|
|
|
const Path = require("path");
|
|
|
|
const Fs = require("fs");
|
|
|
|
const Fse = require("fs-extra");
|
|
|
|
const nThen = require("nthen");
|
|
|
|
|
|
|
|
Block.mkPath = function (Env, publicKey) {
|
|
|
|
// prepare publicKey to be used as a file name
|
|
|
|
var safeKey = Util.escapeKeyCharacters(publicKey);
|
|
|
|
|
|
|
|
// validate safeKey
|
|
|
|
if (typeof(safeKey) !== 'string') { return; }
|
|
|
|
|
|
|
|
// derive the full path
|
|
|
|
// /home/cryptpad/cryptpad/block/fg/fg32kefksjdgjkewrjksdfksjdfsdfskdjfsfd
|
|
|
|
return Path.join(Env.paths.block, safeKey.slice(0, 2), safeKey);
|
|
|
|
};
|
|
|
|
|
|
|
|
Block.mkArchivePath = function (Env, publicKey) {
|
|
|
|
// prepare publicKey to be used as a file name
|
|
|
|
var safeKey = Util.escapeKeyCharacters(publicKey);
|
|
|
|
|
|
|
|
// validate safeKey
|
|
|
|
if (typeof(safeKey) !== 'string') {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// derive the full path
|
|
|
|
// /home/cryptpad/cryptpad/block/fg/fg32kefksjdgjkewrjksdfksjdfsdfskdjfsfd
|
|
|
|
return Path.join(Env.paths.archive, 'block', safeKey.slice(0, 2), safeKey);
|
|
|
|
};
|
|
|
|
|
|
|
|
Block.archive = function (Env, publicKey, _cb) {
|
|
|
|
var cb = Util.once(Util.mkAsync(_cb));
|
|
|
|
|
|
|
|
// derive the filepath
|
|
|
|
var currentPath = Block.mkPath(Env, publicKey);
|
|
|
|
|
|
|
|
// make sure the path is valid
|
|
|
|
if (typeof(currentPath) !== 'string') {
|
|
|
|
return void cb('E_INVALID_BLOCK_PATH');
|
|
|
|
}
|
|
|
|
|
|
|
|
var archivePath = Block.mkArchivePath(Env, publicKey);
|
|
|
|
// make sure the path is valid
|
|
|
|
if (typeof(archivePath) !== 'string') {
|
|
|
|
return void cb('E_INVALID_BLOCK_ARCHIVAL_PATH');
|
|
|
|
}
|
|
|
|
|
|
|
|
Fse.move(currentPath, archivePath, {
|
|
|
|
overwrite: true,
|
|
|
|
}, cb);
|
|
|
|
};
|
|
|
|
|
|
|
|
Block.check = function (Env, publicKey, _cb) { // 'check' because 'exists' implies boolean
|
|
|
|
var cb = Util.once(Util.mkAsync(_cb));
|
|
|
|
var path = Block.mkPath(Env, publicKey);
|
|
|
|
Fs.access(path, Fs.constants.F_OK, cb);
|
|
|
|
};
|
|
|
|
|
|
|
|
Block.write = function (Env, publicKey, buffer, _cb) {
|
|
|
|
var cb = Util.once(Util.mkAsync(_cb));
|
|
|
|
var path = Block.mkPath(Env, publicKey);
|
|
|
|
if (typeof(path) !== 'string') { return void cb('INVALID_PATH'); }
|
|
|
|
var parsed = Path.parse(path);
|
|
|
|
|
|
|
|
nThen(function (w) {
|
|
|
|
Fse.mkdirp(parsed.dir, w(function (err) {
|
|
|
|
if (!err) { return; }
|
|
|
|
w.abort();
|
|
|
|
cb(err);
|
|
|
|
}));
|
|
|
|
}).nThen(function (w) {
|
|
|
|
Block.archive(Env, publicKey, w(function (/* err */) {
|
|
|
|
/*
|
|
|
|
we proceed even if there are errors.
|
|
|
|
it might be ENOENT (there is no file to archive)
|
|
|
|
or EACCES (bad filesystem permissions for the existing archived block?)
|
|
|
|
or lots of other things, none of which justify preventing the write
|
|
|
|
*/
|
|
|
|
}));
|
|
|
|
}).nThen(function () {
|
|
|
|
Fs.writeFile(path, buffer, { encoding: 'binary' }, cb);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|