signal-desktop/ts/textsecure/ContactsParser.ts
2020-11-04 13:03:13 -06:00

101 lines
2.5 KiB
TypeScript

// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable max-classes-per-file */
import { ByteBufferClass } from '../window.d';
import { AttachmentType } from './SendMessage';
type ProtobufConstructorType = {
decode: (data: ArrayBuffer) => ProtobufType;
};
type ProtobufType = {
avatar?: PackedAttachmentType;
profileKey?: any;
uuid?: string;
members: Array<string>;
};
export type PackedAttachmentType = AttachmentType & {
length: number;
};
export class ProtoParser {
buffer: ByteBufferClass;
protobuf: ProtobufConstructorType;
constructor(arrayBuffer: ArrayBuffer, protobuf: ProtobufConstructorType) {
this.protobuf = protobuf;
this.buffer = new window.dcodeIO.ByteBuffer();
this.buffer.append(arrayBuffer);
this.buffer.offset = 0;
this.buffer.limit = arrayBuffer.byteLength;
}
next(): ProtobufType | undefined | null {
try {
if (this.buffer.limit === this.buffer.offset) {
return undefined; // eof
}
const len = this.buffer.readVarint32();
const nextBuffer = this.buffer
.slice(this.buffer.offset, this.buffer.offset + len)
.toArrayBuffer();
const proto = this.protobuf.decode(nextBuffer);
this.buffer.skip(len);
if (proto.avatar) {
const attachmentLen = proto.avatar.length;
proto.avatar.data = this.buffer
.slice(this.buffer.offset, this.buffer.offset + attachmentLen)
.toArrayBuffer();
this.buffer.skip(attachmentLen);
}
if (proto.profileKey) {
proto.profileKey = proto.profileKey.toArrayBuffer();
}
if (proto.uuid) {
window.normalizeUuids(
proto,
['uuid'],
'ProtoParser::next (proto.uuid)'
);
}
if (proto.members) {
window.normalizeUuids(
proto,
proto.members.map((_member, i) => `members.${i}.uuid`),
'ProtoParser::next (proto.members)'
);
}
return proto;
} catch (error) {
window.log.error(
'ProtoParser.next error:',
error && error.stack ? error.stack : error
);
}
return null;
}
}
export class GroupBuffer extends ProtoParser {
constructor(arrayBuffer: ArrayBuffer) {
super(arrayBuffer, window.textsecure.protobuf.GroupDetails as any);
}
}
export class ContactBuffer extends ProtoParser {
constructor(arrayBuffer: ArrayBuffer) {
super(arrayBuffer, window.textsecure.protobuf.ContactDetails as any);
}
}