SimpleX-Chat/apps/ios/SimpleXChat/CryptoFile.swift
Evgeny 24b0f0290b
core: pass event and response error without dedicated constructor (#5869)
* core: pass event and response error without dedicated constructor

* ios: WIP

* android, desktop: update UI for new API

* ios: fix parser

* fix showing invalid chats

* fix mobile api tests

* ios: split ChatResponse to 3 enums, decode API results on the same thread

* tweak types

* remove throws

* rename
2025-05-05 11:51:22 +01:00

69 lines
2.6 KiB
Swift

//
// CryptoFile.swift
// SimpleX (iOS)
//
// Created by Evgeny on 05/09/2023.
// Copyright © 2023 SimpleX Chat. All rights reserved.
//
import Foundation
enum WriteFileResult: Decodable {
case result(cryptoArgs: CryptoFileArgs)
case error(writeError: String)
}
public func writeCryptoFile(path: String, data: Data) throws -> CryptoFileArgs {
let ptr: UnsafeMutableRawPointer = malloc(data.count)
memcpy(ptr, (data as NSData).bytes, data.count)
var cPath = path.cString(using: .utf8)!
let cjson = chat_write_file(getChatCtrl(), &cPath, ptr, Int32(data.count))!
let d = dataFromCString(cjson)! // TODO [unsafe]
switch try jsonDecoder.decode(WriteFileResult.self, from: d) {
case let .result(cfArgs): return cfArgs
case let .error(err): throw RuntimeError(err) // TODO [unsafe]
}
}
public func readCryptoFile(path: String, cryptoArgs: CryptoFileArgs) throws -> Data {
var cPath = path.cString(using: .utf8)!
var cKey = cryptoArgs.fileKey.cString(using: .utf8)!
var cNonce = cryptoArgs.fileNonce.cString(using: .utf8)!
let ptr = chat_read_file(&cPath, &cKey, &cNonce)!
let status = UInt8(ptr.pointee)
switch status {
case 0: // ok
let dLen = Data(bytes: ptr.advanced(by: 1), count: 4)
let len = dLen.withUnsafeBytes { $0.load(as: UInt32.self) }
let d = Data(bytes: ptr.advanced(by: 5), count: Int(len))
free(ptr)
return d
case 1: // error
let err = String.init(cString: ptr)
free(ptr)
throw RuntimeError(err)
default:
throw RuntimeError("unexpected chat_read_file status: \(status)")
}
}
public func encryptCryptoFile(fromPath: String, toPath: String) throws -> CryptoFileArgs {
var cFromPath = fromPath.cString(using: .utf8)!
var cToPath = toPath.cString(using: .utf8)!
let cjson = chat_encrypt_file(getChatCtrl(), &cFromPath, &cToPath)!
let d = dataFromCString(cjson)! // TODO [unsafe]
switch try jsonDecoder.decode(WriteFileResult.self, from: d) {
case let .result(cfArgs): return cfArgs
case let .error(err): throw RuntimeError(err) // TODO [unsafe]
}
}
public func decryptCryptoFile(fromPath: String, cryptoArgs: CryptoFileArgs, toPath: String) throws {
var cFromPath = fromPath.cString(using: .utf8)!
var cKey = cryptoArgs.fileKey.cString(using: .utf8)!
var cNonce = cryptoArgs.fileNonce.cString(using: .utf8)!
var cToPath = toPath.cString(using: .utf8)!
let cErr = chat_decrypt_file(&cFromPath, &cKey, &cNonce, &cToPath)!
let err = fromCString(cErr)
if err != "" { throw RuntimeError(err) }
}