core-3nweb-client-lib 0.49.5 → 0.49.7
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.
- package/build/api-defs/files.d.ts +11 -5
- package/build/core/asmail/delivery/common.d.ts +8 -28
- package/build/core/asmail/delivery/common.js +1 -47
- package/build/core/asmail/delivery/index.js +3 -8
- package/build/core/asmail/delivery/msg.js +1 -7
- package/build/core/asmail/delivery/per-recipient-wip.js +3 -29
- package/build/core/asmail/inbox/index.d.ts +1 -2
- package/build/core/asmail/inbox/index.js +14 -15
- package/build/core/asmail/inbox/msg-indexing/dataset/v0/sql-db-v-none.d.ts +11 -0
- package/build/core/asmail/inbox/msg-indexing/dataset/v0/sql-db-v-none.js +25 -0
- package/build/core/asmail/inbox/msg-indexing/dataset/v1/logs.d.ts +33 -0
- package/build/core/asmail/inbox/msg-indexing/dataset/v1/logs.js +72 -0
- package/build/core/asmail/inbox/msg-indexing/dataset/v1/sql-db.d.ts +28 -0
- package/build/core/asmail/inbox/msg-indexing/dataset/v1/sql-db.js +477 -0
- package/build/core/asmail/inbox/msg-indexing/index.d.ts +12 -26
- package/build/core/asmail/inbox/msg-indexing/index.js +47 -68
- package/build/core/asmail/inbox/msg-on-disk.js +1 -2
- package/build/core/asmail/index.js +8 -7
- package/build/core/asmail/msg/common.d.ts +0 -1
- package/build/core/asmail/msg/common.js +1 -1
- package/build/core/asmail/msg/packer.js +1 -3
- package/build/core/index.js +7 -4
- package/build/core/keyring/common.d.ts +1 -0
- package/build/core/keyring/common.js +2 -1
- package/build/core/keyring/index.d.ts +7 -44
- package/build/core/keyring/index.js +89 -222
- package/build/core/keyring/introductory-keys/published-intro-key.d.ts +17 -0
- package/build/core/keyring/introductory-keys/published-intro-key.js +190 -0
- package/build/core/keyring/peer-keys/dataset/v1/json-files.d.ts +105 -0
- package/build/core/keyring/peer-keys/dataset/v1/json-files.js +89 -0
- package/build/core/keyring/peer-keys/dataset/v2/logs.d.ts +43 -0
- package/build/core/keyring/peer-keys/dataset/v2/logs.js +116 -0
- package/build/core/keyring/peer-keys/dataset/v2/peer-keys-db.d.ts +73 -0
- package/build/core/keyring/peer-keys/dataset/v2/peer-keys-db.js +543 -0
- package/build/core/keyring/peer-keys/index.d.ts +24 -0
- package/build/core/keyring/peer-keys/index.js +208 -0
- package/build/core/storage/synced/obj-files.js +10 -3
- package/build/core/storage/synced/obj-status.d.ts +1 -1
- package/build/core/storage/synced/obj-status.js +8 -2
- package/build/core/storage/synced/storage.d.ts +4 -4
- package/build/core/storage/system-folders/apps-data.d.ts +0 -1
- package/build/core/storage/system-folders/apps-data.js +2 -6
- package/build/lib-client/fs-utils/fs-sync-utils.d.ts +1 -1
- package/build/lib-client/fs-utils/fs-sync-utils.js +70 -13
- package/build/lib-client/xsp-fs/fs.js +3 -1
- package/build/lib-client/xsp-fs/node-in-fs.d.ts +1 -0
- package/build/lib-client/xsp-fs/node-in-fs.js +7 -2
- package/build/lib-client/xsp-fs/node-persistence.js +1 -3
- package/build/lib-client/xsp-fs/xsp-payload-v2.js +1 -2
- package/build/lib-common/dataset-sync/per-device-json-array-logs.d.ts +58 -0
- package/build/lib-common/dataset-sync/per-device-json-array-logs.js +432 -0
- package/build/lib-common/number-line.d.ts +10 -0
- package/build/lib-common/number-line.js +66 -0
- package/build/lib-common/objs-on-disk/obj-version-file.d.ts +1 -1
- package/build/lib-common/objs-on-disk/obj-version-file.js +3 -3
- package/build/lib-common/rng-def.d.ts +1 -0
- package/build/lib-common/rng-def.js +8 -0
- package/build/lib-sqlite-on-3nstorage/for-sqlite.d.ts +38 -0
- package/build/lib-sqlite-on-3nstorage/for-sqlite.js +162 -0
- package/build/lib-sqlite-on-3nstorage/index.d.ts +18 -5
- package/build/lib-sqlite-on-3nstorage/index.js +49 -26
- package/build/tests/caps-api/file-sink-checks/splice.js +72 -1
- package/build/tests/caps-api/fs-checks/sync-on-one-dev/upload.js +27 -1
- package/build/tests/caps-api/fs-checks/sync-with-two-devs/update-propagation.js +12 -3
- package/build/tests/computer.3nweb.core/inbox/msg-indexing.js +16 -12
- package/build/tests/computer.3nweb.core/keyrings.js +113 -28
- package/build/tests/jasmine.js +2 -2
- package/build/tests/units/number-line.js +9 -9
- package/package.json +2 -1
- package/build/core/asmail/inbox/msg-indexing/logs-n-entries.d.ts +0 -52
- package/build/core/asmail/inbox/msg-indexing/logs-n-entries.js +0 -333
- package/build/core/asmail/inbox/msg-indexing/sql-indexing.d.ts +0 -4
- package/build/core/asmail/inbox/msg-indexing/sql-indexing.js +0 -319
- package/build/core/keyring/correspondent-keys.d.ts +0 -149
- package/build/core/keyring/correspondent-keys.js +0 -403
- package/build/core/keyring/id-to-email-map.d.ts +0 -38
- package/build/core/keyring/id-to-email-map.js +0 -105
- package/build/core/keyring/keyring-storage.d.ts +0 -9
- package/build/core/keyring/keyring-storage.js +0 -54
- package/build/core/keyring/published-intro-key.d.ts +0 -45
- package/build/core/keyring/published-intro-key.js +0 -200
|
@@ -314,7 +314,7 @@ declare namespace web3n.files {
|
|
|
314
314
|
* sink with this error. When err is given, no errors will be thrown back
|
|
315
315
|
* to this call.
|
|
316
316
|
*/
|
|
317
|
-
done(err?: any
|
|
317
|
+
done(err?: any): Promise<void>;
|
|
318
318
|
|
|
319
319
|
}
|
|
320
320
|
|
|
@@ -1178,27 +1178,33 @@ declare namespace web3n.files {
|
|
|
1178
1178
|
type RemoteEvent = RemoteVersionArchivalEvent | RemoteArchVerRemovalEvent |
|
|
1179
1179
|
RemoteRemovalEvent | RemoteChangeEvent;
|
|
1180
1180
|
|
|
1181
|
+
/**
|
|
1182
|
+
* SyncStatus has fields that connect to item's parent, uploading, i.e. not just state of the item.
|
|
1183
|
+
* Hence, we pick only related fields.
|
|
1184
|
+
*/
|
|
1185
|
+
type ItemSyncStatus = Pick<SyncStatus, 'state' | 'remote' | 'synced' | 'local'>;
|
|
1186
|
+
|
|
1181
1187
|
interface RemoteVersionArchivalEvent extends FSEvent {
|
|
1182
1188
|
type: 'remote-version-archival';
|
|
1183
1189
|
archivedVersion: number;
|
|
1184
|
-
syncStatus:
|
|
1190
|
+
syncStatus: ItemSyncStatus;
|
|
1185
1191
|
}
|
|
1186
1192
|
|
|
1187
1193
|
interface RemoteArchVerRemovalEvent extends FSEvent {
|
|
1188
1194
|
type: 'remote-arch-ver-removal';
|
|
1189
1195
|
removedArchVer: number;
|
|
1190
|
-
syncStatus:
|
|
1196
|
+
syncStatus: ItemSyncStatus;
|
|
1191
1197
|
}
|
|
1192
1198
|
|
|
1193
1199
|
interface RemoteRemovalEvent extends FSEvent {
|
|
1194
1200
|
type: 'remote-removal';
|
|
1195
|
-
syncStatus:
|
|
1201
|
+
syncStatus: ItemSyncStatus;
|
|
1196
1202
|
}
|
|
1197
1203
|
|
|
1198
1204
|
interface RemoteChangeEvent extends FSEvent {
|
|
1199
1205
|
type: 'remote-change';
|
|
1200
1206
|
newRemoteVersion: number;
|
|
1201
|
-
syncStatus:
|
|
1207
|
+
syncStatus: ItemSyncStatus;
|
|
1202
1208
|
}
|
|
1203
1209
|
|
|
1204
1210
|
type UploadEvent = UploadStartEvent | UploadProgressEvent | UploadDisconnectedEvent | UploadDoneEvent;
|
|
@@ -40,22 +40,17 @@ export interface ResourcesForSending {
|
|
|
40
40
|
* @param address
|
|
41
41
|
*/
|
|
42
42
|
needIntroKeyFor(address: string): boolean;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
* (c) msgCount - message count for a current pair.
|
|
51
|
-
* @param address
|
|
52
|
-
* @param introPKeyFromServer is an optional recipient's key from a mail
|
|
53
|
-
* server.
|
|
54
|
-
*/
|
|
55
|
-
generateKeysToSend: (address: string, introPKeyFromServer?: JsonKey) => Promise<{
|
|
43
|
+
getEstablishedKeysToSendMsg: (address: string) => Promise<{
|
|
44
|
+
encryptor: Encryptor;
|
|
45
|
+
currentPair: ASMailKeyPair;
|
|
46
|
+
msgCount: number;
|
|
47
|
+
nextMsgCrypto?: SuggestedNextKeyPair;
|
|
48
|
+
}>;
|
|
49
|
+
generateIntroKeysToSendMsg: (address: string, introPKey: JsonKey) => Promise<{
|
|
56
50
|
encryptor: Encryptor;
|
|
57
51
|
currentPair: ASMailKeyPair;
|
|
58
52
|
msgCount: number;
|
|
53
|
+
nextMsgCrypto?: SuggestedNextKeyPair;
|
|
59
54
|
}>;
|
|
60
55
|
/**
|
|
61
56
|
* This function returns sending parameters that should be used now to
|
|
@@ -64,11 +59,6 @@ export interface ResourcesForSending {
|
|
|
64
59
|
* @param address
|
|
65
60
|
*/
|
|
66
61
|
paramsForSendingTo: (address: string) => SendingParams | undefined;
|
|
67
|
-
/**
|
|
68
|
-
* This function returns next key pair
|
|
69
|
-
* @param address
|
|
70
|
-
*/
|
|
71
|
-
nextCrypto: (address: string) => Promise<SuggestedNextKeyPair | undefined>;
|
|
72
62
|
/**
|
|
73
63
|
* This returns a new sending parameters that given address should use to
|
|
74
64
|
* send messages back. Undefined is returned, if current parameters don't
|
|
@@ -89,14 +79,4 @@ export interface SavedMsgToSend {
|
|
|
89
79
|
recipients: string[];
|
|
90
80
|
retryOpts: DeliveryOptions['retryRecipient'];
|
|
91
81
|
}
|
|
92
|
-
/**
|
|
93
|
-
* This is a utility function that adds a number into given number line
|
|
94
|
-
* segments. Each segment is represented by an array, in which 0-th element is
|
|
95
|
-
* the smallest number in the segment, while 1-st element is the largest.
|
|
96
|
-
* Segments don't overlap and are ordered as they would on a number line:
|
|
97
|
-
* segment with smaller numbers go first.
|
|
98
|
-
* @param segments
|
|
99
|
-
* @param n
|
|
100
|
-
*/
|
|
101
|
-
export declare function addToNumberLineSegments(segments: number[][], n: number): void;
|
|
102
82
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2016 - 2017, 2020 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2016 - 2017, 2020, 2026 3NSoft Inc.
|
|
4
4
|
|
|
5
5
|
This program is free software: you can redistribute it and/or modify it under
|
|
6
6
|
the terms of the GNU General Public License as published by the Free Software
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.SEG_SIZE_IN_K_QUATS = exports.Attachments = void 0;
|
|
20
20
|
exports.estimatePackedSizeOf = estimatePackedSizeOf;
|
|
21
|
-
exports.addToNumberLineSegments = addToNumberLineSegments;
|
|
22
21
|
const attachments_container_1 = require("../msg/attachments-container");
|
|
23
22
|
const buffer_utils_1 = require("../../../lib-common/buffer-utils");
|
|
24
23
|
const ATTACHMENTS_NAME = 'attachments';
|
|
@@ -139,49 +138,4 @@ function estimatePackedSizeOf(size) {
|
|
|
139
138
|
}
|
|
140
139
|
return 148 + numOfCompleteSegs * exports.SEG_SIZE_IN_K_QUATS * 256 + lastSegSize;
|
|
141
140
|
}
|
|
142
|
-
/**
|
|
143
|
-
* This is a utility function that adds a number into given number line
|
|
144
|
-
* segments. Each segment is represented by an array, in which 0-th element is
|
|
145
|
-
* the smallest number in the segment, while 1-st element is the largest.
|
|
146
|
-
* Segments don't overlap and are ordered as they would on a number line:
|
|
147
|
-
* segment with smaller numbers go first.
|
|
148
|
-
* @param segments
|
|
149
|
-
* @param n
|
|
150
|
-
*/
|
|
151
|
-
function addToNumberLineSegments(segments, n) {
|
|
152
|
-
for (let i = (segments.length - 1); i >= 0; i -= 1) {
|
|
153
|
-
const [low, high] = segments[i];
|
|
154
|
-
if (high < n) {
|
|
155
|
-
if ((high + 1) >= n) {
|
|
156
|
-
// segment should be grown on a high side.
|
|
157
|
-
// But now bigger segment won't merge with higher segment, cause if
|
|
158
|
-
// it does, it would've merge from lower side of a higher segment.
|
|
159
|
-
segments[i][1] = n;
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
// new segment should be added higher than this one
|
|
163
|
-
segments.splice(i + 1, 0, [n, n]);
|
|
164
|
-
}
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
if ((low <= n) && (n <= high)) {
|
|
168
|
-
// do nothing as number falls into current segment
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
if (low <= (n + 1)) {
|
|
172
|
-
// segment should be grown on a lower side
|
|
173
|
-
segments[i][0] = n;
|
|
174
|
-
if ((i - 1) >= 0) {
|
|
175
|
-
// bigger segment may overlap with a lower one
|
|
176
|
-
const lowerSeg = segments[i - 1];
|
|
177
|
-
if ((lowerSeg[1] + 1) >= n) {
|
|
178
|
-
lowerSeg[1] = high;
|
|
179
|
-
segments.splice(i, 1);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
segments.unshift([n, n]);
|
|
186
|
-
}
|
|
187
141
|
Object.freeze(exports);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
Copyright (C) 2016 - 2017, 2020 - 2023 3NSoft Inc.
|
|
3
|
+
Copyright (C) 2016 - 2017, 2020 - 2023, 2026 3NSoft Inc.
|
|
4
4
|
|
|
5
5
|
This program is free software: you can redistribute it and/or modify it under
|
|
6
6
|
the terms of the GNU General Public License as published by the Free Software
|
|
@@ -28,8 +28,8 @@ const utils_for_observables_1 = require("../../../lib-common/utils-for-observabl
|
|
|
28
28
|
const SMALL_MSG_SIZE = 1024 * 1024;
|
|
29
29
|
const MSGS_FOLDER = 'msgs';
|
|
30
30
|
function idToMsgFolder(id) {
|
|
31
|
-
if (id.
|
|
32
|
-
throw new Error(`Message id ${id} contains illegal character
|
|
31
|
+
if (id.includes('/') || id.includes('.')) {
|
|
32
|
+
throw new Error(`Message id ${id} contains illegal character(s).`);
|
|
33
33
|
}
|
|
34
34
|
return `${MSGS_FOLDER}/${id}`;
|
|
35
35
|
}
|
|
@@ -154,11 +154,6 @@ class Delivery {
|
|
|
154
154
|
}
|
|
155
155
|
const attachments = common_1.Attachments.fromMsg(msgToSend);
|
|
156
156
|
const localMeta = opts === null || opts === void 0 ? void 0 : opts.localMeta;
|
|
157
|
-
// DEBUG log
|
|
158
|
-
console.log(`\n adding message ${msgToSend.attachments ? `with attachments: ${JSON.stringify({
|
|
159
|
-
files: msgToSend.attachments.files ? Object.keys(msgToSend.attachments.files).length : 0,
|
|
160
|
-
folders: msgToSend.attachments.folders ? Object.keys(msgToSend.attachments.folders).length : 0
|
|
161
|
-
})}` : `without attachments in outgoing msg object.`}`);
|
|
162
157
|
// save msg, in case delivery should be restarted
|
|
163
158
|
const msgFS = await this.makeFSForNewMsg(id);
|
|
164
159
|
const msg = await msg_1.Msg.forNew(id, msgFS, msgToSend, sender, recipients, this.r, attachments, localMeta, opts === null || opts === void 0 ? void 0 : opts.retryRecipient);
|
|
@@ -127,11 +127,7 @@ class Msg {
|
|
|
127
127
|
await this.msgFS.writeJSONFile(MAIN_OBJ_FILE_NAME, main, { create: true, exclusive: true });
|
|
128
128
|
await this.msgFS.writeJSONFile(PROGRESS_INFO_FILE_NAME, this.progress, { create: true, exclusive: true });
|
|
129
129
|
if (this.attachments) {
|
|
130
|
-
|
|
131
|
-
await this.attachments.linkIn(this.msgFS)
|
|
132
|
-
.then(
|
|
133
|
-
// DEBUG log
|
|
134
|
-
() => console.log(` .... msg attachments linked while delivery`), err => console.error(`linking attachments error:`, err));
|
|
130
|
+
await this.attachments.linkIn(this.msgFS);
|
|
135
131
|
}
|
|
136
132
|
}
|
|
137
133
|
notifyOfChangesInProgress(saveProgress, saveWIPs) {
|
|
@@ -192,8 +188,6 @@ class Msg {
|
|
|
192
188
|
msg.setSection('Cc', this.msgToSend.carbonCopy);
|
|
193
189
|
msg.setSection('To', this.msgToSend.recipients);
|
|
194
190
|
if (this.attachments) {
|
|
195
|
-
// DEBUG log
|
|
196
|
-
console.log(`setting attachment on messages packer`);
|
|
197
191
|
await msg.setAttachments(this.attachments);
|
|
198
192
|
}
|
|
199
193
|
return msg;
|
|
@@ -80,7 +80,6 @@ class WIP {
|
|
|
80
80
|
* or if this wip is done, undefined is returned.
|
|
81
81
|
*/
|
|
82
82
|
startNext() {
|
|
83
|
-
var _a, _b;
|
|
84
83
|
let proc = this.proc.latestTaskAtThisMoment();
|
|
85
84
|
if (proc) {
|
|
86
85
|
return;
|
|
@@ -102,13 +101,9 @@ class WIP {
|
|
|
102
101
|
proc = this.proc.addStarted(this.sendObjs());
|
|
103
102
|
}
|
|
104
103
|
else if (stage === "cancel") {
|
|
105
|
-
// DEBUG log
|
|
106
|
-
console.log(` canceled sending msgId: ${(_a = this.state.session) === null || _a === void 0 ? void 0 : _a.msgId}`);
|
|
107
104
|
return;
|
|
108
105
|
}
|
|
109
106
|
else if (stage === undefined) {
|
|
110
|
-
// DEBUG log
|
|
111
|
-
console.log(` done sending msgId: ${(_b = this.state.session) === null || _b === void 0 ? void 0 : _b.msgId}`);
|
|
112
107
|
return;
|
|
113
108
|
}
|
|
114
109
|
else {
|
|
@@ -164,11 +159,11 @@ class WIP {
|
|
|
164
159
|
async getRecipientKeyAndEncrypt() {
|
|
165
160
|
const recipient = this.sender.recipient;
|
|
166
161
|
const introPKeyFromServer = await this.getIntroKeyIfRecipientIsUnknown(recipient);
|
|
167
|
-
// DEBUG log
|
|
168
|
-
console.log(`\n wip.getRecipientKeyAndEncrypt()`);
|
|
169
162
|
this.packer = await this.msg.msgPacker();
|
|
170
163
|
// get crypto parts for encrypting this message
|
|
171
|
-
const { currentPair, encryptor, msgCount } = await
|
|
164
|
+
const { currentPair, encryptor, msgCount, nextMsgCrypto } = await (introPKeyFromServer ?
|
|
165
|
+
this.msg.r.correspondents.generateIntroKeysToSendMsg(recipient, introPKeyFromServer) :
|
|
166
|
+
this.msg.r.correspondents.getEstablishedKeysToSendMsg(recipient));
|
|
172
167
|
// add crypto parameters to the message
|
|
173
168
|
if (currentPair.pid) {
|
|
174
169
|
this.packer.setEstablishedKeyPairInfo(currentPair.pid, msgCount);
|
|
@@ -183,7 +178,6 @@ class WIP {
|
|
|
183
178
|
this.packer.setNewKeyInfo(currentPair.recipientKid, currentPair.senderPKey.k, pkCerts, msgCount);
|
|
184
179
|
}
|
|
185
180
|
// add next crypto parameters to the message
|
|
186
|
-
const nextMsgCrypto = await this.msg.r.correspondents.nextCrypto(recipient);
|
|
187
181
|
if (nextMsgCrypto) {
|
|
188
182
|
this.packer.setNextCrypto(nextMsgCrypto);
|
|
189
183
|
}
|
|
@@ -262,8 +256,6 @@ class WIP {
|
|
|
262
256
|
throw new Error(`Message pack is not set.`);
|
|
263
257
|
}
|
|
264
258
|
this.state.session = await this.sender.sendMetadata(this.state.pack.meta);
|
|
265
|
-
// DEBUG log
|
|
266
|
-
console.log(`\n wip.sendMeta() returned with\n msgId: ${this.state.session.msgId}\n meta.objIds sent to server:`, this.state.pack.meta.objIds);
|
|
267
259
|
this.msg.progress.recipients[this.state.recipient].idOnDelivery = this.state.session.msgId;
|
|
268
260
|
if (this.state.stage !== "cancel") {
|
|
269
261
|
this.state.stage = "5-send-objs";
|
|
@@ -317,9 +309,6 @@ class WIP {
|
|
|
317
309
|
return { objId, upload, src };
|
|
318
310
|
}
|
|
319
311
|
async completeDelivery() {
|
|
320
|
-
var _a;
|
|
321
|
-
// DEBUG log
|
|
322
|
-
console.log(` wip.completeDelivery() msg ${!!((_a = this.state.session) === null || _a === void 0 ? void 0 : _a.msgId)}`);
|
|
323
312
|
await this.sender.completeDelivery();
|
|
324
313
|
this.updateInfo(0, true);
|
|
325
314
|
this.state.stage = undefined;
|
|
@@ -339,17 +328,12 @@ class WIP {
|
|
|
339
328
|
* completes sending, when no more sending is left.
|
|
340
329
|
*/
|
|
341
330
|
async sendObjs() {
|
|
342
|
-
var _a, _b, _c;
|
|
343
|
-
// DEBUG log
|
|
344
|
-
console.log(` wip.sendObjs(), msgId: ${(_a = this.state.session) === null || _a === void 0 ? void 0 : _a.msgId}, p 0, \n !!this.sender is ${!!this.sender}\n this.currentObj is ${(_b = this.currentObj) === null || _b === void 0 ? void 0 : _b.objId}`);
|
|
345
331
|
if (!this.sender) {
|
|
346
332
|
this.sender = await sender_1.MailSender.resume(this.msg.r.makeNet(), this.state.recipient, this.state.session);
|
|
347
333
|
}
|
|
348
334
|
// ensure there is an object to send, or complete delivery
|
|
349
335
|
if (!this.currentObj) {
|
|
350
336
|
this.currentObj = await this.getObjToSend();
|
|
351
|
-
// DEBUG log
|
|
352
|
-
console.log(` ... this.getObjToSend() sets currentObj to be ${(_c = this.currentObj) === null || _c === void 0 ? void 0 : _c.objId}`);
|
|
353
337
|
if (!this.currentObj) {
|
|
354
338
|
return this.completeDelivery();
|
|
355
339
|
}
|
|
@@ -377,8 +361,6 @@ class WIP {
|
|
|
377
361
|
* @param obj is a message object to send
|
|
378
362
|
*/
|
|
379
363
|
async firstObjSendingRequest(obj) {
|
|
380
|
-
// DEBUG log
|
|
381
|
-
console.log(` wip.firstObjSendingRequest() ${obj.objId}`);
|
|
382
364
|
// read from source
|
|
383
365
|
const header = await obj.src.readHeader();
|
|
384
366
|
const { size, isEndless } = await obj.src.segSrc.getSize();
|
|
@@ -410,8 +392,6 @@ class WIP {
|
|
|
410
392
|
obj.upload.header = buffer_utils_1.base64.pack(header);
|
|
411
393
|
}
|
|
412
394
|
this.updateInfo(header.length + segsChunk.length);
|
|
413
|
-
// DEBUG log
|
|
414
|
-
console.log(` ... ${obj.objId} 1st/single obj request send, isObjDone is ${isObjDone}`);
|
|
415
395
|
return isObjDone;
|
|
416
396
|
}
|
|
417
397
|
/**
|
|
@@ -421,16 +401,12 @@ class WIP {
|
|
|
421
401
|
* @param obj is a message object to send
|
|
422
402
|
*/
|
|
423
403
|
async followingObjSendingRequest(obj) {
|
|
424
|
-
// DEBUG log
|
|
425
|
-
console.log(` wip.followingObjSendingRequest() ${obj.objId}`);
|
|
426
404
|
// read from source
|
|
427
405
|
const segsSize = obj.upload.expectedSegsSize;
|
|
428
406
|
const chunk = await obj.src.segSrc.readNext(this.sender.maxChunkSize);
|
|
429
407
|
// return early, when there are no bytes
|
|
430
408
|
if (!chunk) {
|
|
431
409
|
await this.sender.sendObj(obj.objId, EMPTY_BYTE_ARR, undefined, { ofs: obj.upload.segsOffset, last: true });
|
|
432
|
-
// DEBUG log
|
|
433
|
-
console.log(` ... ${obj.objId} 2nd/following obj request has no more chunk to send, and completed sending obj`);
|
|
434
410
|
return true;
|
|
435
411
|
}
|
|
436
412
|
// check for an overrun
|
|
@@ -450,8 +426,6 @@ class WIP {
|
|
|
450
426
|
await this.sender.sendObj(obj.objId, chunk, undefined, opts);
|
|
451
427
|
obj.upload.segsOffset += chunk.length;
|
|
452
428
|
this.updateInfo(chunk.length);
|
|
453
|
-
// DEBUG log
|
|
454
|
-
console.log(` ... ${obj.objId} 2nd/following obj request sent ${chunk.length} bytes, isObjDone is ${isObjDone}`);
|
|
455
429
|
return isObjDone;
|
|
456
430
|
}
|
|
457
431
|
}
|
|
@@ -86,7 +86,7 @@ export declare class InboxOnServer {
|
|
|
86
86
|
private readonly procs;
|
|
87
87
|
private readonly recentlyOpenedMsgs;
|
|
88
88
|
private constructor();
|
|
89
|
-
static makeAndStart(cachePath: string, syncedFS: WritableFS, r: ResourcesForReceiving): Promise<InboxOnServer>;
|
|
89
|
+
static makeAndStart(cachePath: string, syncedFS: WritableFS, localFS: WritableFS, r: ResourcesForReceiving): Promise<InboxOnServer>;
|
|
90
90
|
close(): Promise<void>;
|
|
91
91
|
makeCAP(): InboxService;
|
|
92
92
|
private removeMsg;
|
|
@@ -95,7 +95,6 @@ export declare class InboxOnServer {
|
|
|
95
95
|
private startCachingAndAddKeyToIndex;
|
|
96
96
|
private markOwnParams;
|
|
97
97
|
private absorbSendingParams;
|
|
98
|
-
private checkServerAuthIfPresent;
|
|
99
98
|
private listMsgs;
|
|
100
99
|
private listNewMsgs;
|
|
101
100
|
private getMsg;
|
|
@@ -55,15 +55,15 @@ class InboxOnServer {
|
|
|
55
55
|
this.inboxEvents = new inbox_events_1.InboxEvents(this.msgReceiver, this.getMsg.bind(this), this.listNewMsgs.bind(this), this.removeMsg.bind(this), this.logError);
|
|
56
56
|
Object.seal(this);
|
|
57
57
|
}
|
|
58
|
-
static async makeAndStart(cachePath, syncedFS, r) {
|
|
58
|
+
static async makeAndStart(cachePath, syncedFS, localFS, r) {
|
|
59
59
|
try {
|
|
60
60
|
(0, file_1.ensureCorrectFS)(syncedFS, 'synced', true);
|
|
61
61
|
const msgReceiver = new recipient_1.MailRecipient(r.address, r.getSigner, () => r.asmailResolver(r.address), r.makeNet());
|
|
62
62
|
const downloader = new msg_downloader_1.MsgDownloader(msgReceiver);
|
|
63
63
|
const cache = await cached_msgs_1.CachedMessages.makeFor(cachePath, downloader, r.logError);
|
|
64
|
-
const indexSyncedFS = await (0, fs_sync_utils_1.
|
|
65
|
-
const
|
|
66
|
-
await (0,
|
|
64
|
+
const indexSyncedFS = await (0, fs_sync_utils_1.getOrMakeSyncedDirOnInit)(syncedFS, MSG_INDEX_FOLDER);
|
|
65
|
+
const indexLocalFS = await localFS.writableSubRoot(MSG_INDEX_FOLDER);
|
|
66
|
+
const index = await (0, msg_indexing_1.makeMsgIndex)(indexSyncedFS, indexLocalFS, r.logError);
|
|
67
67
|
const inbox = new InboxOnServer(r.correspondents, msgReceiver, r.getStorages, r.cryptor, r.random, downloader, cache, index, r.logError);
|
|
68
68
|
return inbox;
|
|
69
69
|
}
|
|
@@ -141,7 +141,7 @@ class InboxOnServer {
|
|
|
141
141
|
if (decrOut) {
|
|
142
142
|
const { decrInfo, openedMsg } = decrOut;
|
|
143
143
|
openedMsg.setMsgKeyRole(decrInfo.keyStatus);
|
|
144
|
-
|
|
144
|
+
checkServerAuthIfPresent(meta, decrInfo);
|
|
145
145
|
// add records cache and to index
|
|
146
146
|
this.recentlyOpenedMsgs.set(msgId, openedMsg);
|
|
147
147
|
const msgInfo = {
|
|
@@ -189,14 +189,6 @@ class InboxOnServer {
|
|
|
189
189
|
const address = openedMsg.sender;
|
|
190
190
|
await this.r.saveParamsForSendingTo(address, sendingParams);
|
|
191
191
|
}
|
|
192
|
-
checkServerAuthIfPresent(meta, decrInfo) {
|
|
193
|
-
// if sender authenticated to server, check that it matches address,
|
|
194
|
-
// recovered from message decryption
|
|
195
|
-
if (meta.authSender
|
|
196
|
-
&& !(0, canonical_address_1.areAddressesEqual)(meta.authSender, decrInfo.correspondent)) {
|
|
197
|
-
throw new Error(`Sender authenticated to server as ${meta.authSender}, while decrypting key is associated with ${decrInfo.correspondent}`);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
192
|
async listMsgs(fromTS) {
|
|
201
193
|
const checkServer = true; // XXX in future this will be an option from req
|
|
202
194
|
if (!checkServer) {
|
|
@@ -272,8 +264,8 @@ class InboxOnServer {
|
|
|
272
264
|
if (msg) {
|
|
273
265
|
return this.msgToUIForm(msg, msgOnDisk.deliveryTS, msgOnDisk);
|
|
274
266
|
}
|
|
275
|
-
if ((msgOnDisk.keyStatus === 'not-found')
|
|
276
|
-
(msgOnDisk.keyStatus === 'fail')) {
|
|
267
|
+
if ((msgOnDisk.keyStatus === 'not-found')
|
|
268
|
+
|| (msgOnDisk.keyStatus === 'fail')) {
|
|
277
269
|
// XXX
|
|
278
270
|
// message cannot be opened, and should be removed
|
|
279
271
|
// await Promise.all([
|
|
@@ -342,4 +334,11 @@ class InboxOnServer {
|
|
|
342
334
|
exports.InboxOnServer = InboxOnServer;
|
|
343
335
|
Object.freeze(InboxOnServer.prototype);
|
|
344
336
|
Object.freeze(InboxOnServer);
|
|
337
|
+
function checkServerAuthIfPresent(meta, { correspondent }) {
|
|
338
|
+
// if sender authenticated to server, check that it matches address,
|
|
339
|
+
// recovered from message decryption
|
|
340
|
+
if (meta.authSender && !(0, canonical_address_1.areAddressesEqual)(meta.authSender, correspondent)) {
|
|
341
|
+
throw new Error(`Sender authenticated to server as ${meta.authSender}, while decrypting key is associated with ${correspondent}`);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
345
344
|
Object.freeze(exports);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Database } from '../../../../../../lib-sqlite-on-3nstorage/sqljs';
|
|
2
|
+
export interface MsgIndexDbVNoneEntry {
|
|
3
|
+
msg_id: string;
|
|
4
|
+
msg_type: string;
|
|
5
|
+
delivery_ts: number;
|
|
6
|
+
key: Uint8Array;
|
|
7
|
+
key_status: string;
|
|
8
|
+
main_obj_header_ofs: number;
|
|
9
|
+
remove_after: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function getAllRecordsFromVersionNone(db: Database): MsgIndexDbVNoneEntry[];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (C) 2026 3NSoft Inc.
|
|
4
|
+
|
|
5
|
+
This program is free software: you can redistribute it and/or modify it under
|
|
6
|
+
the terms of the GNU General Public License as published by the Free Software
|
|
7
|
+
Foundation, either version 3 of the License, or (at your option) any later
|
|
8
|
+
version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful, but
|
|
11
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
13
|
+
See the GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU General Public License along with
|
|
16
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.getAllRecordsFromVersionNone = getAllRecordsFromVersionNone;
|
|
20
|
+
const lib_sqlite_on_3nstorage_1 = require("../../../../../../lib-sqlite-on-3nstorage");
|
|
21
|
+
function getAllRecordsFromVersionNone(db) {
|
|
22
|
+
const result = db.exec(`--sql
|
|
23
|
+
SELECT * FROM inbox_index`)[0];
|
|
24
|
+
return (result ? (0, lib_sqlite_on_3nstorage_1.objectFromQueryExecResult)(result) : []);
|
|
25
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { SingleProc } from '../../../../../../lib-common/processes/synced';
|
|
2
|
+
import { MsgKeyInfo, MsgKeyRole } from '../../../../../keyring';
|
|
3
|
+
import { LogError } from '../../../../../../lib-client/logging/log-to-file';
|
|
4
|
+
type WritableFS = web3n.files.WritableFS;
|
|
5
|
+
type MsgInfo = web3n.asmail.MsgInfo;
|
|
6
|
+
interface MsgOpenedLog {
|
|
7
|
+
eventType: 'msg-opened';
|
|
8
|
+
eventTS: number;
|
|
9
|
+
msgId: string;
|
|
10
|
+
msgType: string;
|
|
11
|
+
deliveryTS: number;
|
|
12
|
+
keyB64: string;
|
|
13
|
+
keyStatus: MsgKeyRole;
|
|
14
|
+
mainObjHeaderOfs: number;
|
|
15
|
+
}
|
|
16
|
+
interface MsgRemovedLog {
|
|
17
|
+
eventType: 'msg-removed';
|
|
18
|
+
eventTS: number;
|
|
19
|
+
msgId: string;
|
|
20
|
+
deliveryTS: number;
|
|
21
|
+
}
|
|
22
|
+
export type MsgOp = MsgOpenedLog | MsgRemovedLog;
|
|
23
|
+
export declare function msgOpenedEventToRecordParams(op: MsgOpenedLog): {
|
|
24
|
+
msgInfo: MsgInfo;
|
|
25
|
+
decrInfo: MsgKeyInfo;
|
|
26
|
+
};
|
|
27
|
+
export declare function makeRecentMsgIndexChangesLogs(logsFS: WritableFS, localLogsFS: WritableFS, logError: LogError): Promise<{
|
|
28
|
+
recordMsgAddition: (msgInfo: MsgInfo, decrInfo: MsgKeyInfo) => Promise<void>;
|
|
29
|
+
recordMsgRemoval: (msgId: string, deliveryTS: number) => Promise<void>;
|
|
30
|
+
watchAndApplyOpsFromOtherDevices: (changeProc: SingleProc, sink: (ops: import("../../../../../../lib-common/dataset-sync/per-device-json-array-logs").LogEntry<MsgOp>[]) => Promise<void>) => () => void;
|
|
31
|
+
cutLogOnDatasetSyncAndUpload: (syncPointV: number, params?: any) => Promise<void> | undefined;
|
|
32
|
+
}>;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
Copyright (C) 2016 - 2020, 2023, 2026 3NSoft Inc.
|
|
4
|
+
|
|
5
|
+
This program is free software: you can redistribute it and/or modify it under
|
|
6
|
+
the terms of the GNU General Public License as published by the Free Software
|
|
7
|
+
Foundation, either version 3 of the License, or (at your option) any later
|
|
8
|
+
version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful, but
|
|
11
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
13
|
+
See the GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU General Public License along with
|
|
16
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.msgOpenedEventToRecordParams = msgOpenedEventToRecordParams;
|
|
20
|
+
exports.makeRecentMsgIndexChangesLogs = makeRecentMsgIndexChangesLogs;
|
|
21
|
+
const buffer_utils_1 = require("../../../../../../lib-common/buffer-utils");
|
|
22
|
+
const per_device_json_array_logs_1 = require("../../../../../../lib-common/dataset-sync/per-device-json-array-logs");
|
|
23
|
+
function msgOpenedEventToRecordParams(op) {
|
|
24
|
+
const { msgType, msgId, deliveryTS, keyB64, keyStatus, mainObjHeaderOfs } = op;
|
|
25
|
+
return {
|
|
26
|
+
msgInfo: {
|
|
27
|
+
msgId, msgType, deliveryTS
|
|
28
|
+
},
|
|
29
|
+
decrInfo: {
|
|
30
|
+
correspondent: '',
|
|
31
|
+
keyStatus,
|
|
32
|
+
msgKeyPackLen: mainObjHeaderOfs,
|
|
33
|
+
key: buffer_utils_1.base64.open(keyB64)
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function areOpsEqual(a, b) {
|
|
38
|
+
return ((a.eventType === b.eventType) && (a.msgId === b.msgId) && (a.deliveryTS === b.deliveryTS));
|
|
39
|
+
}
|
|
40
|
+
async function makeRecentMsgIndexChangesLogs(logsFS, localLogsFS, logError) {
|
|
41
|
+
const { appendLogsAndUpload, cutLogOnDatasetSyncAndUpload, watchAndApplyOpsFromOtherDevices } = await (0, per_device_json_array_logs_1.makeRecentChangesLogs)(logsFS, localLogsFS, areOpsEqual, logError);
|
|
42
|
+
function recordMsgAddition(msgInfo, decrInfo) {
|
|
43
|
+
if (!decrInfo.key) {
|
|
44
|
+
throw new Error(`Given message decryption info doesn't have a key for message ${msgInfo.msgId}`);
|
|
45
|
+
}
|
|
46
|
+
return appendLogsAndUpload({
|
|
47
|
+
eventType: 'msg-opened',
|
|
48
|
+
eventTS: Date.now(),
|
|
49
|
+
msgType: msgInfo.msgType,
|
|
50
|
+
msgId: msgInfo.msgId,
|
|
51
|
+
deliveryTS: msgInfo.deliveryTS,
|
|
52
|
+
keyB64: buffer_utils_1.base64.pack(decrInfo.key),
|
|
53
|
+
keyStatus: decrInfo.keyStatus,
|
|
54
|
+
mainObjHeaderOfs: decrInfo.msgKeyPackLen,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function recordMsgRemoval(msgId, deliveryTS) {
|
|
58
|
+
return appendLogsAndUpload({
|
|
59
|
+
eventType: 'msg-removed',
|
|
60
|
+
eventTS: Date.now(),
|
|
61
|
+
msgId,
|
|
62
|
+
deliveryTS
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
recordMsgAddition,
|
|
67
|
+
recordMsgRemoval,
|
|
68
|
+
watchAndApplyOpsFromOtherDevices,
|
|
69
|
+
cutLogOnDatasetSyncAndUpload
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
Object.freeze(exports);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { MsgKeyInfo, MsgKeyRole } from '../../../../../keyring';
|
|
2
|
+
import { MsgOp } from './logs';
|
|
3
|
+
import { SingleProc } from '../../../../../../lib-common/processes/synced';
|
|
4
|
+
import { LogEntry } from '../../../../../../lib-common/dataset-sync/per-device-json-array-logs';
|
|
5
|
+
type WritableFS = web3n.files.WritableFS;
|
|
6
|
+
type WritableFile = web3n.files.WritableFile;
|
|
7
|
+
type MsgInfo = web3n.asmail.MsgInfo;
|
|
8
|
+
export interface MsgKey {
|
|
9
|
+
msgKey: Uint8Array;
|
|
10
|
+
msgKeyRole: MsgKeyRole;
|
|
11
|
+
mainObjHeaderOfs: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function makeSqliteDBs(dbsFS: WritableFS): Promise<{
|
|
14
|
+
absorbOpsFromOtherDevices: (changeProc: SingleProc, ops: LogEntry<MsgOp>[]) => Promise<void>;
|
|
15
|
+
addToLatest: (msgInfo: MsgInfo, decrInfo: MsgKeyInfo) => Promise<boolean>;
|
|
16
|
+
getDBFile: (fileTS: number) => Promise<WritableFile>;
|
|
17
|
+
getKeyFor: (msgId: string, deliveryTS: number) => Promise<MsgKey | undefined>;
|
|
18
|
+
isForLatestDb: (deliveryTS: number) => boolean;
|
|
19
|
+
latestDbHasNewRemoteVersion: () => Promise<boolean>;
|
|
20
|
+
listMsgs: (fromTS: number | undefined) => Promise<MsgInfo[]>;
|
|
21
|
+
msgExists: ({ msgId, deliveryTS }: MsgInfo) => Promise<boolean>;
|
|
22
|
+
makeNewShardWithRecordsUpToTS: (shardTS: number) => Promise<number>;
|
|
23
|
+
syncPastShards: () => Promise<void>;
|
|
24
|
+
numberOfRecordsInLatestBefore: (ts: number) => number;
|
|
25
|
+
remove: (msgId: string) => Promise<number | undefined>;
|
|
26
|
+
watchAndApplyOpsFromOtherDevices: (changeProc: SingleProc, resetSyncInterval: () => void) => () => void;
|
|
27
|
+
}>;
|
|
28
|
+
export {};
|