mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
[android] Show dialog when (pending) contact already exists
If two different people sent the same link, show warning dialog to the user to prevent a social attack trying to discover contact relationships.
This commit is contained in:
@@ -9,6 +9,7 @@ import android.support.annotation.Nullable;
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.UnsupportedVersionException;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.contact.PendingContact;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
@@ -25,6 +26,7 @@ import javax.inject.Inject;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.bramble.api.contact.HandshakeLinkConstants.LINK_REGEX;
|
||||
import static org.briarproject.bramble.api.contact.PendingContactState.FAILED;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@NotNullByDefault
|
||||
@@ -118,4 +120,18 @@ public class AddContactViewModel extends AndroidViewModel {
|
||||
return addContactResult;
|
||||
}
|
||||
|
||||
public void updatePendingContact(String name, PendingContact p) {
|
||||
dbExecutor.execute(() -> {
|
||||
if (contactManager.getPendingContactState(p.getId()) == FAILED) {
|
||||
try {
|
||||
contactManager.removePendingContact(p.getId());
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
addContactResult.postValue(new LiveResult<>(e));
|
||||
}
|
||||
addContact(name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,10 +2,15 @@ package org.briarproject.briar.android.contact.add.remote;
|
||||
|
||||
import android.arch.lifecycle.ViewModelProvider;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.design.widget.TextInputEditText;
|
||||
import android.support.design.widget.TextInputLayout;
|
||||
import android.support.v7.app.AlertDialog.Builder;
|
||||
import android.text.Editable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -15,6 +20,10 @@ import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.bramble.api.UnsupportedVersionException;
|
||||
import org.briarproject.bramble.api.contact.PendingContact;
|
||||
import org.briarproject.bramble.api.db.ContactExistsException;
|
||||
import org.briarproject.bramble.api.db.PendingContactExistsException;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
@@ -24,9 +33,13 @@ import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.support.v4.content.ContextCompat.getColor;
|
||||
import static android.support.v4.content.ContextCompat.getDrawable;
|
||||
import static android.support.v4.graphics.drawable.DrawableCompat.setTint;
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static android.widget.Toast.LENGTH_LONG;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||
import static org.briarproject.bramble.util.StringUtils.utf8IsTooLong;
|
||||
|
||||
@@ -107,23 +120,93 @@ public class NicknameFragment extends BaseFragment {
|
||||
|
||||
viewModel.getAddContactResult().observe(this, result -> {
|
||||
if (result == null) return;
|
||||
if (result.hasError()) {
|
||||
int stringRes;
|
||||
if (result
|
||||
.getException() instanceof UnsupportedVersionException) {
|
||||
stringRes = R.string.unsupported_link;
|
||||
} else {
|
||||
stringRes = R.string.adding_contact_error;
|
||||
}
|
||||
Toast.makeText(getContext(), stringRes, LENGTH_LONG).show();
|
||||
} else {
|
||||
Intent intent = new Intent(getActivity(),
|
||||
PendingContactListActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
finish();
|
||||
if (result.hasError()) handleException(name, result.getException());
|
||||
else showPendingContactListActivity();
|
||||
});
|
||||
viewModel.addContact(name);
|
||||
}
|
||||
|
||||
private void showPendingContactListActivity() {
|
||||
Intent intent = new Intent(getActivity(),
|
||||
PendingContactListActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void handleException(String name, @Nullable Exception e) {
|
||||
if (e instanceof ContactExistsException) {
|
||||
ContactExistsException ce = (ContactExistsException) e;
|
||||
handleExistingContact(name, ce.getRemoteAuthor());
|
||||
} else if (e instanceof PendingContactExistsException) {
|
||||
PendingContactExistsException pe =
|
||||
(PendingContactExistsException) e;
|
||||
handleExistingPendingContact(name, pe.getPendingContact());
|
||||
} else if (e instanceof UnsupportedVersionException) {
|
||||
int stringRes = R.string.unsupported_link;
|
||||
Toast.makeText(getContext(), stringRes, LENGTH_LONG).show();
|
||||
finish();
|
||||
} else {
|
||||
int stringRes = R.string.adding_contact_error;
|
||||
Toast.makeText(getContext(), stringRes, LENGTH_LONG).show();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleExistingContact(String name, Author existing) {
|
||||
OnClickListener listener = (d, w) -> {
|
||||
d.dismiss();
|
||||
String str = getString(R.string.contact_already_exists, name);
|
||||
Toast.makeText(getContext(), str, LENGTH_LONG).show();
|
||||
finish();
|
||||
};
|
||||
showSameLinkDialog(existing.getName(), name,
|
||||
R.string.duplicate_link_dialog_text_1_contact, listener);
|
||||
}
|
||||
|
||||
private void handleExistingPendingContact(String name, PendingContact p) {
|
||||
OnClickListener listener = (d, w) -> {
|
||||
viewModel.updatePendingContact(name, p);
|
||||
Toast.makeText(getContext(), R.string.pending_contact_updated_toast,
|
||||
LENGTH_LONG).show();
|
||||
d.dismiss();
|
||||
showPendingContactListActivity();
|
||||
};
|
||||
showSameLinkDialog(p.getAlias(), name,
|
||||
R.string.duplicate_link_dialog_text_1, listener);
|
||||
}
|
||||
|
||||
private void showSameLinkDialog(String name1, String name2,
|
||||
@StringRes int existsRes, OnClickListener samePersonListener) {
|
||||
Context ctx = requireContext();
|
||||
Builder b = new Builder(ctx, R.style.BriarDialogTheme_Neutral);
|
||||
b.setTitle(getString(R.string.duplicate_link_dialog_title));
|
||||
String msg = getString(existsRes, name1) + "\n\n" +
|
||||
getString(R.string.duplicate_link_dialog_text_2, name2, name1);
|
||||
b.setMessage(msg);
|
||||
b.setPositiveButton(R.string.same_person_button, samePersonListener);
|
||||
b.setNegativeButton(R.string.different_person_button, (d, w) -> {
|
||||
d.dismiss();
|
||||
showWarningDialog(name1, name2);
|
||||
});
|
||||
b.setCancelable(false);
|
||||
b.show();
|
||||
}
|
||||
|
||||
private void showWarningDialog(String name1, String name2) {
|
||||
Context ctx = requireContext();
|
||||
Builder b = new Builder(ctx, R.style.BriarDialogTheme);
|
||||
Drawable icon = getDrawable(ctx, R.drawable.alerts_and_states_error);
|
||||
setTint(requireNonNull(icon), getColor(ctx, R.color.color_primary));
|
||||
b.setIcon(icon);
|
||||
b.setTitle(getString(R.string.duplicate_link_dialog_title));
|
||||
b.setMessage(
|
||||
getString(R.string.duplicate_link_dialog_text_3, name1, name2));
|
||||
b.setPositiveButton(R.string.ok, (d, w) -> {
|
||||
d.dismiss();
|
||||
finish();
|
||||
});
|
||||
b.setCancelable(false);
|
||||
b.show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,8 +62,7 @@ public class ContactExchangeActivity extends KeyAgreementActivity {
|
||||
@UiThread
|
||||
private void contactExchangeSucceeded(Author remoteAuthor) {
|
||||
String contactName = remoteAuthor.getName();
|
||||
String format = getString(R.string.contact_added_toast);
|
||||
String text = String.format(format, contactName);
|
||||
String text = getString(R.string.contact_added_toast, contactName);
|
||||
Toast.makeText(this, text, LENGTH_LONG).show();
|
||||
supportFinishAfterTransition();
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
<string name="adding_contact_slow_text">添加此联系人比通常花费了更多时间。\n\n请检查您的联系人是否收到您的链接并已添加您:</string>
|
||||
<string name="offline_state">无网络连接</string>
|
||||
<string name="duplicate_link_dialog_title">重复的链接</string>
|
||||
<string name="duplicate_link_dialog_text_1">您已经有此链接的待处理联系人:</string>
|
||||
<string name="duplicate_link_dialog_text_1">您已经有此链接的待处理联系人:%s</string>
|
||||
<!--This is a question asking whether two nicknames refer to the same person-->
|
||||
<string name="duplicate_link_dialog_text_2">%s 和 %s 是同一个人吗?</string>
|
||||
<!--This is a button for answering that two nicknames do indeed refer to the same person. This
|
||||
|
||||
@@ -227,6 +227,7 @@
|
||||
<string name="offline_state">No Internet connection</string>
|
||||
<string name="duplicate_link_dialog_title">Duplicate Link</string>
|
||||
<string name="duplicate_link_dialog_text_1">You already have a pending contact with this link: %s</string>
|
||||
<string name="duplicate_link_dialog_text_1_contact">You already have a contact with this link: %s</string>
|
||||
<!-- This is a question asking whether two nicknames refer to the same person -->
|
||||
<string name="duplicate_link_dialog_text_2">Are %s and %s the same person?</string>
|
||||
<!-- This is a button for answering that two nicknames do indeed refer to the same person. This
|
||||
|
||||
Reference in New Issue
Block a user