|
|
|
define([
|
|
|
|
'/common/cryptget.js',
|
|
|
|
'/common/userObject.js',
|
|
|
|
'/common/common-hash.js',
|
|
|
|
'/common/common-realtime.js',
|
|
|
|
], function (Crypt, FO, Hash, Realtime) {
|
|
|
|
var exp = {};
|
|
|
|
|
|
|
|
var getType = function (el) {
|
|
|
|
if (el === null) { return "null"; }
|
|
|
|
return Array.isArray(el) ? "array" : typeof(el);
|
|
|
|
};
|
|
|
|
|
|
|
|
var findAvailableKey = function (obj, key) {
|
|
|
|
if (typeof (obj[key]) === "undefined") { return key; }
|
|
|
|
var i = 1;
|
|
|
|
var nkey = key;
|
|
|
|
while (typeof (obj[nkey]) !== "undefined") {
|
|
|
|
nkey = key + '_' + i;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return nkey;
|
|
|
|
};
|
|
|
|
|
|
|
|
var createFromPath = function (proxy, oldFo, path, id) {
|
|
|
|
var root = proxy.drive;
|
|
|
|
|
|
|
|
if (!oldFo.isFile(id)) { return; }
|
|
|
|
|
|
|
|
var error = function (msg) {
|
|
|
|
console.error(msg || "Unable to find that path", path);
|
|
|
|
};
|
|
|
|
|
|
|
|
if (oldFo.isInTrashRoot(path)) {
|
|
|
|
id = oldFo.find(path.slice(0,3));
|
|
|
|
path.pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
var next, nextRoot;
|
|
|
|
path.forEach(function (p, i) {
|
|
|
|
if (!root) { return; }
|
|
|
|
if (typeof(p) === "string") {
|
|
|
|
if (getType(root) !== "object") { root = undefined; error(); return; }
|
|
|
|
if (i === path.length - 1) {
|
|
|
|
root[Hash.createChannelId()] = id;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
next = getType(path[i+1]);
|
|
|
|
nextRoot = getType(root[p]);
|
|
|
|
if (nextRoot !== "undefined") {
|
|
|
|
if (next === "string" && nextRoot === "object" || next === "number" && nextRoot === "array") {
|
|
|
|
root = root[p];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
p = findAvailableKey(root, p);
|
|
|
|
}
|
|
|
|
if (next === "number") {
|
|
|
|
root[p] = [];
|
|
|
|
root = root[p];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
root[p] = {};
|
|
|
|
root = root[p];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Path contains a non-string element: it's an array index
|
|
|
|
if (typeof(p) !== "number") { root = undefined; error(); return; }
|
|
|
|
if (getType(root) !== "array") { root = undefined; error(); return; }
|
|
|
|
if (i === path.length - 1) {
|
|
|
|
if (root.indexOf(id) === -1) { root.push(id); }
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
next = getType(path[i+1]);
|
|
|
|
if (next === "number") {
|
|
|
|
error('2 consecutives arrays in the user object');
|
|
|
|
root = undefined;
|
|
|
|
//root.push([]);
|
|
|
|
//root = root[root.length - 1];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
root.push({});
|
|
|
|
root = root[root.length - 1];
|
|
|
|
return;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
exp.anonDriveIntoUser = function (proxyData, fsHash, cb) {
|
|
|
|
// Make sure we have an FS_hash and we don't use it, otherwise just stop the migration and cb
|
|
|
|
if (!fsHash || !proxyData.loggedIn) {
|
|
|
|
if (typeof(cb) === "function") { return void cb(); }
|
|
|
|
}
|
|
|
|
// Get the content of FS_hash and then merge the objects, remove the migration key and cb
|
|
|
|
var todo = function (err, doc) {
|
|
|
|
if (err) { console.error("Cannot migrate recent pads", err); return; }
|
|
|
|
var parsed;
|
|
|
|
if (!doc) {
|
|
|
|
if (typeof(cb) === "function") { cb(); }
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
try { parsed = JSON.parse(doc); } catch (e) {
|
|
|
|
if (typeof(cb) === "function") { cb(); }
|
|
|
|
console.error("Cannot parsed recent pads", e);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (parsed) {
|
|
|
|
var proxy = proxyData.proxy;
|
|
|
|
var oldFo = FO.init(parsed.drive, {
|
|
|
|
loggedIn: proxyData.loggedIn,
|
|
|
|
outer: true
|
|
|
|
});
|
|
|
|
var onMigrated = function () {
|
|
|
|
oldFo.fixFiles(true);
|
|
|
|
var newFo = proxyData.userObject;
|
|
|
|
var oldRecentPads = parsed.drive[newFo.FILES_DATA];
|
|
|
|
var newRecentPads = proxy.drive[newFo.FILES_DATA];
|
|
|
|
var oldFiles = oldFo.getFiles([newFo.FILES_DATA]);
|
|
|
|
var newHrefs = Object.keys(newRecentPads).map(function (id) {
|
|
|
|
return newRecentPads[id].href || newRecentPads[id].roHref;
|
|
|
|
});
|
|
|
|
oldFiles.forEach(function (id) {
|
|
|
|
var href = oldRecentPads[id].href || oldRecentPads[id].roHref;
|
|
|
|
var isRo = href === oldRecentPads[id].roHref;
|
|
|
|
// Do not migrate a pad if we already have it, it would create a duplicate in the drive
|
|
|
|
if (newHrefs.indexOf(href) !== -1) { return; }
|
|
|
|
// If we have a stronger version, do not add the current href
|
|
|
|
// If the current href is read-only, don't check, we won't have a stronger
|
|
|
|
if (isRo && Hash.findStronger(href, oldRecentPads[id].channel, newRecentPads)) { return; }
|
|
|
|
// If we have a weaker version, replace the href by the new one
|
|
|
|
// If the current href is an edit link, don't check, we won't have a weaker
|
|
|
|
if (!isRo) {
|
|
|
|
var weaker = Hash.findWeaker(href, oldRecentPads[id].channel, newRecentPads);
|
|
|
|
if (weaker) {
|
|
|
|
// Update RECENTPADS
|
|
|
|
weaker.href = href;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Here it means we have a new href, so we should add it to the drive at its old location
|
|
|
|
var paths = oldFo.findFile(id);
|
|
|
|
if (paths.length === 0) { return; }
|
|
|
|
// Add the file data in our array and use the id to add the file
|
|
|
|
var data = oldFo.getFileData(id);
|
|
|
|
if (data) {
|
|
|
|
// XXX
|
|
|
|
newFo.pushData(data, function (err, id) {
|
|
|
|
if (err) { return void console.error("Cannot import file:", data, err); }
|
|
|
|
createFromPath(proxy, oldFo, paths[0], id);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (!proxy.FS_hashes || !Array.isArray(proxy.FS_hashes)) {
|
|
|
|
proxy.FS_hashes = [];
|
|
|
|
}
|
|
|
|
proxy.FS_hashes.push(fsHash);
|
|
|
|
if (typeof(cb) === "function") {
|
|
|
|
Realtime.whenRealtimeSyncs(proxyData.realtime, cb);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
oldFo.migrate(onMigrated);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (typeof(cb) === "function") { cb(); }
|
|
|
|
};
|
|
|
|
Crypt.get(fsHash, todo);
|
|
|
|
};
|
|
|
|
|
|
|
|
return exp;
|
|
|
|
});
|