@fiduswriter/editor 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,8 +1,117 @@
|
|
|
1
1
|
import { SaveCopy as GenericSaveCopy } from "@fiduswriter/document/exporter/native";
|
|
2
|
-
import { addProgress, gettext, shortFileTitle } from "fwtoolkit";
|
|
2
|
+
import { addAlert, addProgress, gettext, postJson, shortFileTitle } from "fwtoolkit";
|
|
3
3
|
import { E2EEEncryptor } from "../../e2ee/encryptor.js";
|
|
4
4
|
import { E2EEKeyManager } from "../../e2ee/key-manager.js";
|
|
5
5
|
import { NativeImporter } from "@fiduswriter/document/importer/native";
|
|
6
|
+
async function maybeDecryptImage(imageEntry, sourceKey) {
|
|
7
|
+
if (!sourceKey || !imageEntry.file) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (imageEntry.file_type !== "application/octet-stream") {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const fileBuffer = await imageEntry.file.arrayBuffer();
|
|
14
|
+
const bytes = new Uint8Array(fileBuffer);
|
|
15
|
+
let binary = "";
|
|
16
|
+
const chunkSize = 65536;
|
|
17
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
18
|
+
const chunk = bytes.subarray(i, i + chunkSize);
|
|
19
|
+
binary += String.fromCharCode.apply(null, chunk);
|
|
20
|
+
}
|
|
21
|
+
const base64 = btoa(binary);
|
|
22
|
+
const decrypted = await E2EEEncryptor.decryptBufferToBase64(base64, sourceKey);
|
|
23
|
+
const mime = imageEntry.original_file_type || "image/png";
|
|
24
|
+
const byteCharacters = atob(decrypted);
|
|
25
|
+
const byteNumbers = new Array(byteCharacters.length);
|
|
26
|
+
for (let i = 0; i < byteCharacters.length; i++) {
|
|
27
|
+
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
|
28
|
+
}
|
|
29
|
+
const byteArray = new Uint8Array(byteNumbers);
|
|
30
|
+
imageEntry.file = new Blob([byteArray], { type: mime });
|
|
31
|
+
imageEntry.file_type = mime;
|
|
32
|
+
}
|
|
33
|
+
function createNativeImporterBackend(user, e2eeOptions) {
|
|
34
|
+
return {
|
|
35
|
+
createDoc: (template, importId, path, e2ee, files) => {
|
|
36
|
+
const jsonData = {
|
|
37
|
+
template: template.content,
|
|
38
|
+
export_templates: template.exportTemplates,
|
|
39
|
+
document_styles: template.documentStyles,
|
|
40
|
+
import_id: importId
|
|
41
|
+
? importId
|
|
42
|
+
: template.content.attrs.import_id,
|
|
43
|
+
template_title: template.content.attrs.template,
|
|
44
|
+
path
|
|
45
|
+
};
|
|
46
|
+
if (e2ee?.enabled) {
|
|
47
|
+
jsonData.e2ee = true;
|
|
48
|
+
if (e2ee.salt) {
|
|
49
|
+
jsonData.e2ee_salt = e2ee.salt;
|
|
50
|
+
}
|
|
51
|
+
if (e2ee.iterations) {
|
|
52
|
+
jsonData.e2ee_iterations = e2ee.iterations;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return postJson("/api/document/import/create/", jsonData, files)
|
|
56
|
+
.then(({ json }) => ({
|
|
57
|
+
id: json.id,
|
|
58
|
+
path: json.path,
|
|
59
|
+
e2ee: json.e2ee,
|
|
60
|
+
template: json.template
|
|
61
|
+
}))
|
|
62
|
+
.catch(error => {
|
|
63
|
+
addAlert("error", gettext("Could not create document"));
|
|
64
|
+
throw error;
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
saveImages: async (images, docId, e2ee) => {
|
|
68
|
+
const isE2EE = e2ee?.enabled;
|
|
69
|
+
const endpoint = isE2EE
|
|
70
|
+
? "/api/document/e2ee_image/"
|
|
71
|
+
: "/api/document/import/image/";
|
|
72
|
+
const imageTranslationTable = {};
|
|
73
|
+
await Promise.all(Object.values(images.db).map(async (imageEntry) => {
|
|
74
|
+
await maybeDecryptImage(imageEntry, e2ee?.sourceKey);
|
|
75
|
+
const encryptedFile = e2ee?.enabled && e2ee.key
|
|
76
|
+
? await E2EEEncryptor.encryptImage(imageEntry.file, e2ee.key)
|
|
77
|
+
: imageEntry.file;
|
|
78
|
+
const jsonData = {
|
|
79
|
+
doc_id: docId,
|
|
80
|
+
title: imageEntry.title,
|
|
81
|
+
copyright: imageEntry.copyright,
|
|
82
|
+
checksum: imageEntry.checksum
|
|
83
|
+
};
|
|
84
|
+
const files = {
|
|
85
|
+
image: {
|
|
86
|
+
file: encryptedFile,
|
|
87
|
+
filename: imageEntry.image.split("/").pop()
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const { json } = await postJson(endpoint, jsonData, files);
|
|
91
|
+
imageTranslationTable[imageEntry.id] = json.id;
|
|
92
|
+
}));
|
|
93
|
+
return imageTranslationTable;
|
|
94
|
+
},
|
|
95
|
+
saveDocument: async (saveData, e2ee) => {
|
|
96
|
+
if (e2ee?.enabled && e2ee.key) {
|
|
97
|
+
saveData.content = await E2EEEncryptor.encryptObject(saveData.content, e2ee.key);
|
|
98
|
+
saveData.comments = await E2EEEncryptor.encryptObject(saveData.comments || {}, e2ee.key);
|
|
99
|
+
saveData.bibliography = await E2EEEncryptor.encryptObject(saveData.bibliography, e2ee.key);
|
|
100
|
+
saveData.title = await E2EEEncryptor.encrypt(saveData.title, e2ee.key);
|
|
101
|
+
}
|
|
102
|
+
return postJson("/api/document/import/", saveData)
|
|
103
|
+
.then(({ json }) => ({ added: json.added, updated: json.updated }))
|
|
104
|
+
.catch(error => {
|
|
105
|
+
addAlert("error", `${gettext("Could not save ")} ${shortFileTitle(saveData.title, "")}`);
|
|
106
|
+
throw error;
|
|
107
|
+
});
|
|
108
|
+
},
|
|
109
|
+
encryptImage: E2EEEncryptor.encryptImage.bind(E2EEEncryptor),
|
|
110
|
+
encryptObject: E2EEEncryptor.encryptObject.bind(E2EEEncryptor),
|
|
111
|
+
encrypt: E2EEEncryptor.encrypt.bind(E2EEEncryptor),
|
|
112
|
+
storeKeyInSession: E2EEKeyManager.storeKeyInSession.bind(E2EEKeyManager)
|
|
113
|
+
};
|
|
114
|
+
}
|
|
6
115
|
export class SaveCopy extends GenericSaveCopy {
|
|
7
116
|
constructor(doc, bibDB, imageDB, newUser, importId = null, e2eeOptions = null) {
|
|
8
117
|
const title = shortFileTitle(doc.title, doc.path || "");
|
|
@@ -16,7 +125,11 @@ export class SaveCopy extends GenericSaveCopy {
|
|
|
16
125
|
generateSalt: E2EEKeyManager.generateSalt.bind(E2EEKeyManager),
|
|
17
126
|
deriveKey: E2EEKeyManager.deriveKey.bind(E2EEKeyManager)
|
|
18
127
|
};
|
|
19
|
-
const importDocument = (doc, bibDB, imageDB, httpIncludes, options) => new NativeImporter(doc, bibDB, imageDB, httpIncludes, options.user, options.
|
|
128
|
+
const importDocument = (doc, bibDB, imageDB, httpIncludes, options) => new NativeImporter(doc, bibDB, imageDB, httpIncludes, options.user, createNativeImporterBackend(options.user, options.e2eeOptions), {
|
|
129
|
+
importId: options.importId,
|
|
130
|
+
requestedPath: options.requestedPath,
|
|
131
|
+
e2eeOptions: options.e2eeOptions
|
|
132
|
+
}).init();
|
|
20
133
|
super(doc, bibDB, imageDB, newUser, {
|
|
21
134
|
importId,
|
|
22
135
|
e2eeOptions,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"copy.js","sourceRoot":"","sources":["../../../src/exporter/native/copy.js"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,IAAI,eAAe,EAAC,MAAM,uCAAuC,CAAA;AACjF,OAAO,EAAC,WAAW,EAAE,OAAO,EAAE,cAAc,EAAC,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"copy.js","sourceRoot":"","sources":["../../../src/exporter/native/copy.js"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,144 @@
|
|
|
1
1
|
import {SaveCopy as GenericSaveCopy} from "@fiduswriter/document/exporter/native"
|
|
2
|
-
import {addProgress, gettext, shortFileTitle} from "fwtoolkit"
|
|
2
|
+
import {addAlert, addProgress, gettext, postJson, shortFileTitle} from "fwtoolkit"
|
|
3
3
|
import {E2EEEncryptor} from "../../e2ee/encryptor.js"
|
|
4
4
|
import {E2EEKeyManager} from "../../e2ee/key-manager.js"
|
|
5
5
|
import {NativeImporter} from "@fiduswriter/document/importer/native"
|
|
6
6
|
|
|
7
|
+
async function maybeDecryptImage(imageEntry, sourceKey) {
|
|
8
|
+
if (!sourceKey || !imageEntry.file) {
|
|
9
|
+
return
|
|
10
|
+
}
|
|
11
|
+
if (imageEntry.file_type !== "application/octet-stream") {
|
|
12
|
+
return
|
|
13
|
+
}
|
|
14
|
+
const fileBuffer = await imageEntry.file.arrayBuffer()
|
|
15
|
+
const bytes = new Uint8Array(fileBuffer)
|
|
16
|
+
let binary = ""
|
|
17
|
+
const chunkSize = 65536
|
|
18
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
19
|
+
const chunk = bytes.subarray(i, i + chunkSize)
|
|
20
|
+
binary += String.fromCharCode.apply(null, chunk)
|
|
21
|
+
}
|
|
22
|
+
const base64 = btoa(binary)
|
|
23
|
+
const decrypted = await E2EEEncryptor.decryptBufferToBase64(base64, sourceKey)
|
|
24
|
+
const mime = imageEntry.original_file_type || "image/png"
|
|
25
|
+
const byteCharacters = atob(decrypted)
|
|
26
|
+
const byteNumbers = new Array(byteCharacters.length)
|
|
27
|
+
for (let i = 0; i < byteCharacters.length; i++) {
|
|
28
|
+
byteNumbers[i] = byteCharacters.charCodeAt(i)
|
|
29
|
+
}
|
|
30
|
+
const byteArray = new Uint8Array(byteNumbers)
|
|
31
|
+
imageEntry.file = new Blob([byteArray], {type: mime})
|
|
32
|
+
imageEntry.file_type = mime
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function createNativeImporterBackend(user, e2eeOptions) {
|
|
36
|
+
return {
|
|
37
|
+
createDoc: (template, importId, path, e2ee, files) => {
|
|
38
|
+
const jsonData = {
|
|
39
|
+
template: template.content,
|
|
40
|
+
export_templates: template.exportTemplates,
|
|
41
|
+
document_styles: template.documentStyles,
|
|
42
|
+
import_id: importId
|
|
43
|
+
? importId
|
|
44
|
+
: template.content.attrs.import_id,
|
|
45
|
+
template_title: template.content.attrs.template,
|
|
46
|
+
path
|
|
47
|
+
}
|
|
48
|
+
if (e2ee?.enabled) {
|
|
49
|
+
jsonData.e2ee = true
|
|
50
|
+
if (e2ee.salt) {
|
|
51
|
+
jsonData.e2ee_salt = e2ee.salt
|
|
52
|
+
}
|
|
53
|
+
if (e2ee.iterations) {
|
|
54
|
+
jsonData.e2ee_iterations = e2ee.iterations
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return postJson("/api/document/import/create/", jsonData, files)
|
|
58
|
+
.then(({json}) => ({
|
|
59
|
+
id: json.id,
|
|
60
|
+
path: json.path,
|
|
61
|
+
e2ee: json.e2ee,
|
|
62
|
+
template: json.template
|
|
63
|
+
}))
|
|
64
|
+
.catch(error => {
|
|
65
|
+
addAlert("error", gettext("Could not create document"))
|
|
66
|
+
throw error
|
|
67
|
+
})
|
|
68
|
+
},
|
|
69
|
+
saveImages: async (images, docId, e2ee) => {
|
|
70
|
+
const isE2EE = e2ee?.enabled
|
|
71
|
+
const endpoint = isE2EE
|
|
72
|
+
? "/api/document/e2ee_image/"
|
|
73
|
+
: "/api/document/import/image/"
|
|
74
|
+
const imageTranslationTable = {}
|
|
75
|
+
await Promise.all(
|
|
76
|
+
Object.values(images.db).map(async imageEntry => {
|
|
77
|
+
await maybeDecryptImage(imageEntry, e2ee?.sourceKey)
|
|
78
|
+
const encryptedFile =
|
|
79
|
+
e2ee?.enabled && e2ee.key
|
|
80
|
+
? await E2EEEncryptor.encryptImage(
|
|
81
|
+
imageEntry.file,
|
|
82
|
+
e2ee.key
|
|
83
|
+
)
|
|
84
|
+
: imageEntry.file
|
|
85
|
+
const jsonData = {
|
|
86
|
+
doc_id: docId,
|
|
87
|
+
title: imageEntry.title,
|
|
88
|
+
copyright: imageEntry.copyright,
|
|
89
|
+
checksum: imageEntry.checksum
|
|
90
|
+
}
|
|
91
|
+
const files = {
|
|
92
|
+
image: {
|
|
93
|
+
file: encryptedFile,
|
|
94
|
+
filename: imageEntry.image.split("/").pop()
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const {json} = await postJson(endpoint, jsonData, files)
|
|
98
|
+
imageTranslationTable[imageEntry.id] = json.id
|
|
99
|
+
})
|
|
100
|
+
)
|
|
101
|
+
return imageTranslationTable
|
|
102
|
+
},
|
|
103
|
+
saveDocument: async (saveData, e2ee) => {
|
|
104
|
+
if (e2ee?.enabled && e2ee.key) {
|
|
105
|
+
saveData.content = await E2EEEncryptor.encryptObject(
|
|
106
|
+
saveData.content,
|
|
107
|
+
e2ee.key
|
|
108
|
+
)
|
|
109
|
+
saveData.comments = await E2EEEncryptor.encryptObject(
|
|
110
|
+
saveData.comments || {},
|
|
111
|
+
e2ee.key
|
|
112
|
+
)
|
|
113
|
+
saveData.bibliography = await E2EEEncryptor.encryptObject(
|
|
114
|
+
saveData.bibliography,
|
|
115
|
+
e2ee.key
|
|
116
|
+
)
|
|
117
|
+
saveData.title = await E2EEEncryptor.encrypt(
|
|
118
|
+
saveData.title,
|
|
119
|
+
e2ee.key
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
return postJson("/api/document/import/", saveData)
|
|
123
|
+
.then(({json}) => ({added: json.added, updated: json.updated}))
|
|
124
|
+
.catch(error => {
|
|
125
|
+
addAlert(
|
|
126
|
+
"error",
|
|
127
|
+
`${gettext("Could not save ")} ${shortFileTitle(
|
|
128
|
+
saveData.title,
|
|
129
|
+
""
|
|
130
|
+
)}`
|
|
131
|
+
)
|
|
132
|
+
throw error
|
|
133
|
+
})
|
|
134
|
+
},
|
|
135
|
+
encryptImage: E2EEEncryptor.encryptImage.bind(E2EEEncryptor),
|
|
136
|
+
encryptObject: E2EEEncryptor.encryptObject.bind(E2EEEncryptor),
|
|
137
|
+
encrypt: E2EEEncryptor.encrypt.bind(E2EEEncryptor),
|
|
138
|
+
storeKeyInSession: E2EEKeyManager.storeKeyInSession.bind(E2EEKeyManager)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
7
142
|
export class SaveCopy extends GenericSaveCopy {
|
|
8
143
|
constructor(
|
|
9
144
|
doc,
|
|
@@ -37,10 +172,12 @@ export class SaveCopy extends GenericSaveCopy {
|
|
|
37
172
|
imageDB,
|
|
38
173
|
httpIncludes,
|
|
39
174
|
options.user,
|
|
40
|
-
options.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
175
|
+
createNativeImporterBackend(options.user, options.e2eeOptions),
|
|
176
|
+
{
|
|
177
|
+
importId: options.importId,
|
|
178
|
+
requestedPath: options.requestedPath,
|
|
179
|
+
e2eeOptions: options.e2eeOptions
|
|
180
|
+
}
|
|
44
181
|
).init()
|
|
45
182
|
|
|
46
183
|
super(doc, bibDB, imageDB, newUser, {
|