2020-10-30 20:34:04 +00:00
|
|
|
// Copyright 2020 Signal Messenger, LLC
|
|
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
|
2020-09-24 21:53:21 +00:00
|
|
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
|
|
/* eslint-disable max-classes-per-file */
|
|
|
|
|
2020-04-13 17:37:29 +00:00
|
|
|
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;
|
2020-09-24 21:53:21 +00:00
|
|
|
|
2020-04-13 17:37:29 +00:00
|
|
|
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;
|
|
|
|
}
|
2018-07-21 21:51:20 +00:00
|
|
|
|
2020-09-24 21:53:21 +00:00
|
|
|
next(): ProtobufType | undefined | null {
|
2018-05-02 01:54:43 +00:00
|
|
|
try {
|
|
|
|
if (this.buffer.limit === this.buffer.offset) {
|
|
|
|
return undefined; // eof
|
|
|
|
}
|
2018-07-21 21:51:20 +00:00
|
|
|
const len = this.buffer.readVarint32();
|
|
|
|
const nextBuffer = this.buffer
|
2018-05-02 01:54:43 +00:00
|
|
|
.slice(this.buffer.offset, this.buffer.offset + len)
|
|
|
|
.toArrayBuffer();
|
2015-06-22 21:45:42 +00:00
|
|
|
|
2018-07-21 21:51:20 +00:00
|
|
|
const proto = this.protobuf.decode(nextBuffer);
|
2018-05-02 01:54:43 +00:00
|
|
|
this.buffer.skip(len);
|
2015-06-22 21:45:42 +00:00
|
|
|
|
2018-05-02 01:54:43 +00:00
|
|
|
if (proto.avatar) {
|
2018-07-21 21:51:20 +00:00
|
|
|
const attachmentLen = proto.avatar.length;
|
2018-05-02 01:54:43 +00:00
|
|
|
proto.avatar.data = this.buffer
|
|
|
|
.slice(this.buffer.offset, this.buffer.offset + attachmentLen)
|
|
|
|
.toArrayBuffer();
|
|
|
|
this.buffer.skip(attachmentLen);
|
|
|
|
}
|
2015-06-01 21:08:21 +00:00
|
|
|
|
2018-05-02 01:54:43 +00:00
|
|
|
if (proto.profileKey) {
|
|
|
|
proto.profileKey = proto.profileKey.toArrayBuffer();
|
|
|
|
}
|
2017-09-11 16:50:35 +00:00
|
|
|
|
2020-03-05 21:14:58 +00:00
|
|
|
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)'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-05-02 01:54:43 +00:00
|
|
|
return proto;
|
2018-07-21 19:00:08 +00:00
|
|
|
} catch (error) {
|
|
|
|
window.log.error(
|
|
|
|
'ProtoParser.next error:',
|
|
|
|
error && error.stack ? error.stack : error
|
|
|
|
);
|
2015-06-01 21:08:21 +00:00
|
|
|
}
|
2018-07-21 21:51:20 +00:00
|
|
|
|
|
|
|
return null;
|
2020-04-13 17:37:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|