aboutsummaryrefslogtreecommitdiff
path: root/source/import/Importer.mc
diff options
context:
space:
mode:
Diffstat (limited to 'source/import/Importer.mc')
-rw-r--r--source/import/Importer.mc40
1 files changed, 25 insertions, 15 deletions
diff --git a/source/import/Importer.mc b/source/import/Importer.mc
index 9513358..825221b 100644
--- a/source/import/Importer.mc
+++ b/source/import/Importer.mc
@@ -12,6 +12,10 @@
// STORE one item per step: skip, report, or add to the vault. A crash
// leaves only whole entries.
// The report is complete when step() returns true.
+//
+// Memory: while JSON is parsed the pasted text is held once, as the
+// tokenizer's bytes, and parsed items are kept packed (ImportItem.pack);
+// the M8 numbers are in docs/PERFORMANCE.md.
import Toybox.Lang;
@@ -40,7 +44,8 @@ class Importer extends Jobs.Job {
private var _text as String = "";
private var _uris as Array<String>? = null;
private var _aegis as AegisReader? = null;
- private var _items as Array<ImportItem> = [] as Array<ImportItem>;
+ private var _items as Array<ByteArray> = [] as Array<ByteArray>;
+ private var _groups as Dictionary<String, String> = {} as Dictionary<String, String>;
private var _cursor as Number = 0;
private var _ids as Array<String> = [] as Array<String>;
private var _fingerprints as Dictionary<String, String> = {} as Dictionary<String, String>;
@@ -57,7 +62,7 @@ class Importer extends Jobs.Job {
_now = now;
var keys = vault.keyManager.deviceKeys();
var earlier = ImportBuffer.load(vault.storage(), keys, now);
- _text = earlier + text;
+ _text = earlier.length() > 0 ? earlier + text : text;
detect();
}
@@ -65,9 +70,8 @@ class Importer extends Jobs.Job {
function percent() as Number {
if (phase == P_PARSE) {
var a = _aegis;
- var size = _text.length() > 0 ? _text.length() : 1;
if (a != null) {
- return 40 * a.position() / (size > 0 ? size : 1);
+ return 40 * a.position() / (a.size() > 0 ? a.size() : 1);
}
var u = _uris;
return u != null && u.size() > 0 ? 40 * _cursor / u.size() : 0;
@@ -85,7 +89,10 @@ class Importer extends Jobs.Job {
return;
}
if (trimmed.find("{") == 0) {
- _aegis = new AegisReader(Bytes.fromUtf8(trimmed));
+ // The untrimmed text: an incomplete part is saved exactly as
+ // received (a cut can fall on a space inside a string).
+ _aegis = new AegisReader(Bytes.fromUtf8(_text));
+ _text = "";
return;
}
if (Text.findIgnoreCase(trimmed, OtpAuth.MIGRATION_PREFIX, 0) >= 0) {
@@ -133,31 +140,32 @@ class Importer extends Jobs.Job {
return;
}
if (status == AegisReader.INCOMPLETE) {
- var size = Bytes.fromUtf8(_text).size();
- if (ImportBuffer.save(_vault.storage(), _vault.keyManager.deviceKeys(), _text, _now)) {
- report.waitingChars = _text.length();
+ var data = aegis.data();
+ _aegis = null;
+ if (ImportBuffer.save(_vault.storage(), _vault.keyManager.deviceKeys(), data, _now)) {
+ var text = Bytes.toUtf8(data);
+ report.waitingChars = text != null ? text.length() : data.size();
phase = P_DONE;
} else {
- finishWith("the JSON is incomplete and too long to wait for more (" + size + " bytes, at most "
+ finishWith("the JSON is incomplete and too long to wait for more (" + data.size() + " bytes, at most "
+ ImportBuffer.MAX_TEXT_BYTES + ")");
}
- _text = "";
return;
}
if (status == AegisReader.FAILED) {
+ _aegis = null;
finishWith(aegis.error as String);
- _text = "";
return;
}
_items = aegis.items;
+ _groups = aegis.groups;
_aegis = null;
- _text = "";
startReplace();
return;
}
var uris = _uris as Array<String>;
for (var n = 0; n < URIS_PER_STEP && _cursor < uris.size(); n++) {
- _items.add(OtpAuth.parse(uris[_cursor], _cursor + 1));
+ _items.add(OtpAuth.parse(uris[_cursor], _cursor + 1).pack());
_cursor++;
}
if (_cursor >= uris.size()) {
@@ -239,8 +247,10 @@ class Importer extends Jobs.Job {
phase = P_DONE;
return;
}
- var item = _items[_cursor];
- _items[_cursor] = new ImportItem(item.index); // drop the parsed secret
+ var packed = _items[_cursor];
+ _items[_cursor] = []b;
+ var item = ImportItem.unpack(packed, _groups);
+ Bytes.wipe(packed); // the parsed secret; about 110 bytes
_cursor++;
var kind = _kind;
var note = item.note;