diff --git a/tools/chatgui-android/jni_bridge/android_jni_bridge.c b/tools/chatgui-android/jni_bridge/android_jni_bridge.c index 384cc683..274adf50 100644 --- a/tools/chatgui-android/jni_bridge/android_jni_bridge.c +++ b/tools/chatgui-android/jni_bridge/android_jni_bridge.c @@ -2713,7 +2713,7 @@ JNIEXPORT jboolean JNICALL Java_com_utun_chat_data_NativeLib_nativeAvatarOperati (void)thiz; struct UTUN_INSTANCE* inst = instance_lite_get_instance(); struct UASYNC* ua = instance_lite_get_uasync(); - if (!inst || !ua || !uasync_is_running(ua) || !id || (!group && op != 7) || op < 0 || op > 7) { + if (!inst || !ua || !uasync_is_running(ua) || !id || (!group && op != 7) || op < 0 || op > 8) { DEBUG_WARN(DEBUG_CATEGORY_CHAT, "Android avatar: unavailable/invalid operation=%d id=%lld group=%llx", op, (long long)id, (unsigned long long)group); return JNI_FALSE; } @@ -2721,8 +2721,8 @@ JNIEXPORT jboolean JNICALL Java_com_utun_chat_data_NativeLib_nativeAvatarOperati const char* file = local ? (*env)->GetStringUTFChars(env, local, NULL) : NULL; void* req = NULL; uasync_post_callback_t callback = NULL; if ((remote && !path) || (local && !file)) goto invalid; - if (op >= 1 && op <= 4 && (!server || !owner || !path || - (op == 3 ? strcmp(path, "avatars") != 0 : + if (((op >= 1 && op <= 4) || op == 8) && (!server || !owner || !path || + (op == 3 || op == 8 ? strcmp(path, "avatars") != 0 : strncmp(path, "avatars/", 8) != 0 || !mf_avatar_file_valid(path + 8)))) goto invalid; if (op == 0 || op == 6) { struct group_avatar_gui_request* r = u_calloc(1, sizeof(*r)); req = r; @@ -2741,18 +2741,30 @@ JNIEXPORT jboolean JNICALL Java_com_utun_chat_data_NativeLib_nativeAvatarOperati struct mf_transfer_request* r = u_calloc(1, sizeof(*r)); req = r; if (!r) goto invalid; r->inst = inst; r->id = id; r->group = group; r->server = server; r->owner = owner; - r->upload = op == 2; r->max_bytes = MF_AVATAR_MAX_BYTES; + uint8_t limit[8]; + if (!data || (*env)->GetArrayLength(env, data) != 8) goto invalid; + (*env)->GetByteArrayRegion(env, data, 0, 8, (jbyte*)limit); + if ((*env)->ExceptionCheck(env)) goto invalid; + r->upload = op == 2; r->max_bytes = mf_get64(limit); + if (!r->max_bytes || r->max_bytes > mf_avatar_file_limit(path + 8)) goto invalid; memcpy(r->remote, path, strlen(path) + 1); memcpy(r->local, file, strlen(file) + 1); callback = member_files_gui_transfer; - } else if (op == 3 || op == 4) { + } else if (op == 3 || op == 4 || op == 8) { struct mf_gui_request* r = u_calloc(1, sizeof(*r)); req = r; if (!r) goto invalid; r->inst = inst; r->group = group; r->server = server; - r->message.kind = MF_REQUEST; r->message.command = op == 3 ? MF_MKDIR : MF_STAT; + r->message.kind = MF_REQUEST; r->message.command = op == 3 ? MF_MKDIR : op == 8 ? MF_LIST : MF_STAT; r->message.request_id = id; r->message.owner = owner; + if (op == 8) { + uint8_t page[24]; + if (!data || (*env)->GetArrayLength(env, data) != 24) goto invalid; + (*env)->GetByteArrayRegion(env, data, 0, 24, (jbyte*)page); + if ((*env)->ExceptionCheck(env)) goto invalid; + r->message.cursor = mf_get64(page); memcpy(r->message.version, page + 8, 16); + } memcpy(r->message.path, path, strlen(path) + 1); callback = member_files_gui_request; } else if (op == 5) { - if (server && (!path || !mf_avatar_file_valid(path))) goto invalid; + if (server && (!path || !mf_avatar_manifest_valid(path))) goto invalid; struct chat_avatar_req* r = u_calloc(1, sizeof(*r)); req = r; if (!r) goto invalid; r->inst = inst; r->id = id; r->group = group; r->server = server;