1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2025-02-22 14:00:03 +00:00

Refactor importing of encrypted TiddlyWiki files so that it works on Node.js

This commit is contained in:
Jermolene 2014-01-19 20:13:55 +00:00
parent 98edbec46d
commit ed5cf8b044
3 changed files with 96 additions and 51 deletions

View File

@ -100,7 +100,7 @@ exports["text/html"] = function(text,fields) {
var storeAreaMarkerRegExp = /<div id=["']?storeArea['"]?( style=["']?display:none;["']?)?>/gi,
match = storeAreaMarkerRegExp.exec(text);
if(match) {
// If so, it's either a classic TiddlyWiki file or a TW5 file
// If so, it's either a classic TiddlyWiki file or an unencrypted TW5 file
// First read the normal tiddlers
var results = deserializeTiddlyWikiFile(text,storeAreaMarkerRegExp.lastIndex,!!match[1],fields);
// Then any system tiddlers
@ -111,8 +111,15 @@ exports["text/html"] = function(text,fields) {
}
return results
} else {
// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler
return deserializeHtmlFile(text,fields);
// Check whether we've got an encrypted file
var encryptedStoreArea = $tw.utils.extractEncryptedStoreArea(text);
if(encryptedStoreArea) {
// If so, attempt to decrypt it using the current password
return $tw.utils.decryptStoreArea(encryptedStoreArea);
} else {
// It's not a TiddlyWiki so we'll return the entire HTML file as a tiddler
return deserializeHtmlFile(text,fields);
}
}
};

View File

@ -0,0 +1,80 @@
/*\
title: $:/core/modules/utils/crypto.js
type: application/javascript
module-type: utils
Utility functions related to crypto.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
/*
Look for an encrypted store area in the text of a TiddlyWiki file
*/
exports.extractEncryptedStoreArea = function(text) {
var encryptedStoreAreaStartMarker = "<pre id=\"encryptedStoreArea\" type=\"text/plain\" style=\"display:none;\">",
encryptedStoreAreaStart = text.indexOf(encryptedStoreAreaStartMarker);
if(encryptedStoreAreaStart !== -1) {
var encryptedStoreAreaEnd = text.indexOf("</pre>",encryptedStoreAreaStart);
if(encryptedStoreAreaEnd !== -1) {
return $tw.utils.htmlDecode(text.substring(encryptedStoreAreaStart + encryptedStoreAreaStartMarker.length,encryptedStoreAreaEnd-1));
}
}
return null;
};
/*
Attempt to extract the tiddlers from an encrypted store area using the current password
*/
exports.decryptStoreArea = function(encryptedStoreArea) {
var decryptedText = $tw.crypto.decrypt(encryptedStoreArea);
if(decryptedText) {
var json = JSON.parse(decryptedText),
tiddlers = [];
for(var title in json) {
tiddlers.push(json[title]);
}
return tiddlers;
} else {
return null;
}
};
exports.decryptStoreAreaInteractive = function(encryptedStoreArea,callback) {
// Try to decrypt with the current password
var tiddlers = $tw.utils.decryptStoreArea(encryptedStoreArea);
if(tiddlers) {
callback(tiddlers);
} else {
// Prompt for a new password and keep trying
$tw.passwordPrompt.createPrompt({
serviceName: "Enter a password to decrypt the imported TiddlyWiki",
noUserName: true,
canCancel: true,
submitText: "Decrypt",
callback: function(data) {
// Exit if the user cancelled
if(!data) {
return false;
}
// Attempt to decrypt the tiddlers
$tw.crypto.setPassword(data.password);
var tiddlers = $tw.utils.decryptStoreArea(encryptedStoreArea);
if(tiddlers) {
callback(tiddlers);
// Exit and remove the password prompt
return true;
} else {
// We didn't decrypt everything, so continue to prompt for password
return false;
}
}
});
}
};
})();

View File

@ -1083,56 +1083,14 @@ exports.readFile = function(file,callback) {
}
} else {
// Check whether this is an encrypted TiddlyWiki file
var encryptedStoreAreaStartMarker = "<pre id=\"encryptedStoreArea\" type=\"text/plain\" style=\"display:none;\">",
encryptedStoreAreaStart = text.indexOf(encryptedStoreAreaStartMarker),
encryptedStoreAreaEnd = encryptedStoreAreaStart !== -1 ? text.indexOf("</pre>",encryptedStoreAreaStart) : -1;
if(encryptedStoreAreaStart !== -1 && encryptedStoreAreaEnd !== -1) {
var encryptedJson = $tw.utils.htmlDecode(text.substring(encryptedStoreAreaStart + encryptedStoreAreaStartMarker.length,encryptedStoreAreaEnd-1)),
attemptDecryption = function() {
var decryptedText = $tw.crypto.decrypt(encryptedJson);
if(decryptedText) {
var json = JSON.parse(decryptedText),
tiddlers = [];
for(var title in json) {
tiddlers.push(json[title]);
}
return tiddlers;
} else {
return null;
}
};
// Try to decrypt with the current password
var tiddlers = attemptDecryption();
if(tiddlers) {
var encryptedJson = $tw.utils.extractEncryptedStoreArea(text);
if(encryptedJson) {
// If so, attempt to decrypt it with the current password
$tw.utils.decryptStoreAreaInteractive(encryptedJson,function(tiddlers) {
callback(tiddlers);
} else {
// Prompt for a new password and keep trying
$tw.passwordPrompt.createPrompt({
serviceName: "Enter a password to decrypt the imported TiddlyWiki",
noUserName: true,
canCancel: true,
submitText: "Decrypt",
callback: function(data) {
// Exit if the user cancelled
if(!data) {
return false;
}
// Attempt to decrypt the tiddlers
$tw.crypto.setPassword(data.password);
var tiddlers = attemptDecryption();
if(tiddlers) {
callback(tiddlers);
// Exit and remove the password prompt
return true;
} else {
// We didn't decrypt everything, so continue to prompt for password
return false;
}
}
});
}
});
} else {
// Try to deserialise any tiddlers in the file
// Otherwise, just try to deserialise any tiddlers in the file
callback(self.deserializeTiddlers(type,text,tiddlerFields));
}
}