mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-04-21 21:25:43 +00:00
add chatWriteImage
This commit is contained in:
@@ -25,6 +25,18 @@ public func writeCryptoFile(path: String, data: Data) throws -> CryptoFileArgs {
|
||||
}
|
||||
}
|
||||
|
||||
public func writeCryptoImage(maxSize: Int, path: String, data: Data, encrypted: Bool) 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_image(getChatCtrl(), maxSize, &cPath, ptr, Int32(data.count), encrypted)!
|
||||
let d = fromCString(cjson).data(using: .utf8)!
|
||||
switch try jsonDecoder.decode(WriteFileResult.self, from: d) {
|
||||
case let .result(cfArgs): return cfArgs
|
||||
case let .error(err): throw RuntimeError(err)
|
||||
}
|
||||
}
|
||||
|
||||
public func readCryptoFile(path: String, cryptoArgs: CryptoFileArgs) throws -> Data {
|
||||
var cPath = path.cString(using: .utf8)!
|
||||
var cKey = cryptoArgs.fileKey.cString(using: .utf8)!
|
||||
|
||||
@@ -223,6 +223,17 @@ public func saveFile(_ data: Data, _ fileName: String, encrypted: Bool) -> Crypt
|
||||
}
|
||||
}
|
||||
|
||||
public func saveImage(_ data: Data, _ fileName: String, maxSize: Long, encrypted: Bool) -> CryptoFile? {
|
||||
let filePath = getAppFilePath(fileName)
|
||||
do {
|
||||
let cfArgs = try writeCryptoImage(maxSize: maxSize, path: filePath.path, data: data, encrypted: encrypted)
|
||||
return CryptoFile(filePath: fileName, cryptoArgs: cfArgs)
|
||||
} catch {
|
||||
logger.error("FileUtils.saveImage error: \(error.localizedDescription)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public func removeFile(_ url: URL) {
|
||||
do {
|
||||
try FileManager.default.removeItem(atPath: url.path)
|
||||
|
||||
@@ -35,7 +35,7 @@ extern char *chat_resize_image_to_str_size(const char *path, long maxSize);
|
||||
extern char *chat_write_file(chat_ctrl ctl, char *path, char *data, int len);
|
||||
|
||||
// chat_write_image returns null-terminated string with JSON of WriteFileResult
|
||||
extern char *chat_write_image(chat_ctrl ctl, long maxSize, char *path, char *data, int len);
|
||||
extern char *chat_write_image(chat_ctrl ctl, long maxSize, char *path, char *data, int len, bool encrypted);
|
||||
|
||||
// chat_read_file returns a buffer with:
|
||||
// result status (1 byte), then if
|
||||
|
||||
@@ -72,11 +72,11 @@ fun Bitmap.clipToCircle(): Bitmap {
|
||||
return circle
|
||||
}
|
||||
|
||||
actual fun compressImageStr(bitmap: ImageBitmap): String {
|
||||
val usePng = bitmap.hasAlpha()
|
||||
val ext = if (usePng) "png" else "jpg"
|
||||
return "data:image/$ext;base64," + Base64.encodeToString(compressImageData(bitmap, usePng).toByteArray(), Base64.NO_WRAP)
|
||||
}
|
||||
// actual fun compressImageStr(bitmap: ImageBitmap): String {
|
||||
// val usePng = bitmap.hasAlpha()
|
||||
// val ext = if (usePng) "png" else "jpg"
|
||||
// return "data:image/$ext;base64," + Base64.encodeToString(compressImageData(bitmap, usePng).toByteArray(), Base64.NO_WRAP)
|
||||
// }
|
||||
|
||||
actual fun compressImageData(bitmap: ImageBitmap, usePng: Boolean): ByteArrayOutputStream {
|
||||
val stream = ByteArrayOutputStream()
|
||||
@@ -84,19 +84,19 @@ actual fun compressImageData(bitmap: ImageBitmap, usePng: Boolean): ByteArrayOut
|
||||
return stream
|
||||
}
|
||||
|
||||
actual fun resizeImageToDataSize(image: ImageBitmap, usePng: Boolean, maxDataSize: Long): ByteArrayOutputStream {
|
||||
var img = image
|
||||
var stream = compressImageData(img, usePng)
|
||||
while (stream.size() > maxDataSize) {
|
||||
val ratio = sqrt(stream.size().toDouble() / maxDataSize.toDouble())
|
||||
val clippedRatio = min(ratio, 2.0)
|
||||
val width = (img.width.toDouble() / clippedRatio).toInt()
|
||||
val height = img.height * width / img.width
|
||||
img = Bitmap.createScaledBitmap(img.asAndroidBitmap(), width, height, true).asImageBitmap()
|
||||
stream = compressImageData(img, usePng)
|
||||
}
|
||||
return stream
|
||||
}
|
||||
// actual fun resizeImageToDataSize(image: ImageBitmap, usePng: Boolean, maxDataSize: Long): ByteArrayOutputStream {
|
||||
// var img = image
|
||||
// var stream = compressImageData(img, usePng)
|
||||
// while (stream.size() > maxDataSize) {
|
||||
// val ratio = sqrt(stream.size().toDouble() / maxDataSize.toDouble())
|
||||
// val clippedRatio = min(ratio, 2.0)
|
||||
// val width = (img.width.toDouble() / clippedRatio).toInt()
|
||||
// val height = img.height * width / img.width
|
||||
// img = Bitmap.createScaledBitmap(img.asAndroidBitmap(), width, height, true).asImageBitmap()
|
||||
// stream = compressImageData(img, usePng)
|
||||
// }
|
||||
// return stream
|
||||
// }
|
||||
|
||||
actual fun GrayU8.toImageBitmap(): ImageBitmap = ConvertBitmap.grayToBitmap(this, Bitmap.Config.RGB_565).asImageBitmap()
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <jni.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
//#include <stdlib.h>
|
||||
//#include <android/log.h>
|
||||
@@ -68,7 +69,7 @@ extern char *chat_password_hash(const char *pwd, const char *salt);
|
||||
extern char *chat_valid_name(const char *name);
|
||||
extern int chat_json_length(const char *str);
|
||||
extern char *chat_write_file(chat_ctrl ctrl, const char *path, char *ptr, int length);
|
||||
extern char *chat_write_image(chat_ctrl ctl, long maxSize, char *path, char *data, int len);
|
||||
extern char *chat_write_image(chat_ctrl ctrl, long max_size, const char *path, char *ptr, int length, bool encrypt);
|
||||
extern char *chat_read_file(const char *path, const char *key, const char *nonce);
|
||||
extern char *chat_encrypt_file(chat_ctrl ctrl, const char *from_path, const char *to_path);
|
||||
extern char *chat_decrypt_file(const char *from_path, const char *key, const char *nonce, const char *to_path);
|
||||
@@ -185,11 +186,11 @@ Java_chat_simplex_common_platform_CoreKt_chatWriteFile(JNIEnv *env, jclass clazz
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_chat_simplex_common_platform_CoreKt_chatWriteImage(JNIEnv *env, jclass clazz, jlong controller, jlong maxSize, jstring path, jobject buffer) {
|
||||
Java_chat_simplex_common_platform_CoreKt_chatWriteImage(JNIEnv *env, jclass clazz, jlong controller, jlong maxSize, jstring path, jobject buffer, jboolean encrypt) {
|
||||
const char *_path = encode_to_utf8_chars(env, path);
|
||||
jbyte *buff = (jbyte *) (*env)->GetDirectBufferAddress(env, buffer);
|
||||
jlong capacity = (*env)->GetDirectBufferCapacity(env, buffer);
|
||||
jstring res = decode_to_utf8_string(env, chat_write_image((void*)controller, maxSize, _path, buff, capacity));
|
||||
jstring res = decode_to_utf8_string(env, chat_write_image((void*)controller, maxSize, _path, buff, capacity, encrypt));
|
||||
(*env)->ReleaseStringUTFChars(env, path, _path);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <jni.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -41,7 +42,7 @@ extern char *chat_password_hash(const char *pwd, const char *salt);
|
||||
extern char *chat_valid_name(const char *name);
|
||||
extern int chat_json_length(const char *str);
|
||||
extern char *chat_write_file(chat_ctrl ctrl, const char *path, char *ptr, int length);
|
||||
extern char *chat_write_image(chat_ctrl ctrl, long max_size, const char *path, char *ptr, int length);
|
||||
extern char *chat_write_image(chat_ctrl ctrl, long max_size, const char *path, char *ptr, int length, bool encrypt);
|
||||
extern char *chat_read_file(const char *path, const char *key, const char *nonce);
|
||||
extern char *chat_encrypt_file(chat_ctrl ctrl, const char *from_path, const char *to_path);
|
||||
extern char *chat_decrypt_file(const char *from_path, const char *key, const char *nonce, const char *to_path);
|
||||
@@ -195,11 +196,11 @@ Java_chat_simplex_common_platform_CoreKt_chatWriteFile(JNIEnv *env, jclass clazz
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_chat_simplex_common_platform_CoreKt_chatWriteImage(JNIEnv *env, jclass clazz, jlong controller, jlong maxSize, jstring path, jobject buffer) {
|
||||
Java_chat_simplex_common_platform_CoreKt_chatWriteImage(JNIEnv *env, jclass clazz, jlong controller, jlong maxSize, jstring path, jobject buffer, jboolean encrypt) {
|
||||
const char *_path = encode_to_utf8_chars(env, path);
|
||||
jbyte *buff = (jbyte *) (*env)->GetDirectBufferAddress(env, buffer);
|
||||
jlong capacity = (*env)->GetDirectBufferCapacity(env, buffer);
|
||||
jstring res = decode_to_utf8_string(env, chat_write_image((void*)controller, maxSize, _path, buff, capacity));
|
||||
jstring res = decode_to_utf8_string(env, chat_write_image((void*)controller, maxSize, _path, buff, capacity, encrypt));
|
||||
(*env)->ReleaseStringUTFChars(env, path, _path);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package chat.simplex.common.model
|
||||
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import chat.simplex.common.platform.*
|
||||
import kotlinx.serialization.*
|
||||
import java.nio.ByteBuffer
|
||||
@@ -32,6 +33,19 @@ fun writeCryptoFile(path: String, data: ByteArray): CryptoFileArgs {
|
||||
}
|
||||
}
|
||||
|
||||
fun writeCryptoImage(maxSize: Long, image: ImageBitmap, path: String, encrypt: Boolean): CryptoFileArgs {
|
||||
val ctrl = ChatController.ctrl ?: throw Exception("Controller is not initialized")
|
||||
val data = compressImageData(image, image.hasAlpha).toByteArray()
|
||||
val buffer = ByteBuffer.allocateDirect(data.size)
|
||||
buffer.put(data)
|
||||
buffer.rewind()
|
||||
val str = chatWriteImage(ctrl, maxSize, path, buffer, encrypt)
|
||||
return when (val d = json.decodeFromString(WriteFileResult.serializer(), str)) {
|
||||
is WriteFileResult.Result -> d.cryptoArgs
|
||||
is WriteFileResult.Error -> throw Exception(d.writeError)
|
||||
}
|
||||
}
|
||||
|
||||
fun readCryptoFile(path: String, cryptoArgs: CryptoFileArgs): ByteArray {
|
||||
val res: Array<Any> = chatReadFile(path, cryptoArgs.fileKey, cryptoArgs.fileNonce)
|
||||
val status = (res[0] as Integer).toInt()
|
||||
|
||||
@@ -32,6 +32,7 @@ external fun chatPasswordHash(pwd: String, salt: String): String
|
||||
external fun chatValidName(name: String): String
|
||||
external fun chatJsonLength(str: String): Int
|
||||
external fun chatWriteFile(ctrl: ChatCtrl, path: String, buffer: ByteBuffer): String
|
||||
external fun chatWriteImage(ctrl: ChatCtrl, maxSize: Long, path: String, buffer: ByteBuffer, encrypt: Boolean): String
|
||||
external fun chatReadFile(path: String, key: String, nonce: String): Array<Any>
|
||||
external fun chatEncryptFile(ctrl: ChatCtrl, fromPath: String, toPath: String): String
|
||||
external fun chatDecryptFile(fromPath: String, key: String, nonce: String, toPath: String): String
|
||||
|
||||
@@ -9,9 +9,9 @@ import java.net.URI
|
||||
expect fun base64ToBitmap(base64ImageString: String): ImageBitmap
|
||||
// XXX: Not a part of platform services anymore?
|
||||
expect fun resizeImageToStrSize(image: ImageBitmap, maxDataSize: Long): String
|
||||
expect fun resizeImageToDataSize(image: ImageBitmap, usePng: Boolean, maxDataSize: Long): ByteArrayOutputStream
|
||||
// expect fun resizeImageToDataSize(image: ImageBitmap, usePng: Boolean, maxDataSize: Long): ByteArrayOutputStream
|
||||
expect fun cropToSquare(image: ImageBitmap): ImageBitmap
|
||||
expect fun compressImageStr(bitmap: ImageBitmap): String
|
||||
// expect fun compressImageStr(bitmap: ImageBitmap): String
|
||||
expect fun compressImageData(bitmap: ImageBitmap, usePng: Boolean): ByteArrayOutputStream
|
||||
|
||||
expect fun GrayU8.toImageBitmap(): ImageBitmap
|
||||
|
||||
@@ -169,24 +169,19 @@ fun saveImage(image: ImageBitmap): CryptoFile? {
|
||||
return try {
|
||||
val encrypted = chatController.appPrefs.privacyEncryptLocalFiles.get()
|
||||
val ext = if (image.hasAlpha()) "png" else "jpg"
|
||||
val dataResized = resizeImageToDataSize(image, ext == "png", maxDataSize = MAX_IMAGE_SIZE)
|
||||
val destFileName = generateNewFileName("IMG", ext, File(getAppFilePath("")))
|
||||
val destFile = File(getAppFilePath(destFileName))
|
||||
if (encrypted) {
|
||||
try {
|
||||
val args = writeCryptoFile(destFile.absolutePath, dataResized.toByteArray())
|
||||
try {
|
||||
val args = writeCryptoImage(MAX_IMAGE_SIZE, image, destFile.absolutePath, encrypted)
|
||||
if (encrypted) {
|
||||
CryptoFile(destFileName, args)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to write crypto file: " + e.stackTraceToString())
|
||||
AlertManager.shared.showAlertMsg(title = generalGetString(MR.strings.error), text = e.stackTraceToString())
|
||||
null
|
||||
} else {
|
||||
CryptoFile.plain(destFileName)
|
||||
}
|
||||
} else {
|
||||
val output = FileOutputStream(destFile)
|
||||
dataResized.writeTo(output)
|
||||
output.flush()
|
||||
output.close()
|
||||
CryptoFile.plain(destFileName)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to write crypto file: " + e.stackTraceToString())
|
||||
AlertManager.shared.showAlertMsg(title = generalGetString(MR.strings.error), text = e.stackTraceToString())
|
||||
null
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Util.kt saveImage error: ${e.stackTraceToString()}")
|
||||
@@ -198,14 +193,10 @@ fun desktopSaveImageInTmp(uri: URI): CryptoFile? {
|
||||
val image = getBitmapFromUri(uri) ?: return null
|
||||
return try {
|
||||
val ext = if (image.hasAlpha()) "png" else "jpg"
|
||||
val dataResized = resizeImageToDataSize(image, ext == "png", maxDataSize = MAX_IMAGE_SIZE)
|
||||
val destFileName = generateNewFileName("IMG", ext, tmpDir)
|
||||
val destFile = File(tmpDir, destFileName)
|
||||
val output = FileOutputStream(destFile)
|
||||
dataResized.writeTo(output)
|
||||
output.flush()
|
||||
output.close()
|
||||
CryptoFile.plain(destFile.absolutePath)
|
||||
val args = writeCryptoImage(MAX_IMAGE_SIZE, image, destFile.absolutePath, false)
|
||||
CryptoFile(destFileName, args)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Util.kt desktopSaveImageInTmp error: ${e.stackTraceToString()}")
|
||||
null
|
||||
@@ -301,11 +292,7 @@ fun saveWallpaperFile(uri: URI): String? {
|
||||
fun saveWallpaperFile(image: ImageBitmap): String {
|
||||
val destFileName = generateNewFileName("wallpaper", "jpg", File(getWallpaperFilePath("")))
|
||||
val destFile = File(getWallpaperFilePath(destFileName))
|
||||
val dataResized = resizeImageToDataSize(image, false, maxDataSize = 5_000_000)
|
||||
val output = FileOutputStream(destFile)
|
||||
dataResized.use {
|
||||
it.writeTo(output)
|
||||
}
|
||||
writeCryptoImage(5_000_000, image, destFile.absolutePath, false)
|
||||
return destFile.name
|
||||
}
|
||||
|
||||
|
||||
@@ -46,19 +46,19 @@ actual fun resizeImageToStrSize(image: ImageBitmap, maxDataSize: Long): String {
|
||||
return str
|
||||
}
|
||||
|
||||
actual fun resizeImageToDataSize(image: ImageBitmap, usePng: Boolean, maxDataSize: Long): ByteArrayOutputStream {
|
||||
var img = image
|
||||
var stream = compressImageData(img, usePng)
|
||||
while (stream.size() > maxDataSize) {
|
||||
val ratio = sqrt(stream.size().toDouble() / maxDataSize.toDouble())
|
||||
val clippedRatio = kotlin.math.min(ratio, 2.0)
|
||||
val width = (img.width.toDouble() / clippedRatio).toInt()
|
||||
val height = img.height * width / img.width
|
||||
img = img.scale(width, height)
|
||||
stream = compressImageData(img, usePng)
|
||||
}
|
||||
return stream
|
||||
}
|
||||
// actual fun resizeImageToDataSize(image: ImageBitmap, usePng: Boolean, maxDataSize: Long): ByteArrayOutputStream {
|
||||
// var img = image
|
||||
// var stream = compressImageData(img, usePng)
|
||||
// while (stream.size() > maxDataSize) {
|
||||
// val ratio = sqrt(stream.size().toDouble() / maxDataSize.toDouble())
|
||||
// val clippedRatio = kotlin.math.min(ratio, 2.0)
|
||||
// val width = (img.width.toDouble() / clippedRatio).toInt()
|
||||
// val height = img.height * width / img.width
|
||||
// img = img.scale(width, height)
|
||||
// stream = compressImageData(img, usePng)
|
||||
// }
|
||||
// return stream
|
||||
// }
|
||||
|
||||
actual fun cropToSquare(image: ImageBitmap): ImageBitmap {
|
||||
var xOffset = 0
|
||||
@@ -73,17 +73,17 @@ actual fun cropToSquare(image: ImageBitmap): ImageBitmap {
|
||||
return image
|
||||
}
|
||||
|
||||
actual fun compressImageStr(bitmap: ImageBitmap): String {
|
||||
val usePng = bitmap.hasAlpha()
|
||||
val ext = if (usePng) "png" else "jpg"
|
||||
return try {
|
||||
val encoded = Base64.getEncoder().encodeToString(compressImageData(bitmap, usePng).toByteArray())
|
||||
"data:image/$ext;base64,$encoded"
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "resizeImageToStrSize error: $e")
|
||||
throw e
|
||||
}
|
||||
}
|
||||
// actual fun compressImageStr(bitmap: ImageBitmap): String {
|
||||
// val usePng = bitmap.hasAlpha()
|
||||
// val ext = if (usePng) "png" else "jpg"
|
||||
// return try {
|
||||
// val encoded = Base64.getEncoder().encodeToString(compressImageData(bitmap, usePng).toByteArray())
|
||||
// "data:image/$ext;base64,$encoded"
|
||||
// } catch (e: Exception) {
|
||||
// Log.e(TAG, "resizeImageToStrSize error: $e")
|
||||
// throw e
|
||||
// }
|
||||
// }
|
||||
|
||||
actual fun compressImageData(bitmap: ImageBitmap, usePng: Boolean): ByteArrayOutputStream {
|
||||
val writer = ImageIO.getImageWritersByFormatName(if (usePng) "png" else "jpg").next()
|
||||
|
||||
@@ -30,7 +30,7 @@ import Data.Word (Word8)
|
||||
import Database.SQLite.Simple (SQLError (..))
|
||||
import qualified Database.SQLite.Simple as DB
|
||||
import Foreign.C.String
|
||||
import Foreign.C.Types (CInt (..), CLong (..))
|
||||
import Foreign.C.Types (CBool (..), CInt (..), CLong (..))
|
||||
import Foreign.Ptr
|
||||
import Foreign.StablePtr
|
||||
import Foreign.Storable (poke)
|
||||
@@ -105,7 +105,7 @@ foreign export ccall "chat_decrypt_media" cChatDecryptMedia :: CString -> Ptr Wo
|
||||
|
||||
foreign export ccall "chat_write_file" cChatWriteFile :: StablePtr ChatController -> CString -> Ptr Word8 -> CInt -> IO CJSONString
|
||||
|
||||
foreign export ccall "chat_write_image" cChatWriteImage :: StablePtr ChatController -> CLong -> CString -> Ptr Word8 -> CInt -> IO CJSONString
|
||||
foreign export ccall "chat_write_image" cChatWriteImage :: StablePtr ChatController -> CLong -> CString -> Ptr Word8 -> CInt -> CBool -> IO CJSONString
|
||||
|
||||
foreign export ccall "chat_read_file" cChatReadFile :: CString -> CString -> CString -> IO (Ptr Word8)
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ import Simplex.Messaging.Util (catchAll)
|
||||
import UnliftIO (Handle, IOMode (..), atomically, withFile)
|
||||
|
||||
data WriteFileResult
|
||||
= WFResult {cryptoArgs :: CryptoFileArgs}
|
||||
= WFResult {cryptoArgs :: Maybe CryptoFileArgs}
|
||||
| WFError {writeError :: String}
|
||||
|
||||
$(JQ.deriveToJSON (sumTypeJSON $ dropPrefix "WF") ''WriteFileResult)
|
||||
@@ -61,28 +61,33 @@ cChatWriteFile cc cPath ptr len = do
|
||||
r <- chatWriteFile c path s
|
||||
newCStringFromLazyBS $ J.encode r
|
||||
|
||||
cChatWriteImage :: StablePtr ChatController -> CLong -> CString -> Ptr Word8 -> CInt -> IO CJSONString
|
||||
cChatWriteImage cc maxSize cPath ptr len = do
|
||||
chatWriteFile :: ChatController -> FilePath -> ByteString -> IO WriteFileResult
|
||||
chatWriteFile ChatController {random} path s = do
|
||||
cfArgs <- atomically $ CF.randomArgs random
|
||||
chatWriteFile_ (Just cfArgs) path s
|
||||
|
||||
chatWriteFile_ :: Maybe CryptoFileArgs -> FilePath -> ByteString -> IO WriteFileResult
|
||||
chatWriteFile_ cfArgs_ path s = do
|
||||
let file = CryptoFile path cfArgs_
|
||||
either WFError (\_ -> WFResult cfArgs_)
|
||||
<$> runCatchExceptT (withExceptT show $ CF.writeFile file $ LB.fromStrict s)
|
||||
|
||||
cChatWriteImage :: StablePtr ChatController -> CLong -> CString -> Ptr Word8 -> CInt -> CBool -> IO CJSONString
|
||||
cChatWriteImage cc maxSize cPath ptr len encrypt = do
|
||||
c <- deRefStablePtr cc
|
||||
path <- peekCString cPath
|
||||
src <- getByteString ptr len
|
||||
cfArgs_ <- if encrypt /= 0 then Just <$> atomically (CF.randomArgs $ random c) else pure Nothing
|
||||
r <-
|
||||
case Picture.decodeResizeable src of
|
||||
Left e -> pure $ WFError e
|
||||
Right (ri, _metadata) -> do
|
||||
let resized = resizeImageToSize True (fromIntegral maxSize) ri
|
||||
let resized = resizeImageToSize False (fromIntegral maxSize) ri
|
||||
if LB.length resized > fromIntegral maxSize
|
||||
then pure $ WFError "unable to fit"
|
||||
else chatWriteFile c path (LB.toStrict resized)
|
||||
else chatWriteFile_ cfArgs_ path (LB.toStrict resized)
|
||||
newCStringFromLazyBS $ J.encode r
|
||||
|
||||
chatWriteFile :: ChatController -> FilePath -> ByteString -> IO WriteFileResult
|
||||
chatWriteFile ChatController {random} path s = do
|
||||
cfArgs <- atomically $ CF.randomArgs random
|
||||
let file = CryptoFile path $ Just cfArgs
|
||||
either WFError (\_ -> WFResult cfArgs)
|
||||
<$> runCatchExceptT (withExceptT show $ CF.writeFile file $ LB.fromStrict s)
|
||||
|
||||
data ReadFileResult
|
||||
= RFResult {fileSize :: Int}
|
||||
| RFError {readError :: String}
|
||||
@@ -124,7 +129,7 @@ chatEncryptFile ChatController {random} fromPath toPath =
|
||||
encrypt = do
|
||||
cfArgs <- atomically $ CF.randomArgs random
|
||||
encryptFile fromPath toPath cfArgs
|
||||
pure cfArgs
|
||||
pure $ Just cfArgs
|
||||
|
||||
cChatDecryptFile :: CString -> CString -> CString -> CString -> IO CString
|
||||
cChatDecryptFile cFromPath cKey cNonce cToPath = do
|
||||
|
||||
Reference in New Issue
Block a user