Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions library/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ android {
"proguard-rules.pro"
)
}

debug {
packaging {
jniLibs {
keepDebugSymbols += "**/*.so"
}
}
}
}

compileOptions {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package network.loki.messenger.libsession_util.image

import android.graphics.ImageDecoder
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.sessionfoundation.libsession_util.test.R

@RunWith(AndroidJUnit4::class)
class GifUtilsTest {
@Test
fun testReencodeGif() {

for (outputSize in listOf(200, 400, 600)) {
val output = InstrumentationRegistry.getInstrumentation()
.targetContext
.applicationContext
.resources
.openRawResource(R.raw.earth).use { input ->
GifUtils.reencodeGif(
input = input,
timeoutMills = 100_000L,
targetWidth = outputSize,
targetHeight = outputSize
)
}

ImageDecoder.decodeDrawable(
ImageDecoder.createSource(output)
) { decoder, info, source ->
assertEquals(outputSize, info.size.width)
assertEquals(outputSize, info.size.height)
assertTrue(info.isAnimated)
}
}
}

@Test
fun testCheckAnimatedGifWorks() {
assertTrue(
InstrumentationRegistry.getInstrumentation()
.targetContext
.applicationContext
.resources
.openRawResource(R.raw.earth)
.use(GifUtils::isAnimatedGif)
)

assertFalse(
InstrumentationRegistry.getInstrumentation()
.targetContext
.applicationContext
.resources
.openRawResource(R.raw.sunflower_noanim)
.use(GifUtils::isAnimatedGif)
)
}
}
Binary file added library/src/androidTest/res/raw/earth.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
85 changes: 82 additions & 3 deletions library/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS -Wno-deprecated-declarations)

set(CMAKE_BUILD_TYPE Release)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
Expand All @@ -26,6 +24,55 @@ set(STATIC_BUNDLE ON)
set(ENABLE_ONIONREQ OFF)
add_subdirectory(../../../../libsession-util libsession)

include(FetchContent)


## Catering for libwebp
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
set(WEBP_BUILD_ANIM_UTILS ON CACHE BOOL "" FORCE)
set(WEBP_BUILD_LIBWEBPMUX ON CACHE BOOL "" FORCE)

FetchContent_Declare(
webp
GIT_REPOSITORY https://chromium.googlesource.com/webm/libwebp
GIT_TAG v1.6.0
)

FetchContent_MakeAvailable(webp)

## Catering for libyuv - to rescale images
FetchContent_Declare(
libyuv
GIT_REPOSITORY https://chromium.googlesource.com/libyuv/libyuv
GIT_TAG stable
)
FetchContent_MakeAvailable(libyuv)

## cgif
FetchContent_Declare(
cgif
GIT_REPOSITORY https://github.com/dloebl/cgif.git
GIT_TAG 4ddc417
)
FetchContent_MakeAvailable(cgif)

## giflib (only to encode)
FetchContent_Declare(
giflib
GIT_REPOSITORY https://git.code.sf.net/p/giflib/code
GIT_TAG 5.2.2
)
FetchContent_MakeAvailable(giflib)

## EasyGifReader (on top of giflib for easier reading)
FetchContent_Declare(
easy_gif_reader
GIT_REPOSITORY https://github.com/Chlumsky/EasyGifReader
GIT_TAG eaaa794
)
FetchContent_MakeAvailable(easy_gif_reader)


set(SOURCES
user_profile.cpp
user_groups.cpp
Expand All @@ -44,6 +91,23 @@ set(SOURCES
ed25519.cpp
curve25519.cpp
hash.cpp
attachments.cpp
webp_utils.cpp
gif_utils.cpp

${cgif_SOURCE_DIR}/src/cgif.c
${cgif_SOURCE_DIR}/src/cgif_rgb.c
${cgif_SOURCE_DIR}/src/cgif_raw.c

${giflib_SOURCE_DIR}/gifalloc.c
${giflib_SOURCE_DIR}/gif_err.c
${giflib_SOURCE_DIR}/dgif_lib.c
${giflib_SOURCE_DIR}/egif_lib.c
${giflib_SOURCE_DIR}/gif_hash.c
${giflib_SOURCE_DIR}/gif_font.c
${giflib_SOURCE_DIR}/openbsd-reallocarray.c

${easy_gif_reader_SOURCE_DIR}/EasyGifReader.cpp
)

add_library( # Sets the name of the library.
Expand All @@ -53,6 +117,15 @@ add_library( # Sets the name of the library.
# Provides a relative path to your source file(s).
${SOURCES})

target_include_directories(session_util
PRIVATE
${cgif_SOURCE_DIR}/inc
${libyuv_SOURCE_DIR}/include
${giflib_SOURCE_DIR}
${easy_gif_reader_SOURCE_DIR}
)


# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
Expand All @@ -78,4 +151,10 @@ target_link_libraries( # Specifies the target library.
libsodium::sodium-internal
# Links the target library to the log library
# included in the NDK.
${log-lib})
${log-lib}
webp
libwebpmux
webpdemux
webpdecoder
yuv
)
79 changes: 79 additions & 0 deletions library/src/main/cpp/attachments.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include <jni.h>
#include <session/attachments.hpp>
#include "jni_utils.h"

using namespace session::attachment;
using namespace jni_utils;

extern "C"
JNIEXPORT jlong JNICALL
Java_network_loki_messenger_libsession_1util_encrypt_Attachments_encryptedSize(JNIEnv *env,
jobject thiz,
jlong plaintext_size) {
return encrypted_size(plaintext_size);
}

extern "C"
JNIEXPORT jlong JNICALL
Java_network_loki_messenger_libsession_1util_encrypt_Attachments_decryptedMaxSize(JNIEnv *env,
jobject thiz,
jlong ciphertext_size) {
auto s = decrypted_max_size(ciphertext_size);
if (s.has_value()) {
return *s;
} else {
env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"),
"ciphertext_size too small to be a valid encrypted attachment");
return 0;
}
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_network_loki_messenger_libsession_1util_encrypt_Attachments_encryptBytes(JNIEnv *env,
jobject thiz,
jbyteArray seed,
jbyteArray plaintext_in,
jint plaintext_in_offset,
jint plaintext_in_len,
jbyteArray cipher_out,
jint cipher_out_offset,
jint cipher_out_len,
jint domain) {
return run_catching_cxx_exception_or_throws<jbyteArray>(env, [=] {
auto key = encrypt(
JavaByteArrayRef(env, seed).get_as_bytes(),
JavaByteArrayRef(env, plaintext_in).get_as_bytes().subspan(plaintext_in_offset, plaintext_in_len),
static_cast<Domain>(domain),
JavaByteArrayRef(env, cipher_out).get_as_bytes().subspan(cipher_out_offset, cipher_out_len)
);


return util::bytes_from_span(env, std::span(reinterpret_cast<unsigned char *>(key.data()), key.size()));
});
}

extern "C"
JNIEXPORT jlong JNICALL
Java_network_loki_messenger_libsession_1util_encrypt_Attachments_decryptBytes(JNIEnv *env,
jobject thiz,
jbyteArray key,
jbyteArray cipher_in,
jint cipher_in_offset,
jint cipher_in_len,
jbyteArray plain_out,
jint plain_out_offset,
jint plain_out_len) {
return run_catching_cxx_exception_or_throws<jlong>(env, [=] {
JavaByteArrayRef key_ref(env, key);

return decrypt(
JavaByteArrayRef(env, cipher_in).get_as_bytes().subspan(cipher_in_offset, cipher_in_len),
std::span<std::byte, ENCRYPT_KEY_SIZE>(
reinterpret_cast<std::byte *>(key_ref.get().data()),
ENCRYPT_KEY_SIZE
),
JavaByteArrayRef(env, plain_out).get_as_bytes().subspan(plain_out_offset, plain_out_len)
);
});
}
Loading