diff --git a/src/Model/Global/connectionModel.ts b/src/Model/Global/connectionModel.ts index bb81c486..de8ebf9c 100644 --- a/src/Model/Global/connectionModel.ts +++ b/src/Model/Global/connectionModel.ts @@ -161,7 +161,7 @@ export default class ConnectionModel { tryToSendMessage = (chatMessage: ChatMessage): boolean => { const stringifiedBody: string = stringify(chatMessage); - const isSent: boolean = this.udn.sendMessage( + const isSent: boolean = this.sendPlainMessage( chatMessage.channel, stringifiedBody ); @@ -169,6 +169,10 @@ export default class ConnectionModel { return isSent; }; + sendPlainMessage = (channel: string, body: string): boolean => { + return this.udn.sendMessage(channel, body); + }; + // storage getPreviousAddressPath = (): string[] => { return StorageModel.getPath( diff --git a/src/Model/Global/fileTransferModel.ts b/src/Model/Global/fileTransferModel.ts index e9a795f0..afbbf1ef 100644 --- a/src/Model/Global/fileTransferModel.ts +++ b/src/Model/Global/fileTransferModel.ts @@ -1,14 +1,21 @@ // this file is responsible for sending and handling files. +import { decryptString, encryptString } from "../Utility/crypto"; +import { generateRandomToken, parse, stringify } from "../Utility/utility"; + import ConnectionModel from "./connectionModel"; +import { Message } from "udn-frontend"; import StorageModel from "./storageModel"; -import { generateRandomToken } from "../Utility/utility"; +import { checkMatchesObjectStructure } from "../Utility/typeSafety"; export default class FileTransferModel { storageModel: StorageModel; connectionModel: ConnectionModel; - // methods + // data + transferData: TransferData | undefined; + + // general generateTransferData = (): TransferData => { return { channel: generateRandomToken(2), @@ -16,10 +23,68 @@ export default class FileTransferModel { }; }; + prepareToReceive = (transferData: TransferData) => { + this.connectionModel.addChannel(transferData.channel); + this.transferData = transferData; + }; + + // handlers + handleMessage = (data: Message): void => { + if (this.transferData == undefined) return; + if (data.messageChannel != this.transferData.channel) return; + }; + + handleFile = async (encryptedFileData: string): Promise => { + if (this.transferData == undefined) return; + + const decrypted: string = await decryptString( + encryptedFileData, + this.transferData.key + ); + + const parsed: any = parse(decrypted); + const isFileData: boolean = checkMatchesObjectStructure(parsed, FileDataReference); + if (isFileData == false) return; + + const fileData: FileData = parsed; + this.storageModel.write(fileData.path, fileData.body); + }; + + // sending + sendFiles = (...directoryPaths: string[][]): void => { + for (const directoryPath of directoryPaths) { + this.storageModel.recurse(directoryPath, (filePath: string[]) => { + this.sendFile(filePath); + }); + } + }; + + sendFile = async (filePath: string[]): Promise => { + if (this.transferData == undefined) return; + const fileContent: string | null = this.storageModel.read(filePath); + if (fileContent == null) return; + + const fileData: FileData = { + path: filePath, + body: fileContent, + }; + const stringifiedFileData: string = stringify(fileData); + const encryptedFileData: string = await encryptString( + fileContent, + stringifiedFileData + ); + this.connectionModel.sendPlainMessage( + this.transferData.channel, + encryptedFileData + ); + }; + // init constructor(storageModel: StorageModel, connectionModel: ConnectionModel) { this.storageModel = storageModel; this.connectionModel = connectionModel; + + this.connectionModel.messageHandlerManager.addHandler(this.handleMessage); } } @@ -27,3 +92,13 @@ export interface TransferData { channel: string; key: string; } + +export interface FileData { + path: string[]; + body: string; +} + +export const FileDataReference: FileData = { + path: [""], + body: "", +};