mirror of
https://github.com/oxen-io/session-android.git
synced 2025-08-11 12:37:26 +00:00
Strings work
Squashed commit of the following: commit86cab0e11e
Author: ThomasSession <thomas.r@getsession.org> Date: Fri Aug 30 10:17:04 2024 +1000 Bringing my xml dialog styling from my 'Standardise message deletion' branch commit706d1aadd8
Author: ThomasSession <thomas.r@getsession.org> Date: Fri Aug 30 09:49:48 2024 +1000 fixing up clear data dialog Removing unused code commitf90599451f
Author: Al Lansley <al@oxen.io> Date: Fri Aug 30 09:13:51 2024 +1000 Replaced 'now' with 12/24 hour time commit16b8ad46c0
Author: alansley <aclansley@gmail.com> Date: Thu Aug 29 17:34:03 2024 +1000 Fix two one-liner issues commit4c6c450b32
Merge:052f910d69
beb89d5b74
Author: ThomasSession <thomas.r@getsession.org> Date: Thu Aug 29 17:07:16 2024 +1000 Merge branch 'strings-squashed' of https://github.com/oxen-io/session-android into strings-squashed commit052f910d69
Author: ThomasSession <thomas.r@getsession.org> Date: Thu Aug 29 17:06:53 2024 +1000 More bold fixing commitbeb89d5b74
Author: fanchao <git@fanchao.dev> Date: Thu Aug 29 17:00:37 2024 +1000 Fix incorrect group member left message commit5773f05a5c
Merge:d35482daba
1cec477020
Author: ThomasSession <thomas.r@getsession.org> Date: Thu Aug 29 15:21:44 2024 +1000 Merge branch 'strings-squashed' of https://github.com/oxen-io/session-android into strings-squashed commitd35482daba
Author: ThomasSession <thomas.r@getsession.org> Date: Thu Aug 29 15:20:13 2024 +1000 More bold fixes and UI tweaks commit78a9ab7159
Author: ThomasSession <thomas.r@getsession.org> Date: Thu Aug 29 14:03:41 2024 +1000 Making sure we bold appropriately commit1cec477020
Author: alansley <aclansley@gmail.com> Date: Thu Aug 29 13:33:50 2024 +1000 Made call to 'getQuantityString' pass the count twice because otherwise it doesn't work correctly commit8e80ab08a9
Author: ThomasSession <thomas.r@getsession.org> Date: Thu Aug 29 13:28:54 2024 +1000 Using the existing implementation commitcb9554ab38
Author: alansley <aclansley@gmail.com> Date: Thu Aug 29 12:32:30 2024 +1000 Merge CrowdIn strings circa 2024-08-29 commitdd57da70f6
Author: alansley <aclansley@gmail.com> Date: Thu Aug 29 09:06:22 2024 +1000 Updated Phrase usage in ConversationAdapter commit34b15d7865
Author: alansley <aclansley@gmail.com> Date: Thu Aug 29 09:03:55 2024 +1000 Converted TransferControlView into Kotlin and updated Phrase usage commita35a7a6a96
Author: alansley <aclansley@gmail.com> Date: Thu Aug 29 08:55:16 2024 +1000 Converted MessageReceipientNotificationBuilder to Kotlin & updated Phrase usage commit6dd93b33f2
Author: alansley <aclansley@gmail.com> Date: Thu Aug 29 08:25:24 2024 +1000 Update MuteDialog, LinkPreviewDialog, and PathActivity commite7dd1c582d
Author: alansley <aclansley@gmail.com> Date: Thu Aug 29 08:16:09 2024 +1000 Updated DisappearingMessages.kt and HelpSettingsActivity.kt commit5bd55ea993
Author: alansley <aclansley@gmail.com> Date: Thu Aug 29 08:01:30 2024 +1000 Converted SwitchPreferenceCompat to Kotlin and fixed the BlockedDialog using the joinCommunity string for some bizarre reason commitd3fb440d05
Author: alansley <aclansley@gmail.com> Date: Thu Aug 29 07:15:03 2024 +1000 Removed R.string.gif and replaced with a string constant commitace58e3493
Author: alansley <aclansley@gmail.com> Date: Thu Aug 29 07:11:53 2024 +1000 getSubbedString correction commit2a8f010369
Merge:ce8efd7def
116bef3c71
Author: alansley <aclansley@gmail.com> Date: Wed Aug 28 16:31:43 2024 +1000 Merge branch 'compose-open-url-dialog' into strings-squashed commitce8efd7def
Author: alansley <aclansley@gmail.com> Date: Wed Aug 28 16:31:11 2024 +1000 WIP commit114066ad5f
Author: alansley <aclansley@gmail.com> Date: Wed Aug 28 15:30:02 2024 +1000 Push before changing over all the Phrase.from to extension method calls commit116bef3c71
Author: ThomasSession <thomas.r@getsession.org> Date: Wed Aug 28 15:25:03 2024 +1000 For safety commit0b1a71a582
Author: ThomasSession <thomas.r@getsession.org> Date: Wed Aug 28 15:23:02 2024 +1000 Cleaning other use of old url dialog commit20abbebf4a
Author: ThomasSession <thomas.r@getsession.org> Date: Wed Aug 28 15:19:46 2024 +1000 Forgot !! commit25132c6342
Author: ThomasSession <thomas.r@getsession.org> Date: Wed Aug 28 15:13:58 2024 +1000 Proper set up for the Open URL dialog commit1f68791da9
Author: alansley <aclansley@gmail.com> Date: Wed Aug 28 14:35:05 2024 +1000 Replaced placeholder text with new string commit8d97f31b4d
Author: alansley <aclansley@gmail.com> Date: Wed Aug 28 14:31:52 2024 +1000 Adjusted comment commitdfebe6f3f9
Author: alansley <aclansley@gmail.com> Date: Wed Aug 28 14:25:23 2024 +1000 Moved block/unblock string selection logic into ViewModel and fixed a comment commit736b5313e6
Author: alansley <aclansley@gmail.com> Date: Wed Aug 28 14:02:54 2024 +1000 Changed toast to warning - although condition to trigger should not be possible commit413bc0be4b
Author: alansley <aclansley@gmail.com> Date: Wed Aug 28 13:55:04 2024 +1000 Adjusted EditGroupMembers to match iOS and fixed up save attachment commentary / logic commitae7164ecbb
Merge:5df981bc7a
d1c4283f42
Author: alansley <aclansley@gmail.com> Date: Wed Aug 28 09:51:58 2024 +1000 Merge branch 'dev' into strings-squashed commit2aa58f4dd6
Author: alansley <aclansley@gmail.com> Date: Wed Aug 28 08:27:03 2024 +1000 WIP compose openURL dialog commit5df981bc7a
Author: alansley <aclansley@gmail.com> Date: Tue Aug 27 15:51:38 2024 +1000 Adjusted NotificationRadioButton that takes string IDs to act as a pass-through commit96453f1f1e
Author: alansley <aclansley@gmail.com> Date: Tue Aug 27 15:42:33 2024 +1000 Added some TODO markers for tomorrow commita402a1be79
Author: alansley <aclansley@gmail.com> Date: Tue Aug 27 15:33:55 2024 +1000 Adjusted Landing page string substitutions to cater for emojis commit4809b5444b
Author: alansley <aclansley@gmail.com> Date: Tue Aug 27 15:12:39 2024 +1000 Removed unused 'isEmpty' utility methods commitb52048a080
Author: alansley <aclansley@gmail.com> Date: Tue Aug 27 14:42:57 2024 +1000 Addressed many aspects of PR feedback + misc. strings issues commit9cdbc4b80b
Author: alansley <aclansley@gmail.com> Date: Tue Aug 27 09:50:51 2024 +1000 Adjusted strings as per Rebecca's 'String Changes' spreadsheet commit4d7e4b9e2c
Merge:3c576053a3
1393335121
Author: alansley <aclansley@gmail.com> Date: Tue Aug 27 08:19:53 2024 +1000 Merge branch 'dev' into strings-squashed commit3c576053a3
Author: alansley <aclansley@gmail.com> Date: Mon Aug 26 17:11:45 2024 +1000 Moved into libsession for ease of access to control message view creation commitb908a54a44
Merge:404fb8001c
bfbe4a8fd2
Author: alansley <aclansley@gmail.com> Date: Mon Aug 26 11:54:09 2024 +1000 Merge branch 'dev' into strings-squashed commit404fb8001c
Author: alansley <aclansley@gmail.com> Date: Mon Aug 26 11:52:41 2024 +1000 Performed a PR pass to fix up anything obvious - there's still a few things left TODO commit53978f818d
Author: Al Lansley <al@oxen.io> Date: Fri Aug 23 14:13:11 2024 +1000 Cleaned up HomeActivityTests.kt commit5f82571bef
Merge:69b8bd7396
8deb21c0c6
Author: Al Lansley <al@oxen.io> Date: Fri Aug 23 08:59:21 2024 +1000 Merge branch 'dev' into strings-squashed commit69b8bd7396
Author: alansley <aclansley@gmail.com> Date: Thu Aug 22 16:20:17 2024 +1000 Added back app_name string so app names properly, fixed API 28 save issue, made some buttons display as red if they should commite3cab9c0d9
Author: alansley <aclansley@gmail.com> Date: Thu Aug 22 14:26:48 2024 +1000 SS-75 Prevented ScrollView vertical scroll bar from fading out commitb0b835092d
Author: alansley <aclansley@gmail.com> Date: Thu Aug 22 14:07:49 2024 +1000 SS-64 Removed all 'Unblocked {name}' toasts as per instructions commitc3c35de408
Merge:efc2ee2824
8e10e1abf4
Author: alansley <aclansley@gmail.com> Date: Thu Aug 22 13:43:00 2024 +1000 Merge branch 'dev' into strings-squashed commitefc2ee2824
Author: alansley <aclansley@gmail.com> Date: Thu Aug 22 13:40:59 2024 +1000 Added some comments about the new CrowdIn strings commit7a03fb37ef
Author: alansley <aclansley@gmail.com> Date: Thu Aug 22 13:08:03 2024 +1000 Initial integration of CrowdIn strings (English only) commit9766c3fd0b
Author: alansley <aclansley@gmail.com> Date: Thu Aug 22 09:55:14 2024 +1000 SS-75 Added 'Copied' toast when the user copies a URL in the Open URL dialog commit59b4805b8b
Author: alansley <aclansley@gmail.com> Date: Thu Aug 22 09:51:01 2024 +1000 SS-75 Prevent 'Are you sure you want to open this URL?' dialog from being excessively tall when given a very long URL commitb7f627f03c
Author: alansley <aclansley@gmail.com> Date: Wed Aug 21 14:54:17 2024 +1000 Made closed group deleting-someone-elses msgs use 'Delete message' or 'Delete Messages' appropriately commit69f6818f99
Author: alansley <aclansley@gmail.com> Date: Wed Aug 21 13:53:58 2024 +1000 Adjusted SS-64 so that all Block / Unblock buttons now use that text and are displayed in red commit2192c2c007
Merge:2338bb47ca
eea54d1a17
Author: alansley <aclansley@gmail.com> Date: Wed Aug 21 13:28:16 2024 +1000 Merge branch 'dev' into strings-squashed commit2338bb47ca
Author: alansley <aclansley@gmail.com> Date: Tue Aug 20 19:11:40 2024 +1000 Converted DefaultMessageNotifier to Kotlin because it needs adjustment & that Java is nasty commit6b29e4d8ce
Author: alansley <aclansley@gmail.com> Date: Tue Aug 20 17:53:27 2024 +1000 Added a note about the plurals for search results commitf7748a0c05
Author: alansley <aclansley@gmail.com> Date: Tue Aug 20 16:06:24 2024 +1000 Corrected text on storage permission dialog commitf6b6256598
Author: alansley <aclansley@gmail.com> Date: Tue Aug 20 14:44:25 2024 +1000 Minor cleanup of BlockedContactsActivity commite3d4870d81
Author: alansley <aclansley@gmail.com> Date: Tue Aug 20 14:41:14 2024 +1000 Addressed changes to fix SS-64 / QA-146 - unblocking contacts modal & toast adjustments commite812527358
Merge:5e02e1ef5c
9919f716a7
Author: alansley <aclansley@gmail.com> Date: Tue Aug 20 13:27:35 2024 +1000 Merge branch 'dev' into strings-squashed commit5e02e1ef5c
Author: alansley <aclansley@gmail.com> Date: Tue Aug 20 09:39:16 2024 +1000 Added 'NonTranslatableStringConstants' file commit816f21bb29
Author: alansley <aclansley@gmail.com> Date: Tue Aug 20 09:30:30 2024 +1000 Addressed commit feedback & removed desktop string 'attachmentsClickToDownload' as we use 'attachmentsTapToDownload' commitacc8d47c68
Author: Al Lansley <al@oxen.io> Date: Mon Aug 19 16:22:08 2024 +1000 SES-1571 Large messages show warning toast commit27ca77d5c4
Merge:27bc90bf1f
f379604c54
Author: Al Lansley <al@oxen.io> Date: Mon Aug 19 11:19:27 2024 +1000 Merge branch 'dev' into strings-squashed commit27bc90bf1f
Author: Al Lansley <al@oxen.io> Date: Mon Aug 19 08:59:38 2024 +1000 Cleaned up some comments and content description commit558684a56d
Merge:90d7064c18
93a28906fb
Author: Al Lansley <al@oxen.io> Date: Mon Aug 19 08:41:47 2024 +1000 Merge branch 'dev' into strings-squashed commit90d7064c18
Author: Al Lansley <al@oxen.io> Date: Thu Aug 15 12:13:30 2024 +1000 Fixed issue where new closed groups would display a timestamp instead of the 'groupNoMessages' text commit51ef0ec81c
Author: Al Lansley <al@oxen.io> Date: Thu Aug 15 09:45:28 2024 +1000 Replaced string 'CreateProfileActivity_profile_photo' with the string 'photo' which has the same text ('Photo') commiteecce08c25
Merge:01009cf521
5a248da445
Author: Al Lansley <al@oxen.io> Date: Thu Aug 15 09:38:10 2024 +1000 Merge branch 'dev' into strings-squashed commit01009cf521
Author: Al Lansley <al@oxen.io> Date: Thu Aug 15 08:37:19 2024 +1000 Changed allowed emoji reactions per minute from 5 (which I used for testing) to 20 (production) commit9441d1e08d
Author: Al Lansley <al@oxen.io> Date: Thu Aug 15 08:34:16 2024 +1000 Refactored emoji rate limiter to use a timestamp mechanism rather than removing queue items after a delay commit6cd6cc3e26
Author: alansley <aclansley@gmail.com> Date: Wed Aug 14 16:48:07 2024 +1000 Adjusted emoji rate limit to 20 reactions per minute to match acceptance criteria commitedd154d8e1
Author: alansley <aclansley@gmail.com> Date: Wed Aug 14 16:02:16 2024 +1000 SS-78 / SES-199 Mechanism required to limit emoji reaction rate commita8ee5c9f3b
Author: alansley <aclansley@gmail.com> Date: Wed Aug 14 14:51:40 2024 +1000 Replaced hard-coded 'Session' with '{app_name}' in 'callsSessionCall' commit621094ebe4
Author: alansley <aclansley@gmail.com> Date: Wed Aug 14 13:40:01 2024 +1000 SS-72 Update save attachment models + add one-time warning that other apps can access saved attachments commit0c83606539
Author: alansley <aclansley@gmail.com> Date: Tue Aug 13 15:50:35 2024 +1000 SS-75 Open URL modal change commit802cf19598
Author: Al Lansley <al@oxen.io> Date: Mon Aug 12 16:42:15 2024 +1000 Open or copy URL WIP commitea84aa1478
Author: Al Lansley <al@oxen.io> Date: Mon Aug 12 14:17:04 2024 +1000 Tied in bandDeleteAll string commit93b8e74f2d
Author: Al Lansley <al@oxen.io> Date: Mon Aug 12 11:34:03 2024 +1000 Job done! All Accessibility ID strings mapped and/or dealt with appropriately! commitfc3b4ad367
Author: Al Lansley <al@oxen.io> Date: Mon Aug 12 09:49:57 2024 +1000 Further AccessibilityId mapping & fixed group members counts to display correct details commit558d6741b1
Author: alansley <aclansley@gmail.com> Date: Fri Aug 9 17:24:44 2024 +1000 End of day push commit73fdb16214
Author: alansley <aclansley@gmail.com> Date: Fri Aug 9 15:57:06 2024 +1000 Localised time strings working - even if the unit tests aren't commit436175d146
Author: alansley <aclansley@gmail.com> Date: Fri Aug 9 13:54:09 2024 +1000 Relative time string WIP commitf309263e39
Merge:45c4118d52
007e705cd9
Author: alansley <aclansley@gmail.com> Date: Fri Aug 9 11:39:13 2024 +1000 Merge dev commit45c4118d52
Author: Al Lansley <al@oxen.io> Date: Thu Aug 8 16:43:02 2024 +1000 Further AccessibilityId mapping WIP commit31bac8e30e
Author: Al Lansley <al@oxen.io> Date: Thu Aug 8 10:53:30 2024 +1000 Further accessibility ID changes & removed fragment_new_conversation_home.xml commit9c2111e66e
Author: alansley <aclansley@gmail.com> Date: Wed Aug 7 13:13:52 2024 +1000 AccessibilityId WIP commit1e9eeff86a
Author: alansley <aclansley@gmail.com> Date: Wed Aug 7 11:06:39 2024 +1000 AccessibilityId adjustments & removed some unused XML layouts commite5fd2c8cc0
Author: alansley <aclansley@gmail.com> Date: Wed Aug 7 09:22:14 2024 +1000 AccessibilityId refactor WIP commit399796bac3
Author: alansley <aclansley@gmail.com> Date: Tue Aug 6 15:51:53 2024 +1000 AccessibilityId WIP - up to AccessibilityId_reveal_recovery_phrase_button commita8d72dfcc0
Author: alansley <aclansley@gmail.com> Date: Tue Aug 6 14:12:10 2024 +1000 Cleaned up a few comments and fixed some plurals logic commitbe400d8f4f
Author: alansley <aclansley@gmail.com> Date: Tue Aug 6 11:32:08 2024 +1000 Removed commented out merge conflict marker commit5cbe289a8d
Merge:5fe123e7b5
d6c5ab2b18
Author: alansley <aclansley@gmail.com> Date: Tue Aug 6 11:30:50 2024 +1000 Merge dev and cleanup commit5fe123e7b5
Author: Al Lansley <al@oxen.io> Date: Mon Aug 5 14:37:47 2024 +1000 Adjusted sending of mms messages to show 'Uploading' rather than 'Sending' as per SES-1721 commitd3f8e928b6
Merge:00552930e6
cd1a0643e3
Author: Al Lansley <al@oxen.io> Date: Mon Aug 5 13:30:03 2024 +1000 Merge branch 'dev' into strings-squashed commit00552930e6
Author: Al Lansley <al@oxen.io> Date: Mon Aug 5 13:28:55 2024 +1000 Removed unused helpReportABugDesktop strings commit6c0450b487
Author: Al Lansley <al@oxen.io> Date: Mon Aug 5 12:59:15 2024 +1000 Renamed 'quitButton' string to just 'quit' commit284c485903
Author: Al Lansley <al@oxen.io> Date: Mon Aug 5 12:00:35 2024 +1000 Replaced 'screenSecurity' with 'screenshotNotifications' as the title of the notifications toggle commit6948d64fa8
Author: Al Lansley <al@oxen.io> Date: Mon Aug 5 10:45:05 2024 +1000 WIP commitbc94cb78db
Author: alansley <aclansley@gmail.com> Date: Fri Aug 2 16:21:16 2024 +1000 End of day push commit1a2df3798a
Merge:c7fdb6aed9
a56e1d0b91
Author: alansley <aclansley@gmail.com> Date: Fri Aug 2 15:20:19 2024 +1000 Merged dev commitc7fdb6aed9
Author: alansley <aclansley@gmail.com> Date: Fri Aug 2 14:21:11 2024 +1000 Replaced string 'dialog_disappearing_messages_follow_setting_confirm' with 'confirm' commit2992d590d9
Author: alansley <aclansley@gmail.com> Date: Fri Aug 2 14:01:00 2024 +1000 Removed string 'attachment_type_selector__gallery' and associated / un-used 'attachment_type_selector.xml' layout commit4218663c95
Author: alansley <aclansley@gmail.com> Date: Fri Aug 2 13:39:54 2024 +1000 Removed 'message_details_header__disappears' and the unused 'activity_message_detail.xml' which was the only reference to it commitba2d0275e4
Author: alansley <aclansley@gmail.com> Date: Fri Aug 2 12:15:42 2024 +1000 Implemented task SS-79 to only provide a save attachment menu option when the attachment download is complete commit20662c8222
Merge:608c984a6b
fbbef4898a
Author: alansley <aclansley@gmail.com> Date: Wed Jul 31 13:08:04 2024 +1000 Merge branch 'dev' into strings-squashed commit608c984a6b
Author: alansley <aclansley@gmail.com> Date: Tue Jul 30 16:58:08 2024 +1000 Actually remove the 4 specific time period mute strings commit006a4e8bad
Author: alansley <aclansley@gmail.com> Date: Tue Jul 30 16:43:54 2024 +1000 Cleaned up MuteDialog.kt commitd3177f9f1a
Author: alansley <aclansley@gmail.com> Date: Tue Jul 30 16:27:06 2024 +1000 Added a 1 second kludge to the mute for subtitle so that it initially shows 1 hour not 59 minutes etc. commitd568a86649
Author: alansley <aclansley@gmail.com> Date: Tue Jul 30 16:20:20 2024 +1000 Removed 'Muted for' strings and fixed it up to use 'Mute for {large_time_unit}' across the board commit84f6f19cf4
Author: alansley <aclansley@gmail.com> Date: Tue Jul 30 11:03:46 2024 +1000 Changed some hard-coded 'Session' text in strings and renamed another commitbc90d18c91
Author: alansley <aclansley@gmail.com> Date: Tue Jul 30 10:27:55 2024 +1000 Cleaned up a leftover plural & changed 'app_name' to use 'sessionMessenger' string commit79cd87878c
Merge:3b62e474b3
dec02cef5a
Author: alansley <aclansley@gmail.com> Date: Tue Jul 30 08:16:02 2024 +1000 Merge branch 'dev' into strings-squashed commit3b62e474b3
Author: Al Lansley <al@oxen.io> Date: Mon Jul 29 16:33:21 2024 +1000 Down to just the final few straggler strings commit13e81f046b
Author: Al Lansley <al@oxen.io> Date: Mon Jul 29 13:13:54 2024 +1000 WIP commit2d9961d5c0
Author: Al Lansley <al@oxen.io> Date: Mon Jul 29 08:58:01 2024 +1000 Further cleanup of stragglers commit08b8a84309
Author: Al Lansley <al@oxen.io> Date: Mon Jul 29 08:29:12 2024 +1000 Cleaning up straggler strings commitd0e87c64b5
Author: alansley <aclansley@gmail.com> Date: Fri Jul 26 17:07:46 2024 +1000 WIP commit4bc9d09be2
Author: alansley <aclansley@gmail.com> Date: Fri Jul 26 16:30:28 2024 +1000 WIP commit3cee4bc12f
Merge:aa1db13e3a
a495ec232a
Author: alansley <aclansley@gmail.com> Date: Fri Jul 26 13:57:09 2024 +1000 Removed some legacy strings & substituted others commitaa1db13e3a
Author: fanchao <git@fanchao.dev> Date: Fri Jul 26 11:34:05 2024 +1000 Initial squash merge for strings
This commit is contained in:
@@ -30,11 +30,11 @@ android {
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
jvmTarget = '11'
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2,14 +2,32 @@ package network.loki.messenger.libsession_util
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import network.loki.messenger.libsession_util.util.*
|
||||
import network.loki.messenger.libsession_util.util.BaseCommunityInfo
|
||||
import network.loki.messenger.libsession_util.util.Contact
|
||||
import network.loki.messenger.libsession_util.util.Conversation
|
||||
import network.loki.messenger.libsession_util.util.ExpiryMode
|
||||
import network.loki.messenger.libsession_util.util.GroupMember
|
||||
import network.loki.messenger.libsession_util.util.KeyPair
|
||||
import network.loki.messenger.libsession_util.util.Sodium
|
||||
import network.loki.messenger.libsession_util.util.UserPic
|
||||
import org.hamcrest.CoreMatchers.equalTo
|
||||
import org.hamcrest.CoreMatchers.hasItem
|
||||
import org.hamcrest.CoreMatchers.not
|
||||
import org.hamcrest.CoreMatchers.notNullValue
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Assert.assertArrayEquals
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNotEquals
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.session.libsignal.utilities.Hex
|
||||
import org.session.libsignal.utilities.IdPrefix
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.AccountId
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
@@ -21,12 +39,19 @@ class InstrumentedTests {
|
||||
|
||||
val seed =
|
||||
Hex.fromStringCondensed("0123456789abcdef0123456789abcdef00000000000000000000000000000000")
|
||||
val groupSeed =
|
||||
Hex.fromStringCondensed("0123456789abcdef0123456789abcdef11111111111111111111111111111111")
|
||||
|
||||
private val keyPair: KeyPair
|
||||
get() {
|
||||
return Sodium.ed25519KeyPair(seed)
|
||||
}
|
||||
|
||||
private val groupKeyPair: KeyPair
|
||||
get() {
|
||||
return Sodium.ed25519KeyPair(groupSeed)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
@@ -64,6 +89,37 @@ class InstrumentedTests {
|
||||
assertTrue(contacts.dirty())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_multi_encrypt() {
|
||||
val user = keyPair
|
||||
val xUserKey = Sodium.ed25519PkToCurve25519(user.pubKey)
|
||||
val groupKey = groupKeyPair
|
||||
val xGroupKey = Sodium.ed25519PkToCurve25519(groupKey.pubKey)
|
||||
|
||||
val test = "test"
|
||||
|
||||
val encoded = Sodium.encryptForMultipleSimple(arrayOf(test.encodeToByteArray()), arrayOf(xUserKey), groupKey.secretKey, "test")!!
|
||||
val decoded = Sodium.decryptForMultipleSimple(encoded, user.secretKey, xGroupKey, "test")
|
||||
assertEquals(test, decoded?.decodeToString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_multi_encrypt_from_user_groups() {
|
||||
val user = keyPair
|
||||
val xUserKey = Sodium.ed25519PkToCurve25519(user.pubKey)
|
||||
val groups = UserGroupsConfig.newInstance(user.secretKey)
|
||||
val group = groups.createGroup()
|
||||
val groupSk = group.adminKey!!
|
||||
val groupPub = group.groupAccountId.pubKeyBytes
|
||||
val groupXPub = Sodium.ed25519PkToCurve25519(groupPub)
|
||||
|
||||
val test = "test"
|
||||
|
||||
val encoded = Sodium.encryptForMultipleSimple(arrayOf(test.encodeToByteArray()), arrayOf(xUserKey), groupSk, "test")!!
|
||||
val decoded = Sodium.decryptForMultipleSimple(encoded, user.secretKey, groupXPub, "test")
|
||||
assertEquals(test, decoded?.decodeToString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun jni_contacts() {
|
||||
val contacts = Contacts.newInstance(keyPair.secretKey)
|
||||
@@ -261,7 +317,8 @@ class InstrumentedTests {
|
||||
val newConf = UserProfile.newInstance(edSk)
|
||||
|
||||
val accepted = newConf.merge("fakehash1" to newToPush)
|
||||
assertEquals(1, accepted)
|
||||
assertThat(accepted, hasItem("fakehash1"))
|
||||
assertThat(accepted.size, equalTo(1))
|
||||
|
||||
assertTrue(newConf.needsDump())
|
||||
assertFalse(newConf.needsPush())
|
||||
@@ -551,6 +608,7 @@ class InstrumentedTests {
|
||||
is Conversation.OneToOne -> seen.add("1-to-1: ${convo.accountId}")
|
||||
is Conversation.Community -> seen.add("og: ${convo.baseCommunityInfo.baseUrl}/r/${convo.baseCommunityInfo.room}")
|
||||
is Conversation.LegacyGroup -> seen.add("cl: ${convo.groupId}")
|
||||
is Conversation.ClosedGroup -> TODO()
|
||||
null -> { /* ignore null cases */ }
|
||||
}
|
||||
}
|
||||
@@ -582,4 +640,179 @@ class InstrumentedTests {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGroupInfo() {
|
||||
val (groupPublic, groupSecret) = groupKeyPair
|
||||
val (userPublic, userSecret) = keyPair
|
||||
val userCurve = Sodium.ed25519PkToCurve25519(userPublic)
|
||||
val infoConf = GroupInfoConfig.newInstance(groupPublic, groupSecret)
|
||||
infoConf.setName("New Group")
|
||||
assertEquals("New Group", infoConf.getName())
|
||||
infoConf.setCreated(System.currentTimeMillis())
|
||||
assertThat(infoConf.getCreated(), notNullValue())
|
||||
val memberConf = GroupMembersConfig.newInstance(groupPublic, groupSecret)
|
||||
memberConf.set(
|
||||
GroupMember(
|
||||
sessionId = "05"+Hex.toStringCondensed(userCurve),
|
||||
name = "User",
|
||||
admin = true
|
||||
)
|
||||
)
|
||||
val keys = GroupKeysConfig.newInstance(
|
||||
userSecretKey = userSecret,
|
||||
groupPublicKey = groupPublic,
|
||||
groupSecretKey = groupSecret,
|
||||
info = infoConf,
|
||||
members = memberConf
|
||||
)
|
||||
assertThat(keys.pendingKey(), notNullValue())
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGroupInfoOtherWay() {
|
||||
val (userPublic, userSecret) = keyPair
|
||||
val userCurve = Sodium.ed25519PkToCurve25519(userPublic)
|
||||
val groupConfig = UserGroupsConfig.newInstance(userSecret)
|
||||
val group = groupConfig.createGroup()
|
||||
val groupSecret = checkNotNull(group.adminKey) {
|
||||
"adminKey must exist for created group"
|
||||
}
|
||||
val groupPublic = Hex.fromStringCondensed(group.groupAccountId.publicKey)
|
||||
groupConfig.set(group)
|
||||
val setGroup = groupConfig.getClosedGroup(group.groupAccountId.hexString)
|
||||
assertThat(setGroup, notNullValue())
|
||||
assertTrue(setGroup?.adminKey?.isNotEmpty() == true)
|
||||
val infoConf = GroupInfoConfig.newInstance(groupPublic, group.adminKey)
|
||||
infoConf.setName("New Group")
|
||||
assertEquals("New Group", infoConf.getName())
|
||||
infoConf.setCreated(System.currentTimeMillis())
|
||||
assertThat(infoConf.getCreated(), notNullValue())
|
||||
val memberConf = GroupMembersConfig.newInstance(groupPublic, groupSecret)
|
||||
memberConf.set(
|
||||
GroupMember(
|
||||
sessionId = "05"+Hex.toStringCondensed(userCurve),
|
||||
name = "User",
|
||||
admin = true
|
||||
)
|
||||
)
|
||||
val keys = GroupKeysConfig.newInstance(
|
||||
userSecretKey = userSecret,
|
||||
groupPublicKey = groupPublic,
|
||||
groupSecretKey = groupSecret,
|
||||
info = infoConf,
|
||||
members = memberConf
|
||||
)
|
||||
assertThat(keys.pendingKey(), notNullValue())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGroupMembership() {
|
||||
val (userPublic, userSecret) = keyPair
|
||||
val userSessionId = AccountId(IdPrefix.STANDARD, Sodium.ed25519PkToCurve25519(userPublic))
|
||||
val groupConfig = UserGroupsConfig.newInstance(userSecret)
|
||||
val group = groupConfig.createGroup()
|
||||
groupConfig.set(group)
|
||||
val groupMembersConfig = GroupMembersConfig.newInstance(
|
||||
group.groupAccountId.pubKeyBytes,
|
||||
checkNotNull(group.adminKey) {
|
||||
"signing key must exist for the group"
|
||||
}
|
||||
)
|
||||
val toAdd = GroupMember(userSessionId.hexString, "user", admin = true)
|
||||
groupMembersConfig.set(
|
||||
toAdd
|
||||
)
|
||||
assertThat(groupMembersConfig.all().size, equalTo(1))
|
||||
assertThat(groupMembersConfig.all(), hasItem(toAdd))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNewGroupExists() {
|
||||
val (_, userSecret) = keyPair
|
||||
val groupConfig = UserGroupsConfig.newInstance(userSecret)
|
||||
val group = groupConfig.createGroup()
|
||||
groupConfig.set(group)
|
||||
val allClosedGroups = groupConfig.all()
|
||||
assertThat(allClosedGroups.size, equalTo(1))
|
||||
assertTrue(groupConfig.needsPush())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNewGroupInfo() {
|
||||
val (_, userSecret) = keyPair
|
||||
val groupConfig = UserGroupsConfig.newInstance(userSecret)
|
||||
val group = groupConfig.createGroup()
|
||||
groupConfig.set(group)
|
||||
val groupInfo = GroupInfoConfig.newInstance(group.groupAccountId.pubKeyBytes, group.adminKey)
|
||||
groupInfo.setName("Test Group")
|
||||
groupInfo.setDescription("This is a test group")
|
||||
assertThat(groupInfo.getName(), equalTo("Test Group"))
|
||||
assertThat(groupInfo.getDescription(), equalTo("This is a test group"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGroupKeyConfig() {
|
||||
val (userPubKey, userSecret) = keyPair
|
||||
val groupConfig = UserGroupsConfig.newInstance(userSecret)
|
||||
val group = groupConfig.createGroup()
|
||||
groupConfig.set(group)
|
||||
val groupInfo = GroupInfoConfig.newInstance(group.groupAccountId.pubKeyBytes, group.adminKey)
|
||||
groupInfo.setName("test")
|
||||
val groupMembers = GroupMembersConfig.newInstance(group.groupAccountId.pubKeyBytes, group.adminKey)
|
||||
groupMembers.set(
|
||||
GroupMember(
|
||||
sessionId = AccountId(IdPrefix.STANDARD, Sodium.ed25519PkToCurve25519(userPubKey)).hexString,
|
||||
name = "admin",
|
||||
admin = true
|
||||
)
|
||||
)
|
||||
val membersDump = groupMembers.dump()
|
||||
val infoDump = groupInfo.dump()
|
||||
|
||||
val ourKeyConfig = GroupKeysConfig.newInstance(
|
||||
userSecretKey = userSecret,
|
||||
groupPublicKey = group.groupAccountId.pubKeyBytes,
|
||||
groupSecretKey = group.adminKey,
|
||||
info = groupInfo,
|
||||
members = groupMembers
|
||||
)
|
||||
|
||||
assertThat(ourKeyConfig.needsRekey(), equalTo(false))
|
||||
val pushed = ourKeyConfig.pendingConfig()!!
|
||||
val messageTimestamp = System.currentTimeMillis()
|
||||
ourKeyConfig.loadKey(pushed, "testabc", messageTimestamp, groupInfo, groupMembers)
|
||||
assertThat(ourKeyConfig.needsDump(), equalTo(true))
|
||||
ourKeyConfig.dump()
|
||||
assertThat(ourKeyConfig.needsRekey(), equalTo(false))
|
||||
val mergeInfo = GroupInfoConfig.newInstance(group.groupAccountId.pubKeyBytes, group.adminKey, infoDump)
|
||||
val mergeMembers = GroupMembersConfig.newInstance(group.groupAccountId.pubKeyBytes, group.adminKey, membersDump)
|
||||
val mergeConfig = GroupKeysConfig.newInstance(userSecret, group.groupAccountId.pubKeyBytes, group.adminKey, info = mergeInfo, members = mergeMembers)
|
||||
mergeConfig.loadKey(pushed, "testabc", messageTimestamp, mergeInfo, mergeMembers)
|
||||
assertThat(mergeConfig.needsRekey(), equalTo(false))
|
||||
assertThat(mergeConfig.keys().size, equalTo(1))
|
||||
assertThat(ourKeyConfig.keys().size, equalTo(1))
|
||||
assertThat(mergeConfig.keys().first(), equalTo(ourKeyConfig.keys().first()))
|
||||
assertThat(ourKeyConfig.groupKeys().size, equalTo(1))
|
||||
assertThat(mergeConfig.groupKeys().size, equalTo(1))
|
||||
assertThat(ourKeyConfig.groupKeys().first(), equalTo(mergeConfig.groupKeys().first()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testConvoVolatileSetAndGet() {
|
||||
val (userPubKey, userSecret) = keyPair
|
||||
val groupConfig = UserGroupsConfig.newInstance(userSecret)
|
||||
val group = groupConfig.createGroup()
|
||||
groupConfig.set(group)
|
||||
val volatiles = ConversationVolatileConfig.newInstance(userSecret)
|
||||
val conversation = Conversation.ClosedGroup(
|
||||
group.groupAccountId.hexString,
|
||||
System.currentTimeMillis(),
|
||||
false
|
||||
)
|
||||
volatiles.set(conversation)
|
||||
assertThat(volatiles.all().size, equalTo(1))
|
||||
assertThat(volatiles.allClosedGroups().size, equalTo(1))
|
||||
}
|
||||
|
||||
}
|
@@ -31,7 +31,10 @@ set(SOURCES
|
||||
contacts.cpp
|
||||
conversation.cpp
|
||||
blinded_key.cpp
|
||||
util.cpp)
|
||||
util.cpp
|
||||
group_members.cpp
|
||||
group_keys.cpp
|
||||
group_info.cpp)
|
||||
|
||||
add_library( # Sets the name of the library.
|
||||
session_util
|
||||
@@ -48,7 +51,6 @@ add_library( # Sets the name of the library.
|
||||
|
||||
find_library( # Sets the name of the path variable.
|
||||
log-lib
|
||||
|
||||
# Specifies the name of the NDK library that
|
||||
# you want CMake to locate.
|
||||
log)
|
||||
|
@@ -25,4 +25,10 @@ inline std::pair<std::string, session::ustring> extractHashAndData(JNIEnv *env,
|
||||
return ret_pair;
|
||||
}
|
||||
|
||||
inline session::config::ConfigSig* ptrToConfigSig(JNIEnv* env, jobject obj) {
|
||||
jclass sigClass = env->FindClass("network/loki/messenger/libsession_util/ConfigSig");
|
||||
jfieldID pointerField = env->GetFieldID(sigClass, "pointer", "J");
|
||||
return (session::config::ConfigSig*) env->GetLongField(obj, pointerField);
|
||||
}
|
||||
|
||||
#endif
|
@@ -13,7 +13,7 @@ inline session::config::Contacts *ptrToContacts(JNIEnv *env, jobject obj) {
|
||||
|
||||
inline jobject serialize_contact(JNIEnv *env, session::config::contact_info info) {
|
||||
jclass contactClass = env->FindClass("network/loki/messenger/libsession_util/util/Contact");
|
||||
jmethodID constructor = env->GetMethodID(contactClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZLnetwork/loki/messenger/libsession_util/util/UserPic;ILnetwork/loki/messenger/libsession_util/util/ExpiryMode;)V");
|
||||
jmethodID constructor = env->GetMethodID(contactClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZLnetwork/loki/messenger/libsession_util/util/UserPic;JLnetwork/loki/messenger/libsession_util/util/ExpiryMode;)V");
|
||||
jstring id = env->NewStringUTF(info.session_id.data());
|
||||
jstring name = env->NewStringUTF(info.name.data());
|
||||
jstring nickname = env->NewStringUTF(info.nickname.data());
|
||||
@@ -24,7 +24,7 @@ inline jobject serialize_contact(JNIEnv *env, session::config::contact_info info
|
||||
auto created = info.created;
|
||||
jobject profilePic = util::serialize_user_pic(env, info.profile_picture);
|
||||
jobject returnObj = env->NewObject(contactClass, constructor, id, name, nickname, approved,
|
||||
approvedMe, blocked, profilePic, info.priority,
|
||||
approvedMe, blocked, profilePic, (jlong)info.priority,
|
||||
util::serialize_expiry(env, info.exp_mode, info.exp_timer));
|
||||
return returnObj;
|
||||
}
|
||||
@@ -41,14 +41,14 @@ inline session::config::contact_info deserialize_contact(JNIEnv *env, jobject in
|
||||
getBlocked = env->GetFieldID(contactClass, "blocked", "Z");
|
||||
getUserPic = env->GetFieldID(contactClass, "profilePicture",
|
||||
"Lnetwork/loki/messenger/libsession_util/util/UserPic;");
|
||||
getPriority = env->GetFieldID(contactClass, "priority", "I");
|
||||
getPriority = env->GetFieldID(contactClass, "priority", "J");
|
||||
getExpiry = env->GetFieldID(contactClass, "expiryMode", "Lnetwork/loki/messenger/libsession_util/util/ExpiryMode;");
|
||||
jstring name, nickname, account_id;
|
||||
account_id = static_cast<jstring>(env->GetObjectField(info, getId));
|
||||
name = static_cast<jstring>(env->GetObjectField(info, getName));
|
||||
nickname = static_cast<jstring>(env->GetObjectField(info, getNick));
|
||||
bool approved, approvedMe, blocked, hidden;
|
||||
int priority = env->GetIntField(info, getPriority);
|
||||
int priority = env->GetLongField(info, getPriority);
|
||||
approved = env->GetBooleanField(info, getApproved);
|
||||
approvedMe = env->GetBooleanField(info, getApprovedMe);
|
||||
blocked = env->GetBooleanField(info, getBlocked);
|
||||
|
@@ -109,6 +109,7 @@ Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_set(JNIE
|
||||
jclass one_to_one = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$OneToOne");
|
||||
jclass open_group = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$Community");
|
||||
jclass legacy_closed_group = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$LegacyGroup");
|
||||
jclass closed_group = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$ClosedGroup");
|
||||
|
||||
jclass to_store_class = env->GetObjectClass(to_store);
|
||||
if (env->IsSameObject(to_store_class, one_to_one)) {
|
||||
@@ -120,6 +121,9 @@ Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_set(JNIE
|
||||
} else if (env->IsSameObject(to_store_class,legacy_closed_group)) {
|
||||
// store as legacy_closed_group
|
||||
convos->set(deserialize_legacy_closed_group(env, to_store, convos));
|
||||
} else if (env->IsSameObject(to_store_class, closed_group)) {
|
||||
// store as new closed group
|
||||
convos->set(deserialize_closed_group(env, to_store, convos));
|
||||
}
|
||||
}
|
||||
extern "C"
|
||||
@@ -349,4 +353,57 @@ Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_allLegac
|
||||
for (auto contact = convos->begin_legacy_groups(); contact != convos->end(); ++contact)
|
||||
env->CallObjectMethod(our_stack, push, serialize_legacy_group(env, *contact));
|
||||
return our_stack;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_allClosedGroups(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
jclass stack = env->FindClass("java/util/Stack");
|
||||
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
|
||||
jobject our_stack = env->NewObject(stack, init);
|
||||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
for (auto contact = convos->begin_groups(); contact != convos->end(); ++contact)
|
||||
env->CallObjectMethod(our_stack, push, serialize_closed_group(env, *contact));
|
||||
return our_stack;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getClosedGroup(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring session_id) {
|
||||
auto config = ptrToConvoInfo(env, thiz);
|
||||
auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr);
|
||||
auto group = config->get_group(session_id_bytes);
|
||||
env->ReleaseStringUTFChars(session_id, session_id_bytes);
|
||||
if (group) {
|
||||
auto serialized = serialize_closed_group(env, *group);
|
||||
return serialized;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getOrConstructClosedGroup(
|
||||
JNIEnv *env, jobject thiz, jstring session_id) {
|
||||
auto config = ptrToConvoInfo(env, thiz);
|
||||
auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr);
|
||||
auto group = config->get_or_construct_group(session_id_bytes);
|
||||
env->ReleaseStringUTFChars(session_id, session_id_bytes);
|
||||
return serialize_closed_group(env, group);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_eraseClosedGroup(
|
||||
JNIEnv *env, jobject thiz, jstring session_id) {
|
||||
auto config = ptrToConvoInfo(env, thiz);
|
||||
auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr);
|
||||
auto erased = config->erase_group(session_id_bytes);
|
||||
env->ReleaseStringUTFChars(session_id, session_id_bytes);
|
||||
return erased;
|
||||
}
|
@@ -2,6 +2,7 @@
|
||||
#define SESSION_ANDROID_CONVERSATION_H
|
||||
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include "util.h"
|
||||
#include "session/config/convo_info_volatile.hpp"
|
||||
|
||||
@@ -42,13 +43,25 @@ inline jobject serialize_legacy_group(JNIEnv *env, session::config::convo::legac
|
||||
return serialized;
|
||||
}
|
||||
|
||||
inline jobject serialize_closed_group(JNIEnv* env, session::config::convo::group group) {
|
||||
jclass clazz = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$ClosedGroup");
|
||||
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;JZ)V");
|
||||
auto session_id = env->NewStringUTF(group.id.data());
|
||||
auto last_read = group.last_read;
|
||||
auto unread = group.unread;
|
||||
return env->NewObject(clazz, constructor, session_id, last_read, unread);
|
||||
}
|
||||
|
||||
inline jobject serialize_any(JNIEnv *env, session::config::convo::any any) {
|
||||
__android_log_print(ANDROID_LOG_WARN, "DESERIALIE", "deserializing any");
|
||||
if (auto* dm = std::get_if<session::config::convo::one_to_one>(&any)) {
|
||||
return serialize_one_to_one(env, *dm);
|
||||
} else if (auto* og = std::get_if<session::config::convo::community>(&any)) {
|
||||
return serialize_open_group(env, *og);
|
||||
} else if (auto* lgc = std::get_if<session::config::convo::legacy_group>(&any)) {
|
||||
return serialize_legacy_group(env, *lgc);
|
||||
} else if (auto* gc = std::get_if<session::config::convo::group>(&any)) {
|
||||
return serialize_closed_group(env, *gc);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -104,10 +117,30 @@ inline session::config::convo::legacy_group deserialize_legacy_closed_group(JNIE
|
||||
return deserialized;
|
||||
}
|
||||
|
||||
inline session::config::convo::group deserialize_closed_group(JNIEnv* env, jobject info, session::config::ConvoInfoVolatile* conf) {
|
||||
auto clazz = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$ClosedGroup");
|
||||
auto id_getter = env->GetFieldID(clazz, "accountId", "Ljava/lang/String;");
|
||||
auto last_read_getter = env->GetFieldID(clazz, "lastRead", "J");
|
||||
auto unread_getter = env->GetFieldID(clazz, "unread", "Z");
|
||||
auto session_id = (jstring)env->GetObjectField(info, id_getter);
|
||||
auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr);
|
||||
auto last_read = env->GetLongField(info, last_read_getter);
|
||||
auto unread = env->GetBooleanField(info, unread_getter);
|
||||
|
||||
auto group = conf->get_or_construct_group(session_id_bytes);
|
||||
group.last_read = last_read;
|
||||
group.unread = unread;
|
||||
|
||||
env->ReleaseStringUTFChars(session_id, session_id_bytes);
|
||||
return group;
|
||||
}
|
||||
|
||||
inline std::optional<session::config::convo::any> deserialize_any(JNIEnv *env, jobject convo, session::config::ConvoInfoVolatile *conf) {
|
||||
auto oto_class = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$OneToOne");
|
||||
auto og_class = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$Community");
|
||||
auto lgc_class = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$LegacyGroup");
|
||||
auto gc_class = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$ClosedGroup");
|
||||
|
||||
auto object_class = env->GetObjectClass(convo);
|
||||
if (env->IsSameObject(object_class, oto_class)) {
|
||||
return session::config::convo::any{deserialize_one_to_one(env, convo, conf)};
|
||||
@@ -115,6 +148,8 @@ inline std::optional<session::config::convo::any> deserialize_any(JNIEnv *env, j
|
||||
return session::config::convo::any{deserialize_community(env, convo, conf)};
|
||||
} else if (env->IsSameObject(object_class, lgc_class)) {
|
||||
return session::config::convo::any{deserialize_legacy_closed_group(env, convo, conf)};
|
||||
} else if (env->IsSameObject(object_class, gc_class)) {
|
||||
return session::config::convo::any{deserialize_closed_group(env, convo, conf)};
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
213
libsession-util/src/main/cpp/group_info.cpp
Normal file
213
libsession-util/src/main/cpp/group_info.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
#include <jni.h>
|
||||
#include "group_info.h"
|
||||
#include "session/config/groups/info.hpp"
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_00024Companion_newInstance(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jbyteArray pub_key,
|
||||
jbyteArray secret_key,
|
||||
jbyteArray initial_dump) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
std::optional<session::ustring> secret_key_optional{std::nullopt};
|
||||
std::optional<session::ustring> initial_dump_optional{std::nullopt};
|
||||
auto pub_key_bytes = util::ustring_from_bytes(env, pub_key);
|
||||
if (secret_key && env->GetArrayLength(secret_key) > 0) {
|
||||
auto secret_key_bytes = util::ustring_from_bytes(env, secret_key);
|
||||
secret_key_optional = secret_key_bytes;
|
||||
}
|
||||
if (env->GetArrayLength(initial_dump) > 0) {
|
||||
auto initial_dump_bytes = util::ustring_from_bytes(env, initial_dump);
|
||||
initial_dump_optional = initial_dump_bytes;
|
||||
}
|
||||
|
||||
auto* group_info = new session::config::groups::Info(pub_key_bytes, secret_key_optional, initial_dump_optional);
|
||||
|
||||
jclass groupInfoClass = env->FindClass("network/loki/messenger/libsession_util/GroupInfoConfig");
|
||||
jmethodID constructor = env->GetMethodID(groupInfoClass, "<init>", "(J)V");
|
||||
jobject newConfig = env->NewObject(groupInfoClass, constructor, reinterpret_cast<jlong>(group_info));
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_destroyGroup(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
group_info->destroy_group();
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_getCreated(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
return util::jlongFromOptional(env, group_info->get_created());
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_getDeleteAttachmentsBefore(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
return util::jlongFromOptional(env, group_info->get_delete_attach_before());
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_getDeleteBefore(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
return util::jlongFromOptional(env, group_info->get_delete_before());
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_getExpiryTimer(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
auto timer = group_info->get_expiry_timer();
|
||||
if (!timer) {
|
||||
return 0;
|
||||
}
|
||||
long long in_seconds = timer->count();
|
||||
return in_seconds;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_getName(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
return util::jstringFromOptional(env, group_info->get_name());
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_getProfilePic(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
return util::serialize_user_pic(env, group_info->get_profile_pic());
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_isDestroyed(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
return group_info->is_destroyed();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_setCreated(JNIEnv *env, jobject thiz,
|
||||
jlong created_at) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
group_info->set_created(created_at);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_setDeleteAttachmentsBefore(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jlong delete_before) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
group_info->set_delete_attach_before(delete_before);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_setDeleteBefore(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jlong delete_before) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
group_info->set_delete_before(delete_before);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_setExpiryTimer(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jlong expire_seconds) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
group_info->set_expiry_timer(std::chrono::seconds{expire_seconds});
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_setName(JNIEnv *env, jobject thiz,
|
||||
jstring new_name) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
auto bytes = env->GetStringUTFChars(new_name, nullptr);
|
||||
group_info->set_name(bytes);
|
||||
env->ReleaseStringUTFChars(new_name, bytes);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_setProfilePic(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jobject new_profile_pic) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
auto user_pic = util::deserialize_user_pic(env, new_profile_pic);
|
||||
auto url = env->GetStringUTFChars(user_pic.first, nullptr);
|
||||
auto key = util::ustring_from_bytes(env, user_pic.second);
|
||||
group_info->set_profile_pic(url, key);
|
||||
env->ReleaseStringUTFChars(user_pic.first, url);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_storageNamespace(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
return static_cast<jlong>(group_info->storage_namespace());
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_id(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
return util::serialize_account_id(env, group_info->id);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_getDescription(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
auto description = group_info->get_description();
|
||||
if (!description) {
|
||||
return nullptr;
|
||||
}
|
||||
auto jstring = env->NewStringUTF(description->data());
|
||||
return jstring;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupInfoConfig_setDescription(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring new_description) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto group_info = ptrToInfo(env, thiz);
|
||||
auto description = env->GetStringUTFChars(new_description, nullptr);
|
||||
group_info->set_description(description);
|
||||
env->ReleaseStringUTFChars(new_description, description);
|
||||
}
|
12
libsession-util/src/main/cpp/group_info.h
Normal file
12
libsession-util/src/main/cpp/group_info.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef SESSION_ANDROID_GROUP_INFO_H
|
||||
#define SESSION_ANDROID_GROUP_INFO_H
|
||||
|
||||
#include "util.h"
|
||||
|
||||
inline session::config::groups::Info* ptrToInfo(JNIEnv* env, jobject obj) {
|
||||
jclass configClass = env->FindClass("network/loki/messenger/libsession_util/GroupInfoConfig");
|
||||
jfieldID pointerField = env->GetFieldID(configClass, "pointer", "J");
|
||||
return (session::config::groups::Info*) env->GetLongField(obj, pointerField);
|
||||
}
|
||||
|
||||
#endif //SESSION_ANDROID_GROUP_INFO_H
|
300
libsession-util/src/main/cpp/group_keys.cpp
Normal file
300
libsession-util/src/main/cpp/group_keys.cpp
Normal file
@@ -0,0 +1,300 @@
|
||||
#include "group_keys.h"
|
||||
#include "group_info.h"
|
||||
#include "group_members.h"
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_00024Companion_storageNamespace(JNIEnv* env,
|
||||
jobject thiz) {
|
||||
return (jint)session::config::Namespace::GroupKeys;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_00024Companion_newInstance(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jbyteArray user_secret_key,
|
||||
jbyteArray group_public_key,
|
||||
jbyteArray group_secret_key,
|
||||
jbyteArray initial_dump,
|
||||
jobject info_jobject,
|
||||
jobject members_jobject) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto user_key_bytes = util::ustring_from_bytes(env, user_secret_key);
|
||||
auto pub_key_bytes = util::ustring_from_bytes(env, group_public_key);
|
||||
std::optional<session::ustring> secret_key_optional{std::nullopt};
|
||||
std::optional<session::ustring> initial_dump_optional{std::nullopt};
|
||||
|
||||
if (group_secret_key && env->GetArrayLength(group_secret_key) > 0) {
|
||||
auto secret_key_bytes = util::ustring_from_bytes(env, group_secret_key);
|
||||
secret_key_optional = secret_key_bytes;
|
||||
}
|
||||
|
||||
if (env->GetArrayLength(initial_dump) > 0) {
|
||||
auto initial_dump_bytes = util::ustring_from_bytes(env, initial_dump);
|
||||
initial_dump_optional = initial_dump_bytes;
|
||||
}
|
||||
|
||||
auto info = ptrToInfo(env, info_jobject);
|
||||
auto members = ptrToMembers(env, members_jobject);
|
||||
|
||||
auto* keys = new session::config::groups::Keys(user_key_bytes,
|
||||
pub_key_bytes,
|
||||
secret_key_optional,
|
||||
initial_dump_optional,
|
||||
*info,
|
||||
*members);
|
||||
|
||||
jclass groupKeysConfig = env->FindClass("network/loki/messenger/libsession_util/GroupKeysConfig");
|
||||
jmethodID constructor = env->GetMethodID(groupKeysConfig, "<init>", "(J)V");
|
||||
jobject newConfig = env->NewObject(groupKeysConfig, constructor, reinterpret_cast<jlong>(keys));
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_groupKeys(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToKeys(env, thiz);
|
||||
auto keys = config->group_keys();
|
||||
jclass stack = env->FindClass("java/util/Stack");
|
||||
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
|
||||
jobject our_stack = env->NewObject(stack, init);
|
||||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
for (auto& key : keys) {
|
||||
auto key_bytes = util::bytes_from_ustring(env, key.data());
|
||||
env->CallObjectMethod(our_stack, push, key_bytes);
|
||||
}
|
||||
return our_stack;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_loadKey(JNIEnv *env, jobject thiz,
|
||||
jbyteArray message,
|
||||
jstring hash,
|
||||
jlong timestamp_ms,
|
||||
jobject info_jobject,
|
||||
jobject members_jobject) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto keys = ptrToKeys(env, thiz);
|
||||
auto message_bytes = util::ustring_from_bytes(env, message);
|
||||
auto hash_bytes = env->GetStringUTFChars(hash, nullptr);
|
||||
auto info = ptrToInfo(env, info_jobject);
|
||||
auto members = ptrToMembers(env, members_jobject);
|
||||
bool processed = keys->load_key_message(hash_bytes, message_bytes, timestamp_ms, *info, *members);
|
||||
|
||||
env->ReleaseStringUTFChars(hash, hash_bytes);
|
||||
return processed;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_needsRekey(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto keys = ptrToKeys(env, thiz);
|
||||
return keys->needs_rekey();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_needsDump(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto keys = ptrToKeys(env, thiz);
|
||||
return keys->needs_dump();
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_pendingKey(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto keys = ptrToKeys(env, thiz);
|
||||
auto pending = keys->pending_key();
|
||||
if (!pending) {
|
||||
return nullptr;
|
||||
}
|
||||
auto pending_bytes = util::bytes_from_ustring(env, *pending);
|
||||
return pending_bytes;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_pendingConfig(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto keys = ptrToKeys(env, thiz);
|
||||
auto pending = keys->pending_config();
|
||||
if (!pending) {
|
||||
return nullptr;
|
||||
}
|
||||
auto pending_bytes = util::bytes_from_ustring(env, *pending);
|
||||
return pending_bytes;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_rekey(JNIEnv *env, jobject thiz,
|
||||
jobject info_jobject, jobject members_jobject) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto keys = ptrToKeys(env, thiz);
|
||||
auto info = ptrToInfo(env, info_jobject);
|
||||
auto members = ptrToMembers(env, members_jobject);
|
||||
auto rekey = keys->rekey(*info, *members);
|
||||
auto rekey_bytes = util::bytes_from_ustring(env, rekey.data());
|
||||
return rekey_bytes;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_dump(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto keys = ptrToKeys(env, thiz);
|
||||
auto dump = keys->dump();
|
||||
auto byte_array = util::bytes_from_ustring(env, dump);
|
||||
return byte_array;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_free(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto ptr = ptrToKeys(env, thiz);
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_encrypt(JNIEnv *env, jobject thiz,
|
||||
jbyteArray plaintext) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto ptr = ptrToKeys(env, thiz);
|
||||
auto plaintext_ustring = util::ustring_from_bytes(env, plaintext);
|
||||
auto enc = ptr->encrypt_message(plaintext_ustring);
|
||||
return util::bytes_from_ustring(env, enc);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_decrypt(JNIEnv *env, jobject thiz,
|
||||
jbyteArray ciphertext) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto ptr = ptrToKeys(env, thiz);
|
||||
auto ciphertext_ustring = util::ustring_from_bytes(env, ciphertext);
|
||||
try {
|
||||
auto decrypted = ptr->decrypt_message(ciphertext_ustring);
|
||||
auto sender = decrypted.first;
|
||||
auto plaintext = decrypted.second;
|
||||
auto plaintext_bytes = util::bytes_from_ustring(env, plaintext);
|
||||
auto sender_session_id = util::serialize_account_id(env, sender.data());
|
||||
auto pair_class = env->FindClass("kotlin/Pair");
|
||||
auto pair_constructor = env->GetMethodID(pair_class, "<init>", "(Ljava/lang/Object;Ljava/lang/Object;)V");
|
||||
auto pair_obj = env->NewObject(pair_class, pair_constructor, plaintext_bytes, sender_session_id);
|
||||
return pair_obj;
|
||||
} catch (std::exception& e) {
|
||||
// TODO: maybe log here
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_keys(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto ptr = ptrToKeys(env, thiz);
|
||||
auto keys = ptr->group_keys();
|
||||
jclass stack = env->FindClass("java/util/Stack");
|
||||
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
|
||||
jobject our_stack = env->NewObject(stack, init);
|
||||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
for (auto& key : keys) {
|
||||
auto key_bytes = util::bytes_from_ustring(env, key);
|
||||
env->CallObjectMethod(our_stack, push, key_bytes);
|
||||
}
|
||||
return our_stack;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_currentHashes(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto ptr = ptrToKeys(env, thiz);
|
||||
auto existing = ptr->current_hashes();
|
||||
jclass stack = env->FindClass("java/util/Stack");
|
||||
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
|
||||
jobject our_list = env->NewObject(stack, init);
|
||||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
for (auto& hash : existing) {
|
||||
auto hash_bytes = env->NewStringUTF(hash.data());
|
||||
env->CallObjectMethod(our_list, push, hash_bytes);
|
||||
}
|
||||
return our_list;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_makeSubAccount(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jobject session_id,
|
||||
jboolean can_write,
|
||||
jboolean can_delete) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto ptr = ptrToKeys(env, thiz);
|
||||
auto deserialized_id = util::deserialize_account_id(env, session_id);
|
||||
auto new_subaccount_key = ptr->swarm_make_subaccount(deserialized_id.data(), can_write, can_delete);
|
||||
auto jbytes = util::bytes_from_ustring(env, new_subaccount_key);
|
||||
return jbytes;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_getSubAccountToken(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jobject session_id,
|
||||
jboolean can_write,
|
||||
jboolean can_delete) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto ptr = ptrToKeys(env, thiz);
|
||||
auto deserialized_id = util::deserialize_account_id(env, session_id);
|
||||
auto token = ptr->swarm_subaccount_token(deserialized_id, can_write, can_delete);
|
||||
auto jbytes = util::bytes_from_ustring(env, token);
|
||||
return jbytes;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_subAccountSign(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jbyteArray message,
|
||||
jbyteArray signing_value) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto ptr = ptrToKeys(env, thiz);
|
||||
auto message_ustring = util::ustring_from_bytes(env, message);
|
||||
auto signing_value_ustring = util::ustring_from_bytes(env, signing_value);
|
||||
auto swarm_auth = ptr->swarm_subaccount_sign(message_ustring, signing_value_ustring, false);
|
||||
return util::deserialize_swarm_auth(env, swarm_auth);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_supplementFor(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring user_session_id) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto ptr = ptrToKeys(env, thiz);
|
||||
auto string = env->GetStringUTFChars(user_session_id, nullptr);
|
||||
auto supplement = ptr->key_supplement(string);
|
||||
auto supplement_jbytearray = util::bytes_from_ustring(env, supplement);
|
||||
env->ReleaseStringUTFChars(user_session_id, string);
|
||||
return supplement_jbytearray;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_currentGeneration(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto ptr = ptrToKeys(env, thiz);
|
||||
return ptr->current_generation();
|
||||
}
|
12
libsession-util/src/main/cpp/group_keys.h
Normal file
12
libsession-util/src/main/cpp/group_keys.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef SESSION_ANDROID_GROUP_KEYS_H
|
||||
#define SESSION_ANDROID_GROUP_KEYS_H
|
||||
|
||||
#include "util.h"
|
||||
|
||||
inline session::config::groups::Keys* ptrToKeys(JNIEnv* env, jobject obj) {
|
||||
jclass configClass = env->FindClass("network/loki/messenger/libsession_util/GroupKeysConfig");
|
||||
jfieldID pointerField = env->GetFieldID(configClass, "pointer", "J");
|
||||
return (session::config::groups::Keys*) env->GetLongField(obj, pointerField);
|
||||
}
|
||||
|
||||
#endif //SESSION_ANDROID_GROUP_KEYS_H
|
103
libsession-util/src/main/cpp/group_members.cpp
Normal file
103
libsession-util/src/main/cpp/group_members.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
#include "group_members.h"
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_00024Companion_newInstance(
|
||||
JNIEnv *env, jobject thiz, jbyteArray pub_key, jbyteArray secret_key,
|
||||
jbyteArray initial_dump) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto pub_key_bytes = util::ustring_from_bytes(env, pub_key);
|
||||
std::optional<session::ustring> secret_key_optional{std::nullopt};
|
||||
std::optional<session::ustring> initial_dump_optional{std::nullopt};
|
||||
if (secret_key && env->GetArrayLength(secret_key) > 0) {
|
||||
auto secret_key_bytes = util::ustring_from_bytes(env, secret_key);
|
||||
secret_key_optional = secret_key_bytes;
|
||||
}
|
||||
if (env->GetArrayLength(initial_dump) > 0) {
|
||||
auto initial_dump_bytes = util::ustring_from_bytes(env, initial_dump);
|
||||
initial_dump_optional = initial_dump_bytes;
|
||||
}
|
||||
|
||||
auto* group_members = new session::config::groups::Members(pub_key_bytes, secret_key_optional, initial_dump_optional);
|
||||
|
||||
jclass groupMemberClass = env->FindClass("network/loki/messenger/libsession_util/GroupMembersConfig");
|
||||
jmethodID constructor = env->GetMethodID(groupMemberClass, "<init>", "(J)V");
|
||||
jobject newConfig = env->NewObject(groupMemberClass, constructor, reinterpret_cast<jlong>(group_members));
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_all(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToMembers(env, thiz);
|
||||
jclass stack = env->FindClass("java/util/Stack");
|
||||
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
|
||||
jobject our_stack = env->NewObject(stack, init);
|
||||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
for (auto& member : *config) {
|
||||
auto member_obj = util::serialize_group_member(env, member);
|
||||
env->CallObjectMethod(our_stack, push, member_obj);
|
||||
}
|
||||
return our_stack;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_erase__Lnetwork_loki_messenger_libsession_1util_util_GroupMember_2(JNIEnv *env, jobject thiz,
|
||||
jobject group_member) {
|
||||
auto config = ptrToMembers(env, thiz);
|
||||
auto member = util::deserialize_group_member(env, group_member);
|
||||
return config->erase(member.session_id);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_erase__Ljava_lang_String_2(JNIEnv *env, jobject thiz, jstring pub_key_hex) {
|
||||
auto config = ptrToMembers(env, thiz);
|
||||
auto member_id = env->GetStringUTFChars(pub_key_hex, nullptr);
|
||||
auto erased = config->erase(member_id);
|
||||
env->ReleaseStringUTFChars(pub_key_hex, member_id);
|
||||
return erased;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_get(JNIEnv *env, jobject thiz,
|
||||
jstring pub_key_hex) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToMembers(env, thiz);
|
||||
auto pub_key_bytes = env->GetStringUTFChars(pub_key_hex, nullptr);
|
||||
auto member = config->get(pub_key_bytes);
|
||||
if (!member) {
|
||||
return nullptr;
|
||||
}
|
||||
auto serialized = util::serialize_group_member(env, *member);
|
||||
env->ReleaseStringUTFChars(pub_key_hex, pub_key_bytes);
|
||||
return serialized;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_getOrConstruct(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring pub_key_hex) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToMembers(env, thiz);
|
||||
auto pub_key_bytes = env->GetStringUTFChars(pub_key_hex, nullptr);
|
||||
auto member = config->get_or_construct(pub_key_bytes);
|
||||
auto serialized = util::serialize_group_member(env, member);
|
||||
env->ReleaseStringUTFChars(pub_key_hex, pub_key_bytes);
|
||||
return serialized;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupMembersConfig_set(JNIEnv *env, jobject thiz,
|
||||
jobject group_member) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToMembers(env, thiz);
|
||||
auto deserialized = util::deserialize_group_member(env, group_member);
|
||||
config->set(deserialized);
|
||||
}
|
13
libsession-util/src/main/cpp/group_members.h
Normal file
13
libsession-util/src/main/cpp/group_members.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef SESSION_ANDROID_GROUP_MEMBERS_H
|
||||
#define SESSION_ANDROID_GROUP_MEMBERS_H
|
||||
|
||||
#include "util.h"
|
||||
|
||||
inline session::config::groups::Members* ptrToMembers(JNIEnv* env, jobject obj) {
|
||||
jclass configClass = env->FindClass("network/loki/messenger/libsession_util/GroupMembersConfig");
|
||||
jfieldID pointerField = env->GetFieldID(configClass, "pointer", "J");
|
||||
return (session::config::groups::Members*) env->GetLongField(obj, pointerField);
|
||||
}
|
||||
|
||||
|
||||
#endif //SESSION_ANDROID_GROUP_MEMBERS_H
|
@@ -1,7 +1,7 @@
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
|
||||
#include "user_groups.h"
|
||||
|
||||
#include "oxenc/hex.h"
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
|
||||
@@ -125,6 +125,8 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_set__Lnetwork_loki
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto community_info = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
|
||||
auto legacy_info = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
|
||||
auto closed_group_info = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$ClosedGroupInfo");
|
||||
|
||||
auto object_class = env->GetObjectClass(group_info);
|
||||
if (env->IsSameObject(community_info, object_class)) {
|
||||
auto deserialized = deserialize_community_info(env, group_info, conf);
|
||||
@@ -132,6 +134,9 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_set__Lnetwork_loki
|
||||
} else if (env->IsSameObject(legacy_info, object_class)) {
|
||||
auto deserialized = deserialize_legacy_group_info(env, group_info, conf);
|
||||
conf->set(deserialized);
|
||||
} else if (env->IsSameObject(closed_group_info, object_class)) {
|
||||
auto deserialized = deserialize_closed_group_info(env, group_info);
|
||||
conf->set(deserialized);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,18 +149,22 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_erase__Lnetwork_lo
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto communityInfo = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
|
||||
auto legacyInfo = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
|
||||
auto group_object = env->GetObjectClass(group_info);
|
||||
if (env->IsSameObject(group_object, communityInfo)) {
|
||||
auto closedGroupInfo = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$ClosedGroupInfo");
|
||||
auto object_class = env->GetObjectClass(group_info);
|
||||
if (env->IsSameObject(communityInfo, object_class)) {
|
||||
auto deserialized = deserialize_community_info(env, group_info, conf);
|
||||
conf->erase(deserialized);
|
||||
} else if (env->IsSameObject(group_object, legacyInfo)) {
|
||||
} else if (env->IsSameObject(legacyInfo, object_class)) {
|
||||
auto deserialized = deserialize_legacy_group_info(env, group_info, conf);
|
||||
conf->erase(deserialized);
|
||||
} else if (env->IsSameObject(closedGroupInfo, object_class)) {
|
||||
auto deserialized = deserialize_closed_group_info(env, group_info);
|
||||
conf->erase(deserialized);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_sizeCommunityInfo(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
@@ -164,7 +173,7 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_sizeCommunityInfo(
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_sizeLegacyGroupInfo(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
@@ -173,7 +182,7 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_sizeLegacyGroupInf
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_size(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToConvoInfo(env, thiz);
|
||||
@@ -193,6 +202,8 @@ inline jobject iterator_as_java_stack(JNIEnv *env, const session::config::UserGr
|
||||
serialized = serialize_legacy_group_info(env, *lgc);
|
||||
} else if (auto* community = std::get_if<session::config::community_info>(&item)) {
|
||||
serialized = serialize_community_info(env, *community);
|
||||
} else if (auto* closed = std::get_if<session::config::group_info>(&item)) {
|
||||
serialized = serialize_closed_group_info(env, *closed);
|
||||
}
|
||||
if (serialized != nullptr) {
|
||||
env->CallObjectMethod(our_stack, push, serialized);
|
||||
@@ -271,4 +282,83 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_eraseLegacyGroup(J
|
||||
bool return_bool = conf->erase_legacy_group(account_id_bytes);
|
||||
env->ReleaseStringUTFChars(account_id, account_id_bytes);
|
||||
return return_bool;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_getClosedGroup(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring session_id) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto config = ptrToUserGroups(env, thiz);
|
||||
auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr);
|
||||
|
||||
auto group = config->get_group(session_id_bytes);
|
||||
|
||||
env->ReleaseStringUTFChars(session_id, session_id_bytes);
|
||||
|
||||
if (group) {
|
||||
return serialize_closed_group_info(env, *group);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_getOrConstructClosedGroup(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring session_id) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto config = ptrToUserGroups(env, thiz);
|
||||
auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr);
|
||||
|
||||
auto group = config->get_or_construct_group(session_id_bytes);
|
||||
|
||||
env->ReleaseStringUTFChars(session_id, session_id_bytes);
|
||||
|
||||
return serialize_closed_group_info(env, group);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_allClosedGroupInfo(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto closed_group_stack = iterator_as_java_stack(env, conf->begin_groups(), conf->end());
|
||||
|
||||
return closed_group_stack;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_createGroup(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto config = ptrToUserGroups(env, thiz);
|
||||
|
||||
auto group = config->create_group();
|
||||
return serialize_closed_group_info(env, group);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_sizeClosedGroup(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto config = ptrToUserGroups(env, thiz);
|
||||
return config->size_groups();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_eraseClosedGroup(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring session_id) {
|
||||
std::lock_guard guard{util::util_mutex_};
|
||||
auto config = ptrToUserGroups(env, thiz);
|
||||
auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr);
|
||||
bool return_value = config->erase_group(session_id_bytes);
|
||||
env->ReleaseStringUTFChars(session_id, session_id_bytes);
|
||||
return return_value;
|
||||
}
|
@@ -49,18 +49,18 @@ inline session::config::legacy_group_info deserialize_legacy_group_info(JNIEnv *
|
||||
auto members_field = env->GetFieldID(clazz, "members", "Ljava/util/Map;");
|
||||
auto enc_pub_key_field = env->GetFieldID(clazz, "encPubKey", "[B");
|
||||
auto enc_sec_key_field = env->GetFieldID(clazz, "encSecKey", "[B");
|
||||
auto priority_field = env->GetFieldID(clazz, "priority", "I");
|
||||
auto priority_field = env->GetFieldID(clazz, "priority", "J");
|
||||
auto disappearing_timer_field = env->GetFieldID(clazz, "disappearingTimer", "J");
|
||||
auto joined_at_field = env->GetFieldID(clazz, "joinedAt", "J");
|
||||
jstring id = static_cast<jstring>(env->GetObjectField(info, id_field));
|
||||
auto id = static_cast<jstring>(env->GetObjectField(info, id_field));
|
||||
jstring name = static_cast<jstring>(env->GetObjectField(info, name_field));
|
||||
jobject members_map = env->GetObjectField(info, members_field);
|
||||
jbyteArray enc_pub_key = static_cast<jbyteArray>(env->GetObjectField(info, enc_pub_key_field));
|
||||
jbyteArray enc_sec_key = static_cast<jbyteArray>(env->GetObjectField(info, enc_sec_key_field));
|
||||
int priority = env->GetIntField(info, priority_field);
|
||||
int priority = env->GetLongField(info, priority_field);
|
||||
long joined_at = env->GetLongField(info, joined_at_field);
|
||||
|
||||
auto id_bytes = env->GetStringUTFChars(id, nullptr);
|
||||
auto id_bytes = util::string_from_jstring(env, id);
|
||||
auto name_bytes = env->GetStringUTFChars(name, nullptr);
|
||||
auto enc_pub_key_bytes = util::ustring_from_bytes(env, enc_pub_key);
|
||||
auto enc_sec_key_bytes = util::ustring_from_bytes(env, enc_sec_key);
|
||||
@@ -78,7 +78,6 @@ inline session::config::legacy_group_info deserialize_legacy_group_info(JNIEnv *
|
||||
info_deserialized.priority = priority;
|
||||
info_deserialized.disappearing_timer = std::chrono::seconds(env->GetLongField(info, disappearing_timer_field));
|
||||
info_deserialized.joined_at = joined_at;
|
||||
env->ReleaseStringUTFChars(id, id_bytes);
|
||||
env->ReleaseStringUTFChars(name, name_bytes);
|
||||
return info_deserialized;
|
||||
}
|
||||
@@ -86,10 +85,10 @@ inline session::config::legacy_group_info deserialize_legacy_group_info(JNIEnv *
|
||||
inline session::config::community_info deserialize_community_info(JNIEnv *env, jobject info, session::config::UserGroups* conf) {
|
||||
auto clazz = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
|
||||
auto base_info = env->GetFieldID(clazz, "community", "Lnetwork/loki/messenger/libsession_util/util/BaseCommunityInfo;");
|
||||
auto priority = env->GetFieldID(clazz, "priority", "I");
|
||||
auto priority = env->GetFieldID(clazz, "priority", "J");
|
||||
jobject base_community_info = env->GetObjectField(info, base_info);
|
||||
auto deserialized_base_info = util::deserialize_base_community(env, base_community_info);
|
||||
int deserialized_priority = env->GetIntField(info, priority);
|
||||
int deserialized_priority = env->GetLongField(info, priority);
|
||||
auto community_info = conf->get_or_construct_community(deserialized_base_info.base_url(), deserialized_base_info.room(), deserialized_base_info.pubkey_hex());
|
||||
community_info.priority = deserialized_priority;
|
||||
return community_info;
|
||||
@@ -118,20 +117,63 @@ inline jobject serialize_legacy_group_info(JNIEnv *env, session::config::legacy_
|
||||
jobject members = serialize_members(env, info.members());
|
||||
jbyteArray enc_pubkey = util::bytes_from_ustring(env, info.enc_pubkey);
|
||||
jbyteArray enc_seckey = util::bytes_from_ustring(env, info.enc_seckey);
|
||||
int priority = info.priority;
|
||||
long joined_at = info.joined_at;
|
||||
long long priority = info.priority;
|
||||
long long joined_at = info.joined_at;
|
||||
|
||||
jclass legacy_group_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
|
||||
jmethodID constructor = env->GetMethodID(legacy_group_class, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;[B[BIJJ)V");
|
||||
jmethodID constructor = env->GetMethodID(legacy_group_class, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;[B[BJJJ)V");
|
||||
jobject serialized = env->NewObject(legacy_group_class, constructor, account_id, name, members, enc_pubkey, enc_seckey, priority, (jlong) info.disappearing_timer.count(), joined_at);
|
||||
return serialized;
|
||||
}
|
||||
|
||||
inline jobject serialize_closed_group_info(JNIEnv* env, session::config::group_info info) {
|
||||
auto session_id = util::serialize_account_id(env, info.id);
|
||||
jbyteArray admin_bytes = info.secretkey.empty() ? nullptr : util::bytes_from_ustring(env, info.secretkey);
|
||||
jbyteArray auth_bytes = info.auth_data.empty() ? nullptr : util::bytes_from_ustring(env, info.auth_data);
|
||||
jstring name = util::jstringFromOptional(env, info.name);
|
||||
|
||||
jclass group_info_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$ClosedGroupInfo");
|
||||
jmethodID constructor = env->GetMethodID(group_info_class, "<init>","(Lorg/session/libsignal/utilities/AccountId;[B[BJZLjava/lang/String;)V");
|
||||
jobject return_object = env->NewObject(group_info_class,constructor,
|
||||
session_id, admin_bytes, auth_bytes, (jlong)info.priority, info.invited, name);
|
||||
return return_object;
|
||||
}
|
||||
|
||||
inline session::config::group_info deserialize_closed_group_info(JNIEnv* env, jobject info_serialized) {
|
||||
jclass closed_group_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$ClosedGroupInfo");
|
||||
jfieldID id_field = env->GetFieldID(closed_group_class, "groupAccountId", "Lorg/session/libsignal/utilities/AccountId;");
|
||||
jfieldID secret_field = env->GetFieldID(closed_group_class, "adminKey", "[B");
|
||||
jfieldID auth_field = env->GetFieldID(closed_group_class, "authData", "[B");
|
||||
jfieldID priority_field = env->GetFieldID(closed_group_class, "priority", "J");
|
||||
jfieldID invited_field = env->GetFieldID(closed_group_class, "invited", "Z");
|
||||
jfieldID name_field = env->GetFieldID(closed_group_class, "name", "Ljava/lang/String;");
|
||||
|
||||
|
||||
jobject id_jobject = env->GetObjectField(info_serialized, id_field);
|
||||
jbyteArray secret_jBytes = (jbyteArray)env->GetObjectField(info_serialized, secret_field);
|
||||
jbyteArray auth_jBytes = (jbyteArray)env->GetObjectField(info_serialized, auth_field);
|
||||
jstring name_jstring = (jstring)env->GetObjectField(info_serialized, name_field);
|
||||
|
||||
auto id_bytes = util::deserialize_account_id(env, id_jobject);
|
||||
auto secret_bytes = util::ustring_from_bytes(env, secret_jBytes);
|
||||
auto auth_bytes = util::ustring_from_bytes(env, auth_jBytes);
|
||||
auto name = util::string_from_jstring(env, name_jstring);
|
||||
|
||||
session::config::group_info group_info(id_bytes);
|
||||
group_info.auth_data = auth_bytes;
|
||||
group_info.secretkey = secret_bytes;
|
||||
group_info.priority = env->GetLongField(info_serialized, priority_field);
|
||||
group_info.invited = env->GetBooleanField(info_serialized, invited_field);
|
||||
group_info.name = name;
|
||||
|
||||
return group_info;
|
||||
}
|
||||
|
||||
inline jobject serialize_community_info(JNIEnv *env, session::config::community_info info) {
|
||||
auto priority = info.priority;
|
||||
auto priority = (long long)info.priority;
|
||||
auto serialized_info = util::serialize_base_community(env, info);
|
||||
auto clazz = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
|
||||
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Lnetwork/loki/messenger/libsession_util/util/BaseCommunityInfo;I)V");
|
||||
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Lnetwork/loki/messenger/libsession_util/util/BaseCommunityInfo;J)V");
|
||||
jobject serialized = env->NewObject(clazz, constructor, serialized_info, priority);
|
||||
return serialized;
|
||||
}
|
||||
|
@@ -84,13 +84,13 @@ Java_network_loki_messenger_libsession_1util_UserProfile_setPic(JNIEnv *env, job
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserProfile_setNtsPriority(JNIEnv *env, jobject thiz,
|
||||
jint priority) {
|
||||
jlong priority) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto profile = ptrToProfile(env, thiz);
|
||||
profile->set_nts_priority(priority);
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserProfile_getNtsPriority(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto profile = ptrToProfile(env, thiz);
|
||||
|
@@ -1,6 +1,17 @@
|
||||
#include "util.h"
|
||||
#include <string>
|
||||
#include "sodium/randombytes.h"
|
||||
#include <sodium/crypto_sign.h>
|
||||
#include <session/multi_encrypt.hpp>
|
||||
#include <string>
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
#define LOG_TAG "libsession_util"
|
||||
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
|
||||
|
||||
namespace util {
|
||||
|
||||
@@ -15,6 +26,9 @@ namespace util {
|
||||
}
|
||||
|
||||
session::ustring ustring_from_bytes(JNIEnv* env, jbyteArray byteArray) {
|
||||
if (byteArray == nullptr) {
|
||||
return {};
|
||||
}
|
||||
size_t len = env->GetArrayLength(byteArray);
|
||||
auto bytes = env->GetByteArrayElements(byteArray, nullptr);
|
||||
|
||||
@@ -23,6 +37,15 @@ namespace util {
|
||||
return st;
|
||||
}
|
||||
|
||||
std::string string_from_jstring(JNIEnv* env, jstring string) {
|
||||
size_t len = env->GetStringUTFLength(string);
|
||||
auto chars = env->GetStringUTFChars(string, nullptr);
|
||||
|
||||
std::string st(chars, len);
|
||||
env->ReleaseStringUTFChars(string, chars);
|
||||
return st;
|
||||
}
|
||||
|
||||
jobject serialize_user_pic(JNIEnv *env, session::config::profile_pic pic) {
|
||||
jclass returnObjectClass = env->FindClass("network/loki/messenger/libsession_util/util/UserPic");
|
||||
jmethodID constructor = env->GetMethodID(returnObjectClass, "<init>", "(Ljava/lang/String;[B)V");
|
||||
@@ -115,6 +138,114 @@ namespace util {
|
||||
return our_stack;
|
||||
}
|
||||
|
||||
jobject serialize_group_member(JNIEnv* env, const session::config::groups::member& member) {
|
||||
jclass group_member_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupMember");
|
||||
jmethodID constructor = env->GetMethodID(group_member_class, "<init>", "(Ljava/lang/String;Ljava/lang/String;Lnetwork/loki/messenger/libsession_util/util/UserPic;ZZIII)V");
|
||||
jobject user_pic = serialize_user_pic(env, member.profile_picture);
|
||||
jstring session_id = env->NewStringUTF(member.session_id.data());
|
||||
jstring name = env->NewStringUTF(member.name.data());
|
||||
return env->NewObject(group_member_class,
|
||||
constructor,
|
||||
session_id,
|
||||
name,
|
||||
user_pic,
|
||||
(jboolean) member.admin,
|
||||
(jboolean) member.supplement,
|
||||
(jint) member.invite_status,
|
||||
(jint) member.promotion_status,
|
||||
(jint) member.removed_status
|
||||
);
|
||||
}
|
||||
|
||||
session::config::groups::member deserialize_group_member(JNIEnv* env, jobject member) {
|
||||
jclass group_member_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupMember");
|
||||
jfieldID session_id_field = env->GetFieldID(group_member_class, "sessionId", "Ljava/lang/String;");
|
||||
jfieldID name_field = env->GetFieldID(group_member_class, "name", "Ljava/lang/String;");
|
||||
jfieldID user_pic_field = env->GetFieldID(group_member_class,"profilePicture", "Lnetwork/loki/messenger/libsession_util/util/UserPic;");
|
||||
jfieldID invite_status_field = env->GetFieldID(group_member_class, "inviteStatus", "I");
|
||||
jfieldID admin_field = env->GetFieldID(group_member_class, "admin", "Z");
|
||||
jfieldID promotion_status_field = env->GetFieldID(group_member_class, "promotionStatus", "I");
|
||||
jfieldID removed_status_field = env->GetFieldID(group_member_class, "removedStatus", "I");
|
||||
jfieldID supplement_field = env->GetFieldID(group_member_class, "supplement", "Z");
|
||||
auto session_id = (jstring)env->GetObjectField(member, session_id_field);
|
||||
auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr);
|
||||
auto name = (jstring)env->GetObjectField(member, name_field);
|
||||
auto name_bytes = env->GetStringUTFChars(name, nullptr);
|
||||
auto user_pic_jobject = env->GetObjectField(member, user_pic_field);
|
||||
auto user_pic = deserialize_user_pic(env, user_pic_jobject);
|
||||
auto url_bytes = env->GetStringUTFChars(user_pic.first, nullptr);
|
||||
auto pic_key = ustring_from_bytes(env, user_pic.second);
|
||||
auto invite_status = env->GetIntField(member, invite_status_field);
|
||||
auto promotion_status = env->GetIntField(member, promotion_status_field);
|
||||
auto removed_status = env->GetIntField(member, removed_status_field);
|
||||
auto admin = env->GetBooleanField(member, admin_field);
|
||||
auto supplement = env->GetBooleanField(member, supplement_field);
|
||||
|
||||
// set up the object
|
||||
session::config::groups::member group_member(session_id_bytes);
|
||||
group_member.name = name_bytes;
|
||||
group_member.profile_picture.url = url_bytes;
|
||||
group_member.profile_picture.set_key(pic_key);
|
||||
group_member.invite_status = invite_status;
|
||||
group_member.promotion_status = promotion_status;
|
||||
group_member.removed_status = removed_status;
|
||||
group_member.supplement = supplement;
|
||||
group_member.admin = admin;
|
||||
|
||||
env->ReleaseStringUTFChars(user_pic.first, url_bytes);
|
||||
env->ReleaseStringUTFChars(session_id, session_id_bytes);
|
||||
env->ReleaseStringUTFChars(name, name_bytes);
|
||||
return group_member;
|
||||
}
|
||||
|
||||
jobject deserialize_swarm_auth(JNIEnv *env, session::config::groups::Keys::swarm_auth auth) {
|
||||
jclass swarm_auth_class = env->FindClass("network/loki/messenger/libsession_util/GroupKeysConfig$SwarmAuth");
|
||||
jmethodID constructor = env->GetMethodID(swarm_auth_class, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
||||
jstring sub_account = env->NewStringUTF(auth.subaccount.data());
|
||||
jstring sub_account_sig = env->NewStringUTF(auth.subaccount_sig.data());
|
||||
jstring signature = env->NewStringUTF(auth.signature.data());
|
||||
|
||||
return env->NewObject(swarm_auth_class, constructor, sub_account, sub_account_sig, signature);
|
||||
}
|
||||
|
||||
jobject jlongFromOptional(JNIEnv* env, std::optional<long long> optional) {
|
||||
if (!optional) {
|
||||
return nullptr;
|
||||
}
|
||||
jclass longClass = env->FindClass("java/lang/Long");
|
||||
jmethodID constructor = env->GetMethodID(longClass, "<init>", "(J)V");
|
||||
jobject returned = env->NewObject(longClass, constructor, (jlong)*optional);
|
||||
return returned;
|
||||
}
|
||||
|
||||
jstring jstringFromOptional(JNIEnv* env, std::optional<std::string_view> optional) {
|
||||
if (!optional) {
|
||||
return nullptr;
|
||||
}
|
||||
return env->NewStringUTF(optional->data());
|
||||
}
|
||||
|
||||
jobject serialize_account_id(JNIEnv* env, std::string_view session_id) {
|
||||
if (session_id.size() != 66) return nullptr;
|
||||
|
||||
jclass id_class = env->FindClass("org/session/libsignal/utilities/AccountId");
|
||||
jmethodID session_id_constructor = env->GetMethodID(id_class, "<init>", "(Ljava/lang/String;)V");
|
||||
|
||||
jstring session_id_string = env->NewStringUTF(session_id.data());
|
||||
|
||||
return env->NewObject(id_class, session_id_constructor, session_id_string);
|
||||
}
|
||||
|
||||
std::string deserialize_account_id(JNIEnv* env, jobject account_id) {
|
||||
jclass session_id_class = env->FindClass("org/session/libsignal/utilities/AccountId");
|
||||
jmethodID get_string = env->GetMethodID(session_id_class, "getHexString", "()Ljava/lang/String;");
|
||||
auto hex_jstring = (jstring)env->CallObjectMethod(account_id, get_string);
|
||||
auto hex_bytes = env->GetStringUTFChars(hex_jstring, nullptr);
|
||||
std::string hex_string{hex_bytes};
|
||||
env->ReleaseStringUTFChars(hex_jstring, hex_bytes);
|
||||
return hex_string;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C"
|
||||
@@ -134,6 +265,7 @@ Java_network_loki_messenger_libsession_1util_util_Sodium_ed25519KeyPair(JNIEnv *
|
||||
jobject return_obj = env->NewObject(kp_class, kp_constructor, pk_jarray, sk_jarray);
|
||||
return return_obj;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_util_Sodium_ed25519PkToCurve25519(JNIEnv *env,
|
||||
@@ -150,6 +282,83 @@ Java_network_loki_messenger_libsession_1util_util_Sodium_ed25519PkToCurve25519(J
|
||||
jbyteArray curve_pk_jarray = util::bytes_from_ustring(env, session::ustring_view {curve_pk.data(), curve_pk.size()});
|
||||
return curve_pk_jarray;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_util_Sodium_encryptForMultipleSimple(
|
||||
JNIEnv *env, jobject thiz, jobjectArray messages, jobjectArray recipients,
|
||||
jbyteArray ed25519_secret_key, jstring domain) {
|
||||
// messages and recipients have to be the same size
|
||||
uint size = env->GetArrayLength(messages);
|
||||
if (env->GetArrayLength(recipients) != size) {
|
||||
env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"), "Messages and recipients must be the same size");
|
||||
return nullptr;
|
||||
}
|
||||
std::vector<session::ustring> message_vec{};
|
||||
std::vector<session::ustring> recipient_vec{};
|
||||
for (int i = 0; i < size; i++) {
|
||||
jbyteArray message_j = static_cast<jbyteArray>(env->GetObjectArrayElement(messages, i));
|
||||
jbyteArray recipient_j = static_cast<jbyteArray>(env->GetObjectArrayElement(recipients, i));
|
||||
session::ustring message = util::ustring_from_bytes(env, message_j);
|
||||
session::ustring recipient = util::ustring_from_bytes(env, recipient_j);
|
||||
|
||||
message_vec.emplace_back(session::ustring{message});
|
||||
recipient_vec.emplace_back(session::ustring{recipient});
|
||||
}
|
||||
|
||||
std::vector<session::ustring_view> message_sv_vec{};
|
||||
std::vector<session::ustring_view> recipient_sv_vec{};
|
||||
for (int i = 0; i < size; i++) {
|
||||
message_sv_vec.emplace_back(session::to_unsigned_sv(message_vec[i]));
|
||||
recipient_sv_vec.emplace_back(session::to_unsigned_sv(recipient_vec[i]));
|
||||
}
|
||||
|
||||
auto sk = util::ustring_from_bytes(env, ed25519_secret_key);
|
||||
std::array<unsigned char, 24> random_nonce;
|
||||
randombytes_buf(random_nonce.data(), random_nonce.size());
|
||||
|
||||
auto domain_string = env->GetStringUTFChars(domain, nullptr);
|
||||
|
||||
auto result = session::encrypt_for_multiple_simple(
|
||||
message_sv_vec,
|
||||
recipient_sv_vec,
|
||||
sk,
|
||||
domain_string,
|
||||
session::ustring_view {random_nonce.data(), 24}
|
||||
);
|
||||
|
||||
env->ReleaseStringUTFChars(domain, domain_string);
|
||||
auto encoded = util::bytes_from_ustring(env, result);
|
||||
return encoded;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_util_Sodium_decryptForMultipleSimple(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jbyteArray encoded,
|
||||
jbyteArray secret_key,
|
||||
jbyteArray sender_pub_key,
|
||||
jstring domain) {
|
||||
auto sk_ustring = util::ustring_from_bytes(env, secret_key);
|
||||
auto encoded_ustring = util::ustring_from_bytes(env, encoded);
|
||||
auto pub_ustring = util::ustring_from_bytes(env, sender_pub_key);
|
||||
auto domain_bytes = env->GetStringUTFChars(domain, nullptr);
|
||||
auto result = session::decrypt_for_multiple_simple(
|
||||
encoded_ustring,
|
||||
sk_ustring,
|
||||
pub_ustring,
|
||||
domain_bytes
|
||||
);
|
||||
env->ReleaseStringUTFChars(domain,domain_bytes);
|
||||
if (result) {
|
||||
return util::bytes_from_ustring(env, *result);
|
||||
} else {
|
||||
LOGD("no result from decrypt");
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_util_BaseCommunityInfo_00024Companion_parseFullUrl(
|
||||
@@ -175,4 +384,82 @@ Java_network_loki_messenger_libsession_1util_util_BaseCommunityInfo_fullUrl(JNIE
|
||||
auto deserialized = util::deserialize_base_community(env, thiz);
|
||||
auto full_url = deserialized.full_url();
|
||||
return env->NewStringUTF(full_url.data());
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_session_libsignal_utilities_Namespace_DEFAULT(JNIEnv *env, jobject thiz) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_session_libsignal_utilities_Namespace_USER_1PROFILE(JNIEnv *env, jobject thiz) {
|
||||
return (int) session::config::Namespace::UserProfile;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_session_libsignal_utilities_Namespace_CONTACTS(JNIEnv *env, jobject thiz) {
|
||||
return (int) session::config::Namespace::Contacts;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_session_libsignal_utilities_Namespace_CONVO_1INFO_1VOLATILE(JNIEnv *env, jobject thiz) {
|
||||
return (int) session::config::Namespace::ConvoInfoVolatile;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_session_libsignal_utilities_Namespace_GROUPS(JNIEnv *env, jobject thiz) {
|
||||
return (int) session::config::Namespace::UserGroups;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_session_libsignal_utilities_Namespace_CLOSED_1GROUP_1INFO(JNIEnv *env, jobject thiz) {
|
||||
return (int) session::config::Namespace::GroupInfo;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_session_libsignal_utilities_Namespace_CLOSED_1GROUP_1MEMBERS(JNIEnv *env, jobject thiz) {
|
||||
return (int) session::config::Namespace::GroupMembers;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_session_libsignal_utilities_Namespace_ENCRYPTION_1KEYS(JNIEnv *env, jobject thiz) {
|
||||
return (int) session::config::Namespace::GroupKeys;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_session_libsignal_utilities_Namespace_CLOSED_1GROUP_1MESSAGES(JNIEnv *env, jobject thiz) {
|
||||
return (int) session::config::Namespace::GroupMessages;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_session_libsignal_utilities_Namespace_REVOKED_1GROUP_1MESSAGES(JNIEnv *env, jobject thiz) {
|
||||
return -11; // we don't have revoked namespace in user configs
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_Config_free(JNIEnv *env, jobject thiz) {
|
||||
jclass baseClass = env->FindClass("network/loki/messenger/libsession_util/Config");
|
||||
jfieldID pointerField = env->GetFieldID(baseClass, "pointer", "J");
|
||||
jclass sig = env->FindClass("network/loki/messenger/libsession_util/ConfigSig");
|
||||
jclass base = env->FindClass("network/loki/messenger/libsession_util/ConfigBase");
|
||||
jclass ours = env->GetObjectClass(thiz);
|
||||
if (env->IsSameObject(sig, ours)) {
|
||||
// config sig object
|
||||
auto config = (session::config::ConfigSig*) env->GetLongField(thiz, pointerField);
|
||||
delete config;
|
||||
} else if (env->IsSameObject(base, ours)) {
|
||||
auto config = (session::config::ConfigBase*) env->GetLongField(thiz, pointerField);
|
||||
delete config;
|
||||
}
|
||||
}
|
@@ -5,6 +5,9 @@
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include "session/types.hpp"
|
||||
#include "session/config/groups/info.hpp"
|
||||
#include "session/config/groups/keys.hpp"
|
||||
#include "session/config/groups/members.hpp"
|
||||
#include "session/config/profile_pic.hpp"
|
||||
#include "session/config/user_groups.hpp"
|
||||
#include "session/config/expiring.hpp"
|
||||
@@ -13,13 +16,20 @@ namespace util {
|
||||
extern std::mutex util_mutex_;
|
||||
jbyteArray bytes_from_ustring(JNIEnv* env, session::ustring_view from_str);
|
||||
session::ustring ustring_from_bytes(JNIEnv* env, jbyteArray byteArray);
|
||||
std::string string_from_jstring(JNIEnv* env, jstring string);
|
||||
jobject serialize_user_pic(JNIEnv *env, session::config::profile_pic pic);
|
||||
std::pair<jstring, jbyteArray> deserialize_user_pic(JNIEnv *env, jobject user_pic);
|
||||
jobject serialize_base_community(JNIEnv *env, const session::config::community& base_community);
|
||||
session::config::community deserialize_base_community(JNIEnv *env, jobject base_community);
|
||||
jobject serialize_expiry(JNIEnv *env, const session::config::expiration_mode& mode, const std::chrono::seconds& time_seconds);
|
||||
std::pair<session::config::expiration_mode, long> deserialize_expiry(JNIEnv *env, jobject expiry_mode);
|
||||
jobject serialize_group_member(JNIEnv* env, const session::config::groups::member& member);
|
||||
session::config::groups::member deserialize_group_member(JNIEnv* env, jobject member);
|
||||
jobject jlongFromOptional(JNIEnv* env, std::optional<long long> optional);
|
||||
jstring jstringFromOptional(JNIEnv* env, std::optional<std::string_view> optional);
|
||||
jobject serialize_account_id(JNIEnv* env, std::string_view session_id);
|
||||
std::string deserialize_account_id(JNIEnv* env, jobject account_id);
|
||||
jobject build_string_stack(JNIEnv* env, std::vector<std::string> to_add);
|
||||
}
|
||||
jobject deserialize_swarm_auth(JNIEnv *env, session::config::groups::Keys::swarm_auth auth);}
|
||||
|
||||
#endif
|
@@ -6,14 +6,25 @@ import network.loki.messenger.libsession_util.util.Contact
|
||||
import network.loki.messenger.libsession_util.util.Conversation
|
||||
import network.loki.messenger.libsession_util.util.ExpiryMode
|
||||
import network.loki.messenger.libsession_util.util.GroupInfo
|
||||
import network.loki.messenger.libsession_util.util.GroupMember
|
||||
import network.loki.messenger.libsession_util.util.UserPic
|
||||
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage.Kind
|
||||
import org.session.libsignal.utilities.AccountId
|
||||
import org.session.libsignal.utilities.IdPrefix
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.Namespace
|
||||
import java.io.Closeable
|
||||
import java.util.Stack
|
||||
|
||||
sealed class Config(protected val pointer: Long): Closeable {
|
||||
abstract fun namespace(): Int
|
||||
external fun free()
|
||||
override fun close() {
|
||||
free()
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ConfigBase(protected val /* yucky */ pointer: Long) {
|
||||
sealed class ConfigBase(pointer: Long): Config(pointer) {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
@@ -25,11 +36,13 @@ sealed class ConfigBase(protected val /* yucky */ pointer: Long) {
|
||||
is Contacts -> Kind.CONTACTS
|
||||
is ConversationVolatileConfig -> Kind.CONVO_INFO_VOLATILE
|
||||
is UserGroupsConfig -> Kind.GROUPS
|
||||
is GroupInfoConfig -> Kind.CLOSED_GROUP_INFO
|
||||
is GroupMembersConfig -> Kind.CLOSED_GROUP_MEMBERS
|
||||
}
|
||||
|
||||
const val PRIORITY_HIDDEN = -1
|
||||
const val PRIORITY_VISIBLE = 0
|
||||
const val PRIORITY_PINNED = 1
|
||||
const val PRIORITY_HIDDEN = -1L
|
||||
const val PRIORITY_VISIBLE = 0L
|
||||
const val PRIORITY_PINNED = 1L
|
||||
|
||||
}
|
||||
|
||||
@@ -43,13 +56,9 @@ sealed class ConfigBase(protected val /* yucky */ pointer: Long) {
|
||||
external fun merge(toMerge: Array<Pair<String,ByteArray>>): Stack<String>
|
||||
external fun currentHashes(): List<String>
|
||||
|
||||
external fun configNamespace(): Int
|
||||
|
||||
// Singular merge
|
||||
external fun merge(toMerge: Pair<String,ByteArray>): Stack<String>
|
||||
|
||||
external fun free()
|
||||
|
||||
}
|
||||
|
||||
class Contacts(pointer: Long) : ConfigBase(pointer) {
|
||||
@@ -61,6 +70,8 @@ class Contacts(pointer: Long) : ConfigBase(pointer) {
|
||||
external fun newInstance(ed25519SecretKey: ByteArray, initialDump: ByteArray): Contacts
|
||||
}
|
||||
|
||||
override fun namespace() = Namespace.CONTACTS()
|
||||
|
||||
external fun get(accountId: String): Contact?
|
||||
external fun getOrConstruct(accountId: String): Contact
|
||||
external fun all(): List<Contact>
|
||||
@@ -108,12 +119,14 @@ class UserProfile(pointer: Long) : ConfigBase(pointer) {
|
||||
external fun newInstance(ed25519SecretKey: ByteArray, initialDump: ByteArray): UserProfile
|
||||
}
|
||||
|
||||
override fun namespace() = Namespace.USER_PROFILE()
|
||||
|
||||
external fun setName(newName: String)
|
||||
external fun getName(): String?
|
||||
external fun getPic(): UserPic
|
||||
external fun setPic(userPic: UserPic)
|
||||
external fun setNtsPriority(priority: Int)
|
||||
external fun getNtsPriority(): Int
|
||||
external fun setNtsPriority(priority: Long)
|
||||
external fun getNtsPriority(): Long
|
||||
external fun setNtsExpiry(expiryMode: ExpiryMode)
|
||||
external fun getNtsExpiry(): ExpiryMode
|
||||
external fun getCommunityMessageRequests(): Boolean
|
||||
@@ -130,6 +143,8 @@ class ConversationVolatileConfig(pointer: Long): ConfigBase(pointer) {
|
||||
external fun newInstance(ed25519SecretKey: ByteArray, initialDump: ByteArray): ConversationVolatileConfig
|
||||
}
|
||||
|
||||
override fun namespace() = Namespace.CONVO_INFO_VOLATILE()
|
||||
|
||||
external fun getOneToOne(pubKeyHex: String): Conversation.OneToOne?
|
||||
external fun getOrConstructOneToOne(pubKeyHex: String): Conversation.OneToOne
|
||||
external fun eraseOneToOne(pubKeyHex: String): Boolean
|
||||
@@ -143,8 +158,12 @@ class ConversationVolatileConfig(pointer: Long): ConfigBase(pointer) {
|
||||
external fun getLegacyClosedGroup(groupId: String): Conversation.LegacyGroup?
|
||||
external fun getOrConstructLegacyGroup(groupId: String): Conversation.LegacyGroup
|
||||
external fun eraseLegacyClosedGroup(groupId: String): Boolean
|
||||
external fun erase(conversation: Conversation): Boolean
|
||||
|
||||
external fun getClosedGroup(sessionId: String): Conversation.ClosedGroup?
|
||||
external fun getOrConstructClosedGroup(sessionId: String): Conversation.ClosedGroup
|
||||
external fun eraseClosedGroup(sessionId: String): Boolean
|
||||
|
||||
external fun erase(conversation: Conversation): Boolean
|
||||
external fun set(toStore: Conversation)
|
||||
|
||||
/**
|
||||
@@ -162,6 +181,7 @@ class ConversationVolatileConfig(pointer: Long): ConfigBase(pointer) {
|
||||
external fun allOneToOnes(): List<Conversation.OneToOne>
|
||||
external fun allCommunities(): List<Conversation.Community>
|
||||
external fun allLegacyClosedGroups(): List<Conversation.LegacyGroup>
|
||||
external fun allClosedGroups(): List<Conversation.ClosedGroup>
|
||||
external fun all(): List<Conversation?>
|
||||
|
||||
}
|
||||
@@ -175,19 +195,148 @@ class UserGroupsConfig(pointer: Long): ConfigBase(pointer) {
|
||||
external fun newInstance(ed25519SecretKey: ByteArray, initialDump: ByteArray): UserGroupsConfig
|
||||
}
|
||||
|
||||
override fun namespace() = Namespace.GROUPS()
|
||||
|
||||
external fun getCommunityInfo(baseUrl: String, room: String): GroupInfo.CommunityGroupInfo?
|
||||
external fun getLegacyGroupInfo(accountId: String): GroupInfo.LegacyGroupInfo?
|
||||
external fun getClosedGroup(accountId: String): GroupInfo.ClosedGroupInfo?
|
||||
external fun getOrConstructCommunityInfo(baseUrl: String, room: String, pubKeyHex: String): GroupInfo.CommunityGroupInfo
|
||||
external fun getOrConstructLegacyGroupInfo(accountId: String): GroupInfo.LegacyGroupInfo
|
||||
external fun getOrConstructClosedGroup(accountId: String): GroupInfo.ClosedGroupInfo
|
||||
external fun set(groupInfo: GroupInfo)
|
||||
external fun erase(communityInfo: GroupInfo)
|
||||
external fun erase(groupInfo: GroupInfo)
|
||||
external fun eraseCommunity(baseCommunityInfo: BaseCommunityInfo): Boolean
|
||||
external fun eraseCommunity(server: String, room: String): Boolean
|
||||
external fun eraseLegacyGroup(accountId: String): Boolean
|
||||
external fun sizeCommunityInfo(): Int
|
||||
external fun sizeLegacyGroupInfo(): Int
|
||||
external fun size(): Int
|
||||
external fun eraseClosedGroup(accountId: String): Boolean
|
||||
external fun sizeCommunityInfo(): Long
|
||||
external fun sizeLegacyGroupInfo(): Long
|
||||
external fun sizeClosedGroup(): Long
|
||||
external fun size(): Long
|
||||
external fun all(): List<GroupInfo>
|
||||
external fun allCommunityInfo(): List<GroupInfo.CommunityGroupInfo>
|
||||
external fun allLegacyGroupInfo(): List<GroupInfo.LegacyGroupInfo>
|
||||
external fun allClosedGroupInfo(): List<GroupInfo.ClosedGroupInfo>
|
||||
external fun createGroup(): GroupInfo.ClosedGroupInfo
|
||||
}
|
||||
|
||||
class GroupInfoConfig(pointer: Long): ConfigBase(pointer), Closeable {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
}
|
||||
|
||||
external fun newInstance(
|
||||
pubKey: ByteArray?,
|
||||
secretKey: ByteArray? = null,
|
||||
initialDump: ByteArray = byteArrayOf()
|
||||
): GroupInfoConfig
|
||||
}
|
||||
|
||||
override fun namespace() = Namespace.CLOSED_GROUP_INFO()
|
||||
|
||||
external fun id(): AccountId
|
||||
external fun destroyGroup()
|
||||
external fun getCreated(): Long?
|
||||
external fun getDeleteAttachmentsBefore(): Long?
|
||||
external fun getDeleteBefore(): Long?
|
||||
external fun getExpiryTimer(): Long
|
||||
external fun getName(): String
|
||||
external fun getProfilePic(): UserPic
|
||||
external fun isDestroyed(): Boolean
|
||||
external fun setCreated(createdAt: Long)
|
||||
external fun setDeleteAttachmentsBefore(deleteBefore: Long)
|
||||
external fun setDeleteBefore(deleteBefore: Long)
|
||||
external fun setExpiryTimer(expireSeconds: Long)
|
||||
external fun setName(newName: String)
|
||||
external fun getDescription(): String
|
||||
external fun setDescription(newDescription: String)
|
||||
external fun setProfilePic(newProfilePic: UserPic)
|
||||
external fun storageNamespace(): Long
|
||||
|
||||
override fun close() {
|
||||
free()
|
||||
}
|
||||
}
|
||||
|
||||
class GroupMembersConfig(pointer: Long): ConfigBase(pointer), Closeable {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
}
|
||||
external fun newInstance(
|
||||
pubKey: ByteArray,
|
||||
secretKey: ByteArray? = null,
|
||||
initialDump: ByteArray = byteArrayOf()
|
||||
): GroupMembersConfig
|
||||
}
|
||||
|
||||
override fun namespace() = Namespace.CLOSED_GROUP_MEMBERS()
|
||||
|
||||
external fun all(): Stack<GroupMember>
|
||||
external fun erase(groupMember: GroupMember): Boolean
|
||||
external fun erase(pubKeyHex: String): Boolean
|
||||
external fun get(pubKeyHex: String): GroupMember?
|
||||
external fun getOrConstruct(pubKeyHex: String): GroupMember
|
||||
external fun set(groupMember: GroupMember)
|
||||
override fun close() {
|
||||
free()
|
||||
}
|
||||
}
|
||||
|
||||
sealed class ConfigSig(pointer: Long) : Config(pointer)
|
||||
|
||||
class GroupKeysConfig(pointer: Long): ConfigSig(pointer) {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
}
|
||||
external fun newInstance(
|
||||
userSecretKey: ByteArray,
|
||||
groupPublicKey: ByteArray,
|
||||
groupSecretKey: ByteArray? = null,
|
||||
initialDump: ByteArray = byteArrayOf(),
|
||||
info: GroupInfoConfig,
|
||||
members: GroupMembersConfig
|
||||
): GroupKeysConfig
|
||||
}
|
||||
|
||||
override fun namespace() = Namespace.ENCRYPTION_KEYS()
|
||||
|
||||
external fun groupKeys(): Stack<ByteArray>
|
||||
external fun needsDump(): Boolean
|
||||
external fun dump(): ByteArray
|
||||
external fun loadKey(message: ByteArray,
|
||||
hash: String,
|
||||
timestampMs: Long,
|
||||
info: GroupInfoConfig,
|
||||
members: GroupMembersConfig): Boolean
|
||||
external fun needsRekey(): Boolean
|
||||
external fun pendingKey(): ByteArray?
|
||||
external fun supplementFor(userSessionId: String): ByteArray
|
||||
external fun pendingConfig(): ByteArray?
|
||||
external fun currentHashes(): List<String>
|
||||
external fun rekey(info: GroupInfoConfig, members: GroupMembersConfig): ByteArray
|
||||
override fun close() {
|
||||
free()
|
||||
}
|
||||
|
||||
external fun encrypt(plaintext: ByteArray): ByteArray
|
||||
external fun decrypt(ciphertext: ByteArray): Pair<ByteArray, AccountId>?
|
||||
|
||||
external fun keys(): Stack<ByteArray>
|
||||
|
||||
external fun makeSubAccount(sessionId: AccountId, canWrite: Boolean = true, canDelete: Boolean = false): ByteArray
|
||||
external fun getSubAccountToken(sessionId: AccountId, canWrite: Boolean = true, canDelete: Boolean = false): ByteArray
|
||||
|
||||
external fun subAccountSign(message: ByteArray, signingValue: ByteArray): SwarmAuth
|
||||
|
||||
external fun currentGeneration(): Int
|
||||
|
||||
data class SwarmAuth(
|
||||
val subAccount: String,
|
||||
val subAccountSig: String,
|
||||
val signature: String
|
||||
)
|
||||
|
||||
}
|
@@ -8,6 +8,6 @@ data class Contact(
|
||||
var approvedMe: Boolean = false,
|
||||
var blocked: Boolean = false,
|
||||
var profilePicture: UserPic = UserPic.DEFAULT,
|
||||
var priority: Int = 0,
|
||||
var priority: Long = 0,
|
||||
var expiryMode: ExpiryMode,
|
||||
)
|
@@ -22,4 +22,10 @@ sealed class Conversation {
|
||||
override var lastRead: Long,
|
||||
override var unread: Boolean
|
||||
): Conversation()
|
||||
|
||||
data class ClosedGroup(
|
||||
val accountId: String,
|
||||
override var lastRead: Long,
|
||||
override var unread: Boolean
|
||||
): Conversation()
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package network.loki.messenger.libsession_util.util
|
||||
|
||||
import org.session.libsignal.utilities.AccountId
|
||||
|
||||
data class GroupDisplayInfo(
|
||||
val id: AccountId,
|
||||
val created: Long?,
|
||||
val expiryTimer: Long?,
|
||||
val name: String?,
|
||||
val description: String?,
|
||||
val destroyed: Boolean,
|
||||
val profilePic: UserPic,
|
||||
val isUserAdmin: Boolean
|
||||
)
|
@@ -1,8 +1,53 @@
|
||||
package network.loki.messenger.libsession_util.util
|
||||
|
||||
import org.session.libsignal.utilities.AccountId
|
||||
|
||||
sealed class GroupInfo {
|
||||
|
||||
data class CommunityGroupInfo(val community: BaseCommunityInfo, val priority: Int) : GroupInfo()
|
||||
data class CommunityGroupInfo(val community: BaseCommunityInfo, val priority: Long) : GroupInfo()
|
||||
|
||||
data class ClosedGroupInfo(
|
||||
val groupAccountId: AccountId,
|
||||
val adminKey: ByteArray?,
|
||||
val authData: ByteArray?,
|
||||
val priority: Long,
|
||||
val invited: Boolean,
|
||||
val name: String,
|
||||
): GroupInfo() {
|
||||
|
||||
init {
|
||||
require(adminKey == null || adminKey.isNotEmpty()) {
|
||||
"Admin key must be non-empty if present"
|
||||
}
|
||||
|
||||
require(authData == null || authData.isNotEmpty()) {
|
||||
"Auth data must be non-empty if present"
|
||||
}
|
||||
}
|
||||
|
||||
val kicked: Boolean
|
||||
get() = adminKey == null && authData == null
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as ClosedGroupInfo
|
||||
|
||||
if (groupAccountId != other.groupAccountId) return false
|
||||
if (!adminKey.contentEquals(other.adminKey)) return false
|
||||
return authData.contentEquals(other.authData)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = groupAccountId.hashCode()
|
||||
result = 31 * result + adminKey.contentHashCode()
|
||||
result = 31 * result + authData.contentHashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
fun hasAdminKey() = adminKey != null
|
||||
}
|
||||
|
||||
data class LegacyGroupInfo(
|
||||
val accountId: String,
|
||||
@@ -10,7 +55,7 @@ sealed class GroupInfo {
|
||||
val members: Map<String, Boolean>,
|
||||
val encPubKey: ByteArray,
|
||||
val encSecKey: ByteArray,
|
||||
val priority: Int,
|
||||
val priority: Long,
|
||||
val disappearingTimer: Long,
|
||||
val joinedAt: Long
|
||||
): GroupInfo() {
|
||||
@@ -43,11 +88,12 @@ sealed class GroupInfo {
|
||||
result = 31 * result + members.hashCode()
|
||||
result = 31 * result + encPubKey.contentHashCode()
|
||||
result = 31 * result + encSecKey.contentHashCode()
|
||||
result = 31 * result + priority
|
||||
result = 31 * result + priority.hashCode()
|
||||
result = 31 * result + disappearingTimer.hashCode()
|
||||
result = 31 * result + joinedAt.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
package network.loki.messenger.libsession_util.util
|
||||
|
||||
typealias InviteStatus = Int
|
||||
typealias PromotionStatus = Int
|
||||
typealias RemovedStatus = Int
|
||||
|
||||
const val INVITE_STATUS_SENT = 1
|
||||
const val INVITE_STATUS_FAILED = 2
|
||||
const val INVITE_NOT_SENT = 3
|
||||
|
||||
const val REMOVED_MEMBER = 1
|
||||
const val REMOVED_MEMBER_AND_MESSAGES = 2
|
||||
|
||||
data class GroupMember(
|
||||
val sessionId: String,
|
||||
val name: String? = null,
|
||||
val profilePicture: UserPic = UserPic.DEFAULT,
|
||||
val admin: Boolean = false,
|
||||
val supplement: Boolean = false,
|
||||
private val inviteStatus: InviteStatus = INVITE_NOT_SENT,
|
||||
private val promotionStatus: PromotionStatus = INVITE_NOT_SENT,
|
||||
private val removedStatus: RemovedStatus = 0,
|
||||
) {
|
||||
val accepted: Boolean get() = inviteStatus == 0 && !supplement
|
||||
val inviteNotSent: Boolean get() = inviteStatus == INVITE_NOT_SENT
|
||||
val invitePending: Boolean get() = inviteStatus > 0
|
||||
val inviteFailed: Boolean get() = inviteStatus == INVITE_STATUS_FAILED
|
||||
|
||||
val promotionNotSent: Boolean get() = promotionStatus == INVITE_NOT_SENT
|
||||
val promotionPending: Boolean get() = !admin && promotionStatus == INVITE_STATUS_SENT
|
||||
val promotionFailed: Boolean get() = !admin && promotionStatus == INVITE_STATUS_FAILED
|
||||
val promoted: Boolean get() = admin || promotionPending
|
||||
val removed: Boolean get() = removedStatus > 0
|
||||
val shouldRemoveMessages: Boolean get() = removedStatus == REMOVED_MEMBER_AND_MESSAGES
|
||||
|
||||
val isAdminOrBeingPromoted: Boolean get() = admin || promotionStatus == INVITE_STATUS_SENT
|
||||
|
||||
fun setPromoteSent(): GroupMember
|
||||
= copy(promotionStatus = INVITE_STATUS_SENT)
|
||||
|
||||
fun setPromoteFailed(): GroupMember
|
||||
= copy(promotionStatus = INVITE_STATUS_FAILED)
|
||||
|
||||
fun setRemoved(alsoRemoveMessages: Boolean): GroupMember
|
||||
= copy(removedStatus = if (alsoRemoveMessages) REMOVED_MEMBER_AND_MESSAGES else REMOVED_MEMBER)
|
||||
|
||||
fun setAccepted(): GroupMember
|
||||
= copy(inviteStatus = 0, supplement = false)
|
||||
|
||||
fun setInvited(): GroupMember
|
||||
= copy(inviteStatus = INVITE_STATUS_SENT)
|
||||
|
||||
fun setInviteFailed(): GroupMember = copy(inviteStatus = INVITE_STATUS_FAILED)
|
||||
fun setPromoteSuccess(): GroupMember = copy(admin = true, promotionStatus = 0)
|
||||
}
|
@@ -1,9 +1,27 @@
|
||||
package network.loki.messenger.libsession_util.util
|
||||
|
||||
object Sodium {
|
||||
|
||||
const val KICKED_DOMAIN = "SessionGroupKickedMessage"
|
||||
val KICKED_REGEX = Regex("05\\w{64}-\\d+")
|
||||
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
}
|
||||
external fun ed25519KeyPair(seed: ByteArray): KeyPair
|
||||
external fun ed25519PkToCurve25519(pk: ByteArray): ByteArray
|
||||
|
||||
external fun encryptForMultipleSimple(
|
||||
messages: Array<ByteArray>,
|
||||
recipients: Array<ByteArray>,
|
||||
ed25519SecretKey: ByteArray,
|
||||
domain: String
|
||||
): ByteArray
|
||||
|
||||
external fun decryptForMultipleSimple(
|
||||
encoded: ByteArray,
|
||||
ed25519SecretKey: ByteArray,
|
||||
senderPubKey: ByteArray,
|
||||
domain: String,
|
||||
): ByteArray?
|
||||
}
|
Reference in New Issue
Block a user