diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeActivity.java
index 3435f0858..de1618a98 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeActivity.java
@@ -17,6 +17,7 @@ import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener
import org.briarproject.briar.api.messaging.MessagingManager;
import java.util.logging.Logger;
+import java.util.regex.Pattern;
import javax.annotation.Nullable;
import javax.inject.Inject;
@@ -41,7 +42,10 @@ public class ContactLinkExchangeActivity extends BriarActivity implements
private static final Logger LOG =
Logger.getLogger(ContactLinkExchangeActivity.class.getName());
- static final String OUR_LINK = "briar://" + getRandomBase32String(128);
+ static final int LINK_LENGTH = 128;
+ static final Pattern LINK_REGEX =
+ Pattern.compile("(briar://)?([a-z2-7]{" + LINK_LENGTH + "})");
+ static final String OUR_LINK = "briar://" + getRandomBase32String(LINK_LENGTH);;
@Inject
LifecycleManager lifecycleManager;
@@ -104,9 +108,8 @@ public class ContactLinkExchangeActivity extends BriarActivity implements
}
}
- boolean isBriarLink(CharSequence s) {
- String link = s.toString().trim();
- return link.matches("^(briar://)?[a-z2-7]{64}$");
+ boolean isBriarLink(@Nullable CharSequence s) {
+ return s != null && LINK_REGEX.matcher(s).matches();
}
void scanCode() {
@@ -132,7 +135,7 @@ public class ContactLinkExchangeActivity extends BriarActivity implements
AlarmManager alarmManager =
(AlarmManager) requireNonNull(getSystemService(ALARM_SERVICE));
- double random = getPseudoRandom(link, OUR_LINK);
+ double random = getPseudoRandom(link, OUR_LINK.replace("briar://", ""));
long m = MINUTES.toMillis(1);
long fromNow = (long) (-m * Math.log(random));
LOG.info("Delay " + fromNow + " ms based on seed " + random);
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeFragment.java
index 18b059d33..2b3f072dc 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeFragment.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/contact/ContactLinkExchangeFragment.java
@@ -6,6 +6,8 @@ import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
+import android.support.design.widget.TextInputEditText;
+import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.TextWatcher;
@@ -13,7 +15,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
-import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
@@ -21,6 +22,8 @@ import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
+import java.util.regex.Matcher;
+
import javax.annotation.Nullable;
import static android.content.Context.CLIPBOARD_SERVICE;
@@ -31,6 +34,7 @@ import static android.support.v4.graphics.drawable.DrawableCompat.setTint;
import static android.support.v4.graphics.drawable.DrawableCompat.wrap;
import static android.widget.Toast.LENGTH_SHORT;
import static java.util.Objects.requireNonNull;
+import static org.briarproject.briar.android.contact.ContactLinkExchangeActivity.LINK_REGEX;
import static org.briarproject.briar.android.contact.ContactLinkExchangeActivity.OUR_LINK;
import static org.briarproject.briar.android.util.UiUtils.resolveColorAttribute;
@@ -48,8 +52,8 @@ public class ContactLinkExchangeFragment extends BaseFragment
}
private ClipboardManager clipboard;
- private EditText linkInput;
- private EditText contactNameInput;
+ private TextInputLayout linkInputLayout;
+ private TextInputEditText linkInput, contactNameInput;
private Button addButton;
@Override
@@ -92,6 +96,7 @@ public class ContactLinkExchangeFragment extends BaseFragment
contactNameInput.setCompoundDrawables(drawable, null, null, null);
}
+ linkInputLayout = v.findViewById(R.id.linkInputLayout);
linkInput = v.findViewById(R.id.linkInput);
if (SDK_INT < 23) {
Drawable drawable = wrap(linkInput.getCompoundDrawables()[0]);
@@ -166,21 +171,38 @@ public class ContactLinkExchangeFragment extends BaseFragment
}
private void updateAddButtonState() {
- addButton.setEnabled(contactNameInput.getText().length() > 0 &&
- isBriarLink(linkInput.getText().toString()));
+ boolean validContactName = contactNameInput.getText() != null &&
+ contactNameInput.getText().length() > 0;
+ boolean briarLink = isBriarLink(linkInput.getText());
+ if (briarLink) {
+ linkInputLayout.setErrorEnabled(false);
+ } else {
+ linkInputLayout.setError("Invalid link");
+ }
+ addButton.setEnabled(validContactName && briarLink);
}
- private boolean isBriarLink(CharSequence s) {
+ private boolean isBriarLink(@Nullable CharSequence s) {
ContactLinkExchangeActivity activity = getCastActivity();
return activity != null && activity.isBriarLink(s);
}
+ @Nullable
+ private String getLink() {
+ Matcher matcher = LINK_REGEX.matcher(linkInput.getText());
+ if (matcher.matches()) // needs to be called before groups become available
+ return matcher.group(2);
+ else
+ return null;
+ }
+
private void onAddButtonClicked() {
ContactLinkExchangeActivity activity = getCastActivity();
if (activity == null) return;
- String linkText = linkInput.getText().toString();
- if (linkText.equals(OUR_LINK)) {
+ String linkText = getLink();
+ if (linkText == null) throw new AssertionError();
+ if (OUR_LINK.equals("briar://" + linkText)) {
new AlertDialog.Builder(activity, R.style.BriarDialogTheme_Neutral)
.setMessage(
"Add the link you get from your contact, not your own link.")
diff --git a/briar-android/src/main/res/layout/fragment_contact_link_exchange.xml b/briar-android/src/main/res/layout/fragment_contact_link_exchange.xml
index f4762acda..e4ed7cbe2 100644
--- a/briar-android/src/main/res/layout/fragment_contact_link_exchange.xml
+++ b/briar-android/src/main/res/layout/fragment_contact_link_exchange.xml
@@ -11,37 +11,55 @@
android:layout_height="wrap_content"
android:padding="@dimen/margin_large">
-
+ app:layout_constraintTop_toBottomOf="@+id/pasteButton">
-
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@+id/copyButton">
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@+id/linkInputLayout"/>
@@ -164,7 +182,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/contactNameInput"
+ app:layout_constraintTop_toBottomOf="@+id/contactNameLayout"
tools:enabled="true"/>