From 15d3d3b11a18d40aee81468bccdd2c4489377a40 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Fri, 28 Jul 2023 21:38:31 +0300 Subject: [PATCH] desktop: encoding utf8 (#2795) * desktop: encoding utf8 * rename functions * logs --- .../src/commonMain/cpp/android/simplex-api.c | 6 ++ .../src/commonMain/cpp/desktop/simplex-api.c | 65 +++++++++++-------- 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c b/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c index fe8dcbd536..7b6c032c8a 100644 --- a/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c +++ b/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c @@ -1,4 +1,7 @@ #include +//#include +//#include +//#include // from the RTS void hs_init(int * argc, char **argv[]); @@ -69,6 +72,9 @@ Java_chat_simplex_common_platform_CoreKt_chatMigrateInit(JNIEnv *env, __unused j JNIEXPORT jstring JNICALL Java_chat_simplex_common_platform_CoreKt_chatSendCmd(JNIEnv *env, __unused jclass clazz, jlong controller, jstring msg) { const char *_msg = (*env)->GetStringUTFChars(env, msg, JNI_FALSE); + //jint length = (jint) (*env)->GetStringUTFLength(env, msg); + //for (int i = 0; i < length; ++i) + // __android_log_print(ANDROID_LOG_ERROR, "simplex", "%d: %02x\n", i, _msg[i]); jstring res = (*env)->NewStringUTF(env, chat_send_cmd((void*)controller, _msg)); (*env)->ReleaseStringUTFChars(env, msg, _msg); return res; diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c b/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c index 2c3e123fd5..8e869ca2d9 100644 --- a/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c @@ -1,20 +1,10 @@ #include #include +#include // from the RTS void hs_init(int * argc, char **argv[]); -//extern void __svfscanf(void){}; -//extern void __vfwscanf(void){}; -//extern void __memset_chk_fail(void){}; -//extern void __strcpy_chk_generic(void){}; -//extern void __strcat_chk_generic(void){}; -//extern void __libc_globals(void){}; -//extern void __rel_iplt_start(void){}; - -// Android 9 only, not 13 -//extern void reallocarray(void){}; - JNIEXPORT void JNICALL Java_chat_simplex_common_platform_CoreKt_initHS(JNIEnv *env, jclass clazz) { hs_init(NULL, NULL); @@ -33,7 +23,7 @@ extern char *chat_password_hash(const char *pwd, const char *salt); // As a reference: https://stackoverflow.com/a/60002045 -jstring correct_string_utf8(JNIEnv *env, char *string) { +jstring decode_to_utf8_string(JNIEnv *env, char *string) { jobject bb = (*env)->NewDirectByteBuffer(env, (void *)string, strlen(string)); jclass cls_charset = (*env)->FindClass(env, "java/nio/charset/Charset"); jmethodID mid_charset_forName = (*env)->GetStaticMethodID(env, cls_charset, "forName", "(Ljava/lang/String;)Ljava/nio/charset/Charset;"); @@ -52,14 +42,33 @@ jstring correct_string_utf8(JNIEnv *env, char *string) { return res; } +char * encode_to_utf8_chars(JNIEnv *env, jstring string) { + if (!string) return ""; + + const jclass cls_string = (*env)->FindClass(env, "java/lang/String"); + const jmethodID mid_getBytes = (*env)->GetMethodID(env, cls_string, "getBytes", "(Ljava/lang/String;)[B"); + const jbyteArray jbyte_array = (jbyteArray) (*env)->CallObjectMethod(env, string, mid_getBytes, (*env)->NewStringUTF(env, "UTF-8")); + jint length = (jint) (*env)->GetArrayLength(env, jbyte_array); + jbyte *jbytes = malloc(length + 1); + (*env)->GetByteArrayRegion(env, jbyte_array, 0, length, jbytes); + // char * should be null terminated but jbyte * isn't. Terminate it with \0. Otherwise, Haskell will not see the end of string + jbytes[length] = '\0'; + + //for (int i = 0; i < length; ++i) + // fprintf(stderr, "%d: %02x\n", i, jbytes[i]); + + (*env)->DeleteLocalRef(env, jbyte_array); + (*env)->DeleteLocalRef(env, cls_string); + return (char *) jbytes; +} JNIEXPORT jobjectArray JNICALL Java_chat_simplex_common_platform_CoreKt_chatMigrateInit(JNIEnv *env, jclass clazz, jstring dbPath, jstring dbKey, jstring confirm) { - const char *_dbPath = (*env)->GetStringUTFChars(env, dbPath, JNI_FALSE); - const char *_dbKey = (*env)->GetStringUTFChars(env, dbKey, JNI_FALSE); - const char *_confirm = (*env)->GetStringUTFChars(env, confirm, JNI_FALSE); - jlong _ctrl = (jlong) 0; - jstring res = correct_string_utf8(env, chat_migrate_init(_dbPath, _dbKey, _confirm, &_ctrl)); + const char *_dbPath = encode_to_utf8_chars(env, dbPath); + const char *_dbKey = encode_to_utf8_chars(env, dbKey); + const char *_confirm = encode_to_utf8_chars(env, confirm); + long int *_ctrl = (long) 0; + jstring res = decode_to_utf8_string(env, chat_migrate_init(_dbPath, _dbKey, _confirm, &_ctrl)); (*env)->ReleaseStringUTFChars(env, dbPath, _dbPath); (*env)->ReleaseStringUTFChars(env, dbKey, _dbKey); (*env)->ReleaseStringUTFChars(env, dbKey, _confirm); @@ -78,43 +87,43 @@ Java_chat_simplex_common_platform_CoreKt_chatMigrateInit(JNIEnv *env, jclass cla JNIEXPORT jstring JNICALL Java_chat_simplex_common_platform_CoreKt_chatSendCmd(JNIEnv *env, jclass clazz, jlong controller, jstring msg) { - const char *_msg = (*env)->GetStringUTFChars(env, msg, JNI_FALSE); - jstring res = correct_string_utf8(env, chat_send_cmd((void*)controller, _msg)); + const char *_msg = encode_to_utf8_chars(env, msg); + jstring res = decode_to_utf8_string(env, chat_send_cmd((void*)controller, _msg)); (*env)->ReleaseStringUTFChars(env, msg, _msg); return res; } JNIEXPORT jstring JNICALL Java_chat_simplex_common_platform_CoreKt_chatRecvMsg(JNIEnv *env, jclass clazz, jlong controller) { - return correct_string_utf8(env, chat_recv_msg((void*)controller)); + return decode_to_utf8_string(env, chat_recv_msg((void*)controller)); } JNIEXPORT jstring JNICALL Java_chat_simplex_common_platform_CoreKt_chatRecvMsgWait(JNIEnv *env, jclass clazz, jlong controller, jint wait) { - return correct_string_utf8(env, chat_recv_msg_wait((void*)controller, wait)); + return decode_to_utf8_string(env, chat_recv_msg_wait((void*)controller, wait)); } JNIEXPORT jstring JNICALL Java_chat_simplex_common_platform_CoreKt_chatParseMarkdown(JNIEnv *env, jclass clazz, jstring str) { - const char *_str = (*env)->GetStringUTFChars(env, str, JNI_FALSE); - jstring res = correct_string_utf8(env, chat_parse_markdown(_str)); + const char *_str = encode_to_utf8_chars(env, str); + jstring res = decode_to_utf8_string(env, chat_parse_markdown(_str)); (*env)->ReleaseStringUTFChars(env, str, _str); return res; } JNIEXPORT jstring JNICALL Java_chat_simplex_common_platform_CoreKt_chatParseServer(JNIEnv *env, jclass clazz, jstring str) { - const char *_str = (*env)->GetStringUTFChars(env, str, JNI_FALSE); - jstring res = correct_string_utf8(env, chat_parse_server(_str)); + const char *_str = encode_to_utf8_chars(env, str); + jstring res = decode_to_utf8_string(env, chat_parse_server(_str)); (*env)->ReleaseStringUTFChars(env, str, _str); return res; } JNIEXPORT jstring JNICALL Java_chat_simplex_common_platform_CoreKt_chatPasswordHash(JNIEnv *env, jclass clazz, jstring pwd, jstring salt) { - const char *_pwd = (*env)->GetStringUTFChars(env, pwd, JNI_FALSE); - const char *_salt = (*env)->GetStringUTFChars(env, salt, JNI_FALSE); - jstring res = correct_string_utf8(env, chat_password_hash(_pwd, _salt)); + const char *_pwd = encode_to_utf8_chars(env, pwd); + const char *_salt = encode_to_utf8_chars(env, salt); + jstring res = decode_to_utf8_string(env, chat_password_hash(_pwd, _salt)); (*env)->ReleaseStringUTFChars(env, pwd, _pwd); (*env)->ReleaseStringUTFChars(env, salt, _salt); return res;