mirror of
https://github.com/zadam/trilium.git
synced 2026-01-12 09:34:26 +01:00
chore(core): fix references to Buffer
This commit is contained in:
parent
8149460547
commit
d717a89163
@ -68,7 +68,7 @@ export interface EtapiTokenRow {
|
||||
|
||||
export interface BlobRow {
|
||||
blobId: string;
|
||||
content: string | Buffer;
|
||||
content: string | Uint8Array;
|
||||
contentLength: number;
|
||||
dateModified: string;
|
||||
utcDateModified: string;
|
||||
@ -137,6 +137,6 @@ export interface NoteRow {
|
||||
dateModified?: string;
|
||||
utcDateCreated?: string;
|
||||
utcDateModified?: string;
|
||||
content?: string | Buffer;
|
||||
content?: string | Uint8Array;
|
||||
}
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ export interface RevisionPojo {
|
||||
utcDateLastEdited?: string;
|
||||
utcDateCreated?: string;
|
||||
utcDateModified?: string;
|
||||
content?: string | Buffer<ArrayBufferLike>;
|
||||
content?: string | Uint8Array;
|
||||
contentLength?: number;
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ export interface EntityChange {
|
||||
|
||||
export interface EntityRow {
|
||||
isDeleted?: boolean;
|
||||
content?: Buffer | string;
|
||||
content?: Uint8Array | string;
|
||||
}
|
||||
|
||||
export interface EntityChangeRecord {
|
||||
|
||||
@ -10,6 +10,7 @@ import utils from "../../services/utils.js";
|
||||
import becca from "../becca.js";
|
||||
import type { ConstructorData,default as Becca } from "../becca-interface.js";
|
||||
import { getSql } from "src/services/sql";
|
||||
import { concat2, encodeUtf8, unwrapStringOrBuffer, wrapStringOrBuffer } from "src/services/utils/binary";
|
||||
|
||||
interface ContentOpts {
|
||||
forceSave?: boolean;
|
||||
@ -137,7 +138,7 @@ abstract class AbstractBeccaEntity<T extends AbstractBeccaEntity<T>> {
|
||||
return this;
|
||||
}
|
||||
|
||||
protected _setContent(content: string | Buffer, opts: ContentOpts = {}) {
|
||||
protected _setContent(content: string | Uint8Array, opts: ContentOpts = {}) {
|
||||
// client code asks to save entity even if blobId didn't change (something else was changed)
|
||||
opts.forceSave = !!opts.forceSave;
|
||||
opts.forceFrontendReload = !!opts.forceFrontendReload;
|
||||
@ -148,9 +149,9 @@ abstract class AbstractBeccaEntity<T extends AbstractBeccaEntity<T>> {
|
||||
}
|
||||
|
||||
if (this.hasStringContent()) {
|
||||
content = content.toString();
|
||||
content = unwrapStringOrBuffer(content);
|
||||
} else {
|
||||
content = Buffer.isBuffer(content) ? content : Buffer.from(content);
|
||||
content = wrapStringOrBuffer(content);
|
||||
}
|
||||
|
||||
const unencryptedContentForHashCalculation = this.getUnencryptedContentForHashCalculation(content);
|
||||
@ -202,17 +203,21 @@ abstract class AbstractBeccaEntity<T extends AbstractBeccaEntity<T>> {
|
||||
sql.execute("DELETE FROM entity_changes WHERE entityName = 'blobs' AND entityId = ?", [oldBlobId]);
|
||||
}
|
||||
|
||||
private getUnencryptedContentForHashCalculation(unencryptedContent: Buffer | string) {
|
||||
private getUnencryptedContentForHashCalculation(unencryptedContent: Uint8Array | string) {
|
||||
if (this.isProtected) {
|
||||
// a "random" prefix makes sure that the calculated hash/blobId is different for a decrypted/encrypted content
|
||||
const encryptedPrefixSuffix = "t$[nvQg7q)&_ENCRYPTED_?M:Bf&j3jr_";
|
||||
return Buffer.isBuffer(unencryptedContent) ? Buffer.concat([Buffer.from(encryptedPrefixSuffix), unencryptedContent]) : `${encryptedPrefixSuffix}${unencryptedContent}`;
|
||||
if (typeof unencryptedContent === "string") {
|
||||
return `${encryptedPrefixSuffix}${unencryptedContent}`;
|
||||
} else {
|
||||
return concat2(encodeUtf8(encryptedPrefixSuffix), unencryptedContent)
|
||||
}
|
||||
}
|
||||
return unencryptedContent;
|
||||
|
||||
}
|
||||
|
||||
private saveBlob(content: string | Buffer, unencryptedContentForHashCalculation: string | Buffer, opts: ContentOpts = {}) {
|
||||
private saveBlob(content: string | Uint8Array, unencryptedContentForHashCalculation: string | Uint8Array, opts: ContentOpts = {}) {
|
||||
/*
|
||||
* We're using the unencrypted blob for the hash calculation, because otherwise the random IV would
|
||||
* cause every content blob to be unique which would balloon the database size (esp. with revisioning).
|
||||
@ -260,16 +265,16 @@ abstract class AbstractBeccaEntity<T extends AbstractBeccaEntity<T>> {
|
||||
return newBlobId;
|
||||
}
|
||||
|
||||
protected _getContent(): string | Buffer {
|
||||
protected _getContent(): string | Uint8Array {
|
||||
const sql = getSql();
|
||||
const row = sql.getRow<{ content: string | Buffer }>(/*sql*/`SELECT content FROM blobs WHERE blobId = ?`, [this.blobId]);
|
||||
const row = sql.getRow<{ content: string | Uint8Array }>(/*sql*/`SELECT content FROM blobs WHERE blobId = ?`, [this.blobId]);
|
||||
|
||||
if (!row) {
|
||||
const constructorData = this.constructor as unknown as ConstructorData<T>;
|
||||
throw new Error(`Cannot find content for ${constructorData.primaryKeyName} '${(this as any)[constructorData.primaryKeyName]}', blobId '${this.blobId}'`);
|
||||
}
|
||||
|
||||
return blobService.processContent(row.content, this.isProtected || false, this.hasStringContent()) as string | Buffer;
|
||||
return blobService.processContent(row.content, this.isProtected || false, this.hasStringContent()) as string | Uint8Array;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -136,11 +136,11 @@ class BAttachment extends AbstractBeccaEntity<BAttachment> {
|
||||
}
|
||||
}
|
||||
|
||||
getContent(): Buffer {
|
||||
return this._getContent() as Buffer;
|
||||
getContent(): Uint8Array {
|
||||
return this._getContent() as Uint8Array;
|
||||
}
|
||||
|
||||
setContent(content: string | Buffer, opts?: ContentOpts) {
|
||||
setContent(content: string | Uint8Array, opts?: ContentOpts) {
|
||||
this._setContent(content, opts);
|
||||
}
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ class BBlob extends AbstractBeccaEntity<BBlob> {
|
||||
return ["blobId", "content"];
|
||||
}
|
||||
|
||||
content!: string | Buffer;
|
||||
content!: string | Uint8Array;
|
||||
contentLength!: number;
|
||||
|
||||
constructor(row: BlobRow) {
|
||||
|
||||
@ -251,7 +251,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
}
|
||||
}
|
||||
|
||||
setContent(content: Buffer | string, opts: ContentOpts = {}) {
|
||||
setContent(content: Uint8Array | string, opts: ContentOpts = {}) {
|
||||
this._setContent(content, opts);
|
||||
|
||||
eventService.emit(eventService.NOTE_CONTENT_CHANGE, { entity: this });
|
||||
|
||||
@ -42,7 +42,7 @@ class BRevision extends AbstractBeccaEntity<BRevision> {
|
||||
dateLastEdited?: string;
|
||||
utcDateLastEdited?: string;
|
||||
contentLength?: number;
|
||||
content?: string | Buffer;
|
||||
content?: string | Uint8Array;
|
||||
|
||||
constructor(row: RevisionRow, titleDecrypted = false) {
|
||||
super();
|
||||
@ -95,7 +95,7 @@ class BRevision extends AbstractBeccaEntity<BRevision> {
|
||||
*
|
||||
* This is the same approach as is used for Note's content.
|
||||
*/
|
||||
getContent(): string | Buffer {
|
||||
getContent(): string | Uint8Array {
|
||||
return this._getContent();
|
||||
}
|
||||
|
||||
@ -120,7 +120,7 @@ class BRevision extends AbstractBeccaEntity<BRevision> {
|
||||
}
|
||||
}
|
||||
|
||||
setContent(content: string | Buffer, opts: ContentOpts = {}) {
|
||||
setContent(content: string | Uint8Array, opts: ContentOpts = {}) {
|
||||
this._setContent(content, opts);
|
||||
}
|
||||
|
||||
|
||||
@ -23,13 +23,13 @@ function getBlobPojo(entityName: string, entityId: string, opts?: { preview: boo
|
||||
if (!entity.hasStringContent()) {
|
||||
pojo.content = null;
|
||||
} else {
|
||||
pojo.content = processContent(pojo.content, !!entity.isProtected, true) as string | Buffer;
|
||||
pojo.content = processContent(pojo.content, !!entity.isProtected, true) as string | Uint8Array;
|
||||
}
|
||||
|
||||
return pojo;
|
||||
}
|
||||
|
||||
function processContent(content: Buffer | Uint8Array | string | null, isProtected: boolean, isStringContent: boolean) {
|
||||
function processContent(content: Uint8Array | string | null, isProtected: boolean, isStringContent: boolean) {
|
||||
if (isProtected) {
|
||||
if (protectedSessionService.isProtectedSessionAvailable()) {
|
||||
content = content === null ? null : protectedSessionService.decrypt(content as Uint8Array);
|
||||
@ -47,7 +47,7 @@ function processContent(content: Buffer | Uint8Array | string | null, isProtecte
|
||||
// IIRC a zero-sized buffer can be returned as null from the database
|
||||
if (content === null) {
|
||||
// this will force de/encryption
|
||||
content = Buffer.alloc(0);
|
||||
content = new Uint8Array(0);
|
||||
}
|
||||
|
||||
return content;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { getLog } from "../log.js";
|
||||
import { concat2, decodeBase64, decodeUtf8, encodeBase64 } from "../utils/binary.js";
|
||||
import { concat2, decodeBase64, decodeUtf8, encodeBase64, encodeUtf8 } from "../utils/binary.js";
|
||||
import { getCrypto } from "./crypto.js";
|
||||
|
||||
function arraysIdentical(a: any[] | Uint8Array, b: any[] | Uint8Array) {
|
||||
@ -55,7 +55,7 @@ function decrypt(key: Uint8Array, cipherText: string | Uint8Array): Uint8Array |
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
return Uint8Array.from("[protected]");
|
||||
return encodeUtf8("[protected]");
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@ -21,7 +21,7 @@ export interface RunResult {
|
||||
export interface DatabaseProvider {
|
||||
loadFromFile(path: string, isReadOnly: boolean): void;
|
||||
loadFromMemory(): void;
|
||||
loadFromBuffer(buffer: NonSharedBuffer): void;
|
||||
loadFromBuffer(buffer: Uint8Array): void;
|
||||
backup(destinationFile: string): void;
|
||||
prepare(query: string): Statement;
|
||||
transaction<T>(func: (statement: Statement) => T): Transaction;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
const utf8Decoder = new TextDecoder("utf-8");
|
||||
const utf8Encoder = new TextEncoder();
|
||||
|
||||
export function concat2(a: Uint8Array, b: Uint8Array): Uint8Array {
|
||||
const out = new Uint8Array(a.length + b.length);
|
||||
@ -33,3 +34,23 @@ export function decodeBase64(base64: string): Uint8Array {
|
||||
export function decodeUtf8(bytes: Uint8Array) {
|
||||
return utf8Decoder.decode(bytes);
|
||||
}
|
||||
|
||||
export function encodeUtf8(string: string) {
|
||||
return utf8Encoder.encode(string);
|
||||
}
|
||||
|
||||
export function unwrapStringOrBuffer(stringOrBuffer: string | Uint8Array) {
|
||||
if (typeof stringOrBuffer === "string") {
|
||||
return stringOrBuffer;
|
||||
} else {
|
||||
return decodeUtf8(stringOrBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
export function wrapStringOrBuffer(stringOrBuffer: string | Uint8Array) {
|
||||
if (typeof stringOrBuffer === "string") {
|
||||
return encodeUtf8(stringOrBuffer);
|
||||
} else {
|
||||
return stringOrBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user