Skip to content

Commit

Permalink
v3.1 (build 249)
Browse files Browse the repository at this point in the history
  • Loading branch information
finiasz committed Jul 10, 2024
1 parent ee9d445 commit 868122e
Show file tree
Hide file tree
Showing 47 changed files with 792 additions and 781 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# Build 249 (3.1)
2024-07-10

- Fix a crash wish URL truncation
- Improve double-scan and invitation contact addition flows

# Build 248 (3.0)
2024-07-05

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,18 @@ public void callback(String notificationName, HashMap<String, Object> userInfo)
case ProtocolNotifications.NOTIFICATION_MUTUAL_SCAN_CONTACT_ADDED: {
Identity ownedIdentity = (Identity) userInfo.get(ProtocolNotifications.NOTIFICATION_MUTUAL_SCAN_CONTACT_ADDED_OWNED_IDENTITY_KEY);
Identity contactIdentity = (Identity) userInfo.get(ProtocolNotifications.NOTIFICATION_MUTUAL_SCAN_CONTACT_ADDED_CONTACT_IDENTITY_KEY);
byte[] nonce = (byte[]) userInfo.get(ProtocolNotifications.NOTIFICATION_MUTUAL_SCAN_CONTACT_ADDED_SIGNATURE_KEY);
byte[] signature = (byte[]) userInfo.get(ProtocolNotifications.NOTIFICATION_MUTUAL_SCAN_CONTACT_ADDED_SIGNATURE_KEY);

if (ownedIdentity == null || contactIdentity == null || nonce == null) {
if (ownedIdentity == null || contactIdentity == null) {
break;
}

HashMap<String, Object> engineInfo = new HashMap<>();
engineInfo.put(EngineNotifications.MUTUAL_SCAN_CONTACT_ADDED_BYTES_OWNED_IDENTITIY_KEY, ownedIdentity.getBytes());
engineInfo.put(EngineNotifications.MUTUAL_SCAN_CONTACT_ADDED_BYTES_CONTACT_IDENTITIY_KEY, contactIdentity.getBytes());
engineInfo.put(EngineNotifications.MUTUAL_SCAN_CONTACT_ADDED_NONCE_KEY, nonce);
if (signature != null) {
engineInfo.put(EngineNotifications.MUTUAL_SCAN_CONTACT_ADDED_SIGNATURE_KEY, signature);
}

engine.postEngineNotification(EngineNotifications.MUTUAL_SCAN_CONTACT_ADDED, engineInfo);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ public abstract class EngineNotifications {
public static final String MUTUAL_SCAN_CONTACT_ADDED = "engine_notification_mutual_scan_contact_added";
public static final String MUTUAL_SCAN_CONTACT_ADDED_BYTES_OWNED_IDENTITIY_KEY = "bytes_owned_identity"; // byte[]
public static final String MUTUAL_SCAN_CONTACT_ADDED_BYTES_CONTACT_IDENTITIY_KEY = "bytes_contact_identity"; // byte[]
public static final String MUTUAL_SCAN_CONTACT_ADDED_NONCE_KEY = "nonce"; // byte[]
public static final String MUTUAL_SCAN_CONTACT_ADDED_SIGNATURE_KEY = "signature"; // byte[]

public static final String APP_BACKUP_REQUESTED = "engine_notification_app_backup_requested";
public static final String APP_BACKUP_REQUESTED_BYTES_BACKUP_KEY_UID_KEY = "bytes_backup_key_uid"; // byte[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class ObvUrlIdentity {
public static final String URL_PROTOCOL_OLVID = "olvid";
public static final String URL_INVITATION_HOST = "invitation.olvid.io";

private static final Pattern INVITATION_PATTERN = Pattern.compile("(" + URL_PROTOCOL + "|" + URL_PROTOCOL_OLVID + ")" + Pattern.quote("://" + URL_INVITATION_HOST) + "/[#]?([-_a-zA-Z0-9]+)");
private static final Pattern INVITATION_PATTERN = Pattern.compile("(" + URL_PROTOCOL + "|" + URL_PROTOCOL_OLVID + ")" + Pattern.quote("://" + URL_INVITATION_HOST) + "/1?#([-_a-zA-Z0-9]+)");

public final Identity identity;
public final String displayName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@ public void onCancelCallback(Operation operation) {
break;
}
case DownloadAttachmentOperation.RFC_INVALID_SIGNED_URL: {
// TODO: refresh urls once per hour, at most
waitForRefreshedUrls(ownedIdentity, messageUid, attachmentNumber, priorityCategory, initialPriority);
refreshInboxAttachmentSignedUrlDelegate.refreshInboxAttachmentSignedUrl(ownedIdentity, messageUid, attachmentNumber);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,9 @@ public ConcreteProtocolState executeStep() throws Exception {
} else {
currentDevicePreKeyOnServer = null;
}
if (!Objects.equals(oldDevice.serverDeviceInfo, signedPreKeyAndServerInfo.serverDeviceInfo)) {
protocolManagerSession.identityDelegate.updateOwnedDevice(protocolManagerSession.session, getOwnedIdentity(), oldDevice.deviceUid, signedPreKeyAndServerInfo.serverDeviceInfo.displayName, signedPreKeyAndServerInfo.serverDeviceInfo.expirationTimestamp, signedPreKeyAndServerInfo.serverDeviceInfo.lastRegistrationTimestamp, null);
}
continue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import java.util.HashMap;

import io.olvid.engine.Logger;
import io.olvid.engine.crypto.PRNGService;
import io.olvid.engine.crypto.Signature;
import io.olvid.engine.datatypes.Constants;
Expand Down Expand Up @@ -474,6 +475,7 @@ public ConcreteProtocolState executeStep() throws Exception {
{
// verify the signature is fresh
if (MutualScanSignatureReceived.exists(protocolManagerSession, getOwnedIdentity(), receivedMessage.signature)) {
Logger.e("Mutual scan signature reuse!");
return new FinishedState();
}
}
Expand Down Expand Up @@ -655,6 +657,15 @@ public ConcreteProtocolState executeStep() throws Exception {
}
}

{
// send a notification so the app can automatically open the contact discussion
protocolManagerSession.session.addSessionCommitListener(() -> {
HashMap<String, Object> userInfo = new HashMap<>();
userInfo.put(ProtocolNotifications.NOTIFICATION_MUTUAL_SCAN_CONTACT_ADDED_OWNED_IDENTITY_KEY, getOwnedIdentity());
userInfo.put(ProtocolNotifications.NOTIFICATION_MUTUAL_SCAN_CONTACT_ADDED_CONTACT_IDENTITY_KEY, startState.bobIdentity);
protocolManagerSession.notificationPostingDelegate.postNotification(ProtocolNotifications.NOTIFICATION_MUTUAL_SCAN_CONTACT_ADDED, userInfo);
});
}
return new FinishedState();
}
}
Expand Down
4 changes: 2 additions & 2 deletions obv_messenger/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ android {
applicationId "io.olvid.messenger"
minSdkVersion 21
targetSdk 34
versionCode 248
versionName "3.0"
versionCode 249
versionName "3.1"
vectorDrawables.useSupportLibrary true
multiDexEnabled true
resourceConfigurations += ['en', 'fr']
Expand Down
45 changes: 28 additions & 17 deletions obv_messenger/app/src/main/java/io/olvid/messenger/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -640,8 +640,11 @@ public static void openLink(Context context, Uri uri) {
if (context == null || uri == null) {
return;
}

// first check if this is an Olvid link
boolean olvidLink = ObvLinkActivity.ANY_PATTERN.matcher(uri.toString()).find();
final AlertDialog.Builder builder = new SecureAlertDialogBuilder(context, R.style.CustomAlertDialog)
.setTitle(R.string.dialog_title_confirm_open_link)
.setTitle(olvidLink ? R.string.dialog_title_confirm_open_olvid_link : R.string.dialog_title_confirm_open_link)
.setMessage(uri.toString())
.setNeutralButton(R.string.button_label_copy, (dialog, which) -> {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(CLIPBOARD_SERVICE);
Expand All @@ -650,23 +653,30 @@ public static void openLink(Context context, Uri uri) {
toast(R.string.toast_message_link_copied, Toast.LENGTH_SHORT);
})
.setPositiveButton(R.string.button_label_ok, (dialog, which) -> {
try {
context.startActivity(new Intent(Intent.ACTION_VIEW, uri));

int unwraps = 0;
Context baseContext = context;
while (!(baseContext instanceof DiscussionActivity) && baseContext instanceof ContextThemeWrapper) {
baseContext = ((ContextThemeWrapper) baseContext).getBaseContext();
unwraps++;
if (unwraps > 10) {
break;
if (olvidLink) {
Intent intent = new Intent(context, MainActivity.class);
intent.setAction(MainActivity.LINK_ACTION);
intent.putExtra(MainActivity.LINK_URI_INTENT_EXTRA, uri.toString());
context.startActivity(intent);
} else {
try {
context.startActivity(new Intent(Intent.ACTION_VIEW, uri));

int unwraps = 0;
Context baseContext = context;
while (!(baseContext instanceof DiscussionActivity) && baseContext instanceof ContextThemeWrapper) {
baseContext = ((ContextThemeWrapper) baseContext).getBaseContext();
unwraps++;
if (unwraps > 10) {
break;
}
}
if (baseContext instanceof DiscussionActivity) {
((DiscussionActivity) baseContext).getDiscussionDelegate().doNotMarkAsReadOnPause();
}
} catch (Exception e) {
App.toast(R.string.toast_message_unable_to_open_url, Toast.LENGTH_SHORT);
}
if (baseContext instanceof DiscussionActivity) {
((DiscussionActivity) baseContext).getDiscussionDelegate().doNotMarkAsReadOnPause();
}
} catch (Exception e) {
App.toast(R.string.toast_message_unable_to_open_url, Toast.LENGTH_SHORT);
}
})
.setNegativeButton(R.string.button_label_cancel, null);
Expand Down Expand Up @@ -1081,8 +1091,9 @@ public static void setQrCodeImage(@NonNull ImageView imageView, @NonNull final S
int height = metrics.heightPixels;
final int size = Math.min(height, width);
final ImageView imageView1 = imageViewWeakReference.get();
final Bitmap scaledBitmap = Bitmap.createScaledBitmap(smallQrCodeBitmap, size, size, false);
if (imageView1 != null) {
new Handler(Looper.getMainLooper()).post(() -> imageView1.setImageBitmap(Bitmap.createScaledBitmap(smallQrCodeBitmap, size, size, false)));
new Handler(Looper.getMainLooper()).post(() -> imageView1.setImageBitmap(scaledBitmap));
}
} catch (Exception e) {
final ImageView imageView1 = imageViewWeakReference.get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ public void callback(String notificationName, final HashMap<String, Object> user
if (contact != null && contact.recentlyOnline != recentlyOnline) {
contact.recentlyOnline = recentlyOnline;
db.contactDao().updateRecentlyOnline(contact.bytesOwnedIdentity, contact.bytesContactIdentity, contact.recentlyOnline);
AppSingleton.updateContactCachedInfo(contact);
}
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class ObvLinkActivity : AppCompatActivity() {
val INVITATION_PATTERN: Pattern = Pattern.compile(
"(" + ObvUrlIdentity.URL_PROTOCOL + "|" + ObvUrlIdentity.URL_PROTOCOL_OLVID + ")" + Pattern.quote(
"://$URL_INVITATION_HOST"
) + "/#([-_a-zA-Z\\d]+)"
) + "/1?#([-_a-zA-Z\\d]+)"
)

@JvmField
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,17 @@ class InitialView : View {
init()
}

fun reset() {
bytes = null
bitmap = null
keycloakCertified = false
locked = false
inactive = false
notOneToOne = false
recentlyOnline = true
contactTrustLevel = null
}

fun setKeycloakCertified(keycloakCertified: Boolean) {
if (this.keycloakCertified != keycloakCertified) {
bitmap = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.util.HashMap;
import java.util.Locale;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import io.olvid.engine.Logger;
Expand All @@ -48,6 +49,7 @@
public class StringUtils {

public static final Pattern unAccentPattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
public static final Pattern positionAndCompanyPattern = Pattern.compile("^([^(]+) \\(.+\\)$");

public static String getNiceDurationString(Context context, long duration) {
if (duration < 60) {
Expand Down Expand Up @@ -147,6 +149,14 @@ public static String getInitial(String name) {
return name.substring(0, offset).toUpperCase(Locale.getDefault());
}

public static String removeCompanyFromDisplayName(@NonNull String displayName) {
Matcher matcher = positionAndCompanyPattern.matcher(displayName);
if (matcher.find()) {
return matcher.group(1);
}
return displayName;
}

public static boolean isShortEmojiString(String text, int maxLength) {
// Alternate method based on EmojiCompat library --> we use the legacy method for now, it still works well :)
// CharSequence emojiSequence = EmojiCompat.get().process(text, 0, text.length(), maxLength);
Expand Down Expand Up @@ -276,10 +286,10 @@ public static String joinContactDisplayNames(String[] groupMembersNames) {
}


private static final String DATA_DIR = Environment.getDataDirectory().toString();

// used to validate an externally received Uri and make sure it does not point to an internal file
public static boolean validateUri(Uri uri) {
String DATA_DIR = Environment.getDataDirectory().toString();
boolean valid = false;
if (uri != null && uri.getPath() != null) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,20 @@ public interface Group2Dao {
" WHERE " + Group2.CUSTOM_PHOTO_URL + " IS NOT NULL")
List<String> getAllCustomPhotoUrls();

@Query("SELECT EXISTS (" +
"SELECT 1 FROM " + Group2Member.TABLE_NAME +
" WHERE " + Group2Member.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " +
" AND " + Group2Member.BYTES_GROUP_IDENTIFIER + " = :bytesGroupIdentifier " +
" AND " + Group2Member.BYTES_CONTACT_IDENTITY + " = :bytesContactIdentity " +
") " +
" OR EXISTS (" +
"SELECT 1 FROM " + Group2PendingMember.TABLE_NAME +
" WHERE " + Group2PendingMember.BYTES_OWNED_IDENTITY + " = :bytesOwnedIdentity " +
" AND " + Group2PendingMember.BYTES_GROUP_IDENTIFIER + " = :bytesGroupIdentifier " +
" AND " + Group2PendingMember.BYTES_CONTACT_IDENTITY + " = :bytesContactIdentity " +
")")
boolean isContactAMemberOrPendingMember(byte[] bytesOwnedIdentity, byte[] bytesGroupIdentifier, byte[] bytesContactIdentity);


class GroupOrGroup2 {
@Embedded(prefix = "group_")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,13 @@

import java.util.UUID;

import io.olvid.engine.engine.types.JsonIdentityDetails;
import io.olvid.engine.engine.types.ObvDialog;
import io.olvid.messenger.App;
import io.olvid.messenger.AppSingleton;
import io.olvid.messenger.R;
import io.olvid.messenger.customClasses.StringUtils;
import io.olvid.messenger.settings.SettingsActivity;

@SuppressWarnings("CanBeFinal")
@Entity(tableName = Invitation.TABLE_NAME,
Expand Down Expand Up @@ -108,14 +112,29 @@ public Invitation(ObvDialog associatedDialog, long invitationTimestamp, long dis
@NonNull
public String getStatusText() {
switch (associatedDialog.getCategory().getId()) {
case ObvDialog.Category.INVITE_SENT_DIALOG_CATEGORY:
return App.getContext().getString(R.string.invitation_status_invite_sent);
case ObvDialog.Category.INVITE_SENT_DIALOG_CATEGORY: {
String shortName = StringUtils.removeCompanyFromDisplayName(associatedDialog.getCategory().getContactDisplayNameOrSerializedDetails());
return App.getContext().getString(R.string.invitation_status_invite_sent, shortName);
}
case ObvDialog.Category.ACCEPT_INVITE_DIALOG_CATEGORY:
return App.getContext().getString(R.string.invitation_status_accept_invite);
try {
String displayName = AppSingleton.getJsonObjectMapper()
.readValue(associatedDialog.getCategory().getContactDisplayNameOrSerializedDetails(), JsonIdentityDetails.class)
.formatDisplayName(SettingsActivity.getContactDisplayNameFormat(), SettingsActivity.getUppercaseLastName());
return App.getContext().getString(R.string.invitation_status_accept_invite_from, displayName);
} catch (Exception ignored) {
return App.getContext().getString(R.string.invitation_status_accept_invite);
}
case ObvDialog.Category.SAS_EXCHANGE_DIALOG_CATEGORY:
return App.getContext().getString(R.string.invitation_status_exchange_sas);
case ObvDialog.Category.SAS_CONFIRMED_DIALOG_CATEGORY:
return App.getContext().getString(R.string.invitation_status_give_him_sas);
try {
String displayName = AppSingleton.getJsonObjectMapper()
.readValue(associatedDialog.getCategory().getContactDisplayNameOrSerializedDetails(), JsonIdentityDetails.class)
.formatDisplayName(SettingsActivity.getContactDisplayNameFormat(), SettingsActivity.getUppercaseLastName());
return App.getContext().getString(R.string.invitation_status_exchange_sas_with, displayName);
} catch (Exception ignored) {
return App.getContext().getString(R.string.invitation_status_exchange_sas);
}
case ObvDialog.Category.INVITE_ACCEPTED_DIALOG_CATEGORY:
return App.getContext().getString(R.string.invitation_status_invite_accepted);
case ObvDialog.Category.ACCEPT_MEDIATOR_INVITE_DIALOG_CATEGORY:
Expand Down
Loading

0 comments on commit 868122e

Please sign in to comment.