diff --git a/www/common/common-hash.js b/www/common/common-hash.js index 4b0c2c607..d5066b757 100644 --- a/www/common/common-hash.js +++ b/www/common/common-hash.js @@ -398,10 +398,16 @@ Version 1 Hash.findWeaker = function (href, channel, recents) { var parsed = parsePadUrl(href); if (!parsed.hash) { return false; } + // We can't have a weaker hash if we're already in view mode + if (parsed.hashData && parsed.hashData.mode === 'view') { return; } var weaker; Object.keys(recents).some(function (id) { var pad = recents[id]; - var p = parsePadUrl(pad.href); + if (pad.href || !pad.roHref) { + // This pad has an edit link, so it can't be weaker + return; + } + var p = parsePadUrl(pad.roHref); if (p.type !== parsed.type) { return; } // Not the same type if (p.hash === parsed.hash) { return; } // Same hash, not stronger if (channel !== pad.channel) { return; } // Not the same channel @@ -430,6 +436,10 @@ Version 1 var stronger; Object.keys(recents).some(function (id) { var pad = recents[id]; + if (!pad.href) { + // This pad doesn't have an edit link, so it can't be stronger + return; + } var p = parsePadUrl(pad.href); if (p.type !== parsed.type) { return; } // Not the same type if (p.hash === parsed.hash) { return; } // Same hash, not stronger diff --git a/www/common/mergeDrive.js b/www/common/mergeDrive.js index ea4c6edc7..bcc30666e 100644 --- a/www/common/mergeDrive.js +++ b/www/common/mergeDrive.js @@ -115,23 +115,24 @@ define([ 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; + return newRecentPads[id].href || newRecentPads[id].roHref; }); oldFiles.forEach(function (id) { - var href = oldRecentPads[id].href; + var href = oldRecentPads[id].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 (Hash.findStronger(href, oldRecentPads[id].channel, newRecentPads)) { return; } + // 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 - // NOTE: if that weaker version is in the trash, the strong one will be put in unsorted - var weaker = Hash.findWeaker(href, oldRecentPads[id].channel, newRecentPads); - if (weaker) { - // Update RECENTPADS - weaker.href = href; - // Update the file in the drive - newFo.replace(weaker.href, href); - return; + // 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); diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index 52c0efb9c..3837b338a 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -426,10 +426,11 @@ define([ cb(JSON.parse(JSON.stringify(metadata))); }; - var makePad = function (href, title) { + var makePad = function (href, roHref, title) { var now = +new Date(); return { href: href, + roHref: roHref, atime: now, ctime: now, title: title || Hash.getDefaultName(Hash.parsePadUrl(href)), @@ -437,8 +438,13 @@ define([ }; Store.addPad = function (clientId, data, cb) { - if (!data.href) { return void cb({error:'NO_HREF'}); } - var pad = makePad(data.href, data.title); + if (!data.href && !data.roHref) { return void cb({error:'NO_HREF'}); } + if (!data.roHref) { + var parsed = Hash.parsePadUrl(data.href); + var secret = Hash.getSecrets(parsed.type, parsed.hash, data.password); + data.roHref = '/' + parsed.type + '/#' + Hash.getViewHashFromKeys(secret); + } + var pad = makePad(data.href, data.roHref, data.title); if (data.owners) { pad.owners = data.owners; } if (data.expire) { pad.expire = data.expire; } if (data.password) { pad.password = data.password; } @@ -736,9 +742,9 @@ define([ // Edit > Edit (present) > View > View (present) for (var id in allPads) { var pad = allPads[id]; - if (!pad.href) { continue; } + if (!pad.href || !pad.roHref) { continue; } - var p2 = Hash.parsePadUrl(pad.href); + var p2 = Hash.parsePadUrl(pad.href || pad.roHref); var h2 = p2.hashData; // Different types, proceed to the next one @@ -789,8 +795,14 @@ define([ // Add the pad if it does not exist in our drive if (!contains) { + var roHref; + if (h.mode === "view") { + roHref = href; + href = undefined; + } Store.addPad(clientId, { href: href, + roHref: roHref, channel: channel, title: title, owners: owners, @@ -827,7 +839,7 @@ define([ }; store.userObject.getFiles(where).forEach(function (id) { var data = store.userObject.getFileData(id); - var parsed = Hash.parsePadUrl(data.href); + var parsed = Hash.parsePadUrl(data.href || data.roHref); if ((!types || types.length === 0 || types.indexOf(parsed.type) !== -1) && hashes.indexOf(parsed.hash) === -1 && !isFiltered(parsed.type, data)) { diff --git a/www/common/outer/userObject.js b/www/common/outer/userObject.js index 31e70a3bb..630f8aae1 100644 --- a/www/common/outer/userObject.js +++ b/www/common/outer/userObject.js @@ -50,19 +50,6 @@ define([ var data = exp.getFileData(id); cb(null, clone(data[attr])); }; - var removePadAttribute = exp.removePadAttribute = function (f) { - if (typeof(f) !== 'string') { - console.error("Can't find pad attribute for an undefined pad"); - return; - } - Object.keys(files).forEach(function (key) { - var hash = f.indexOf('#') !== -1 ? f.slice(f.indexOf('#') + 1) : null; - if (hash && key.indexOf(hash) === 0) { - exp.debug("Deleting pad attribute in the realtime object"); - delete files[key]; - } - }); - }; exp.pushData = function (data, cb) { if (typeof cb !== "function") { cb = function () {}; } @@ -145,12 +132,14 @@ define([ if (!loggedIn && !config.testMode) { allFilesPaths.forEach(function (path) { + var id = path[1]; + /* XXX var el = exp.find(path); if (!el) { return; } var id = exp.getIdFromHref(el.href); + */ if (!id) { return; } spliceFileData(id); - removePadAttribute(el.href); }); return; } @@ -259,7 +248,6 @@ define([ if (!id) { return; } if (!loggedIn && !config.testMode) { // delete permanently - exp.removePadAttribute(href); spliceFileData(id); return; } @@ -268,6 +256,7 @@ define([ }; // REPLACE + /* XXX exp.replace = function (o, n) { var idO = exp.getIdFromHref(o); if (!idO || !exp.isFile(idO)) { return; } @@ -275,7 +264,8 @@ define([ if (!data) { return; } data.href = n; }; - // If all the occurences of an href are in the trash, remvoe them and add the file in root. + */ + // If all the occurences of an href are in the trash, remove them and add the file in root. // This is use with setPadTitle when we open a stronger version of a deleted pad exp.restoreHref = function (href) { var idO = exp.getIdFromHref(href); @@ -563,13 +553,15 @@ define([ continue; } // Clean missing href - if (!el.href) { + if (!el.href && !el.roHref) { debug("Removing an element in filesData with a missing href.", el); toClean.push(id); continue; } - var parsed = Hash.parsePadUrl(el.href); + var parsed = Hash.parsePadUrl(el.href || el.roHref); + var secret; + // Clean invalid hash if (!parsed.hash) { debug("Removing an element in filesData with a invalid href.", el); @@ -583,6 +575,22 @@ define([ continue; } + // If we have an edit link, check the view link + if (el.href) { + var fixRo = function () { + secret = Hash.getSecrets(parsed.type, parsed.hash, el.password); + el.roHref = '/' + parsed.type + '/#' + Hash.getViewHasFromKeys(secret); + }; + if (!el.roHref) { + fixRo(); + } else { + var parsed2 = Hash.parsePadUrl(el.roHref); + if (!parsed2.hash || !parsed2.type) { + fixRo(); + } + } + } + // Fix href if (/^https*:\/\//.test(el.href)) { el.href = Hash.getRelativeHref(el.href); } // Fix creation time @@ -592,7 +600,9 @@ define([ // Fix channel if (!el.channel) { try { - var secret = Hash.getSecrets(parsed.type, parsed.hash, el.password); + if (!secret) { + secret = Hash.getSecrets(parsed.type, parsed.hash, el.password); + } el.channel = secret.channel; console.log('Adding missing channel in filesData ', el.channel); } catch (e) { diff --git a/www/common/userObject.js b/www/common/userObject.js index fb39eb484..4d8a6a0a2 100644 --- a/www/common/userObject.js +++ b/www/common/userObject.js @@ -78,11 +78,14 @@ define([ exp.isReadOnlyFile = function (element) { if (!isFile(element)) { return false; } var data = exp.getFileData(element); + return Boolean(data.roHref && !data.href); + /* XXX var parsed = Hash.parsePadUrl(data.href); if (!parsed) { return false; } var pHash = parsed.hashData; if (!pHash || pHash.type !== "pad") { return; } return pHash && pHash.mode === 'view'; + */ }; var isFolder = exp.isFolder = function (element) { @@ -139,7 +142,7 @@ define([ var getTitle = exp.getTitle = function (file, type) { if (workgroup) { debug("No titles in workgroups"); return; } var data = getFileData(file); - if (!file || !data || !data.href) { + if (!file || !data || !(data.href || data.roHref)) { error("getTitle called with a non-existing file id: ", file, data); return; } @@ -288,7 +291,8 @@ define([ var getIdFromHref = exp.getIdFromHref = function (href) { var result; getFiles([FILES_DATA]).some(function (id) { - if (files[FILES_DATA][id].href === href) { + if (files[FILES_DATA][id].href === href || + files[FILES_DATA][id].roHref === href) { result = id; return true; }