split out new, incoming repo configs into a separate class: NewRepoConfig

The swap stuff will also need to handle incoming Intents that represent
new repos, so the parsing logic is now its own class NewRepoConfig, which
is something like the Repo class, but using getters instead of properties.
Since the new repo data does not change once FDroid receives it, the only
way to set the values of a NewRepoConfig is via the constructor.

This is based on some incomplete work from @pserwylo:
71cb12ef5c (diff-6)
and
71cb12ef5c (diff-7)
This commit is contained in:
Hans-Christoph Steiner 2014-07-11 16:58:57 -04:00
parent 92199f2f01
commit a525bca1cf
2 changed files with 158 additions and 63 deletions

View File

@ -0,0 +1,137 @@
package org.fdroid.fdroid.data;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
import org.fdroid.fdroid.R;
import java.util.Arrays;
import java.util.Locale;
public class NewRepoConfig {
private String errorMessage;
private boolean isValidRepo;
private String uriString;
private Uri uri;
private String host;
private int port = -1;
private String scheme;
private String fingerprint;
private String bssid;
private String ssid;
public NewRepoConfig(Context context, Intent intent) {
/* an URL from a click, NFC, QRCode scan, etc */
uri = intent.getData();
if (uri == null) {
isValidRepo = false;
return;
}
// scheme and host should only ever be pure ASCII aka Locale.ENGLISH
scheme = intent.getScheme();
host = uri.getHost();
port = uri.getPort();
if (TextUtils.isEmpty(scheme) || TextUtils.isEmpty(host)) {
errorMessage = String.format(context.getString(R.string.malformed_repo_uri),
uri);
isValidRepo = false;
return;
}
if (Arrays.asList("FDROIDREPO", "FDROIDREPOS").contains(scheme)) {
/*
* QRCodes are more efficient in all upper case, so QR URIs are
* encoded in all upper case, then forced to lower case. Checking if
* the special F-Droid scheme being all is upper case means it
* should be downcased.
*/
uri = Uri.parse(uri.toString().toLowerCase(Locale.ENGLISH));
} else if (uri.getPath().endsWith("/FDROID/REPO")) {
/*
* some QR scanners chop off the fdroidrepo:// and just try http://,
* then the incoming URI does not get downcased properly, and the
* query string is stripped off. So just downcase the path, and
* carry on to get something working.
*/
uri = Uri.parse(uri.toString().toLowerCase(Locale.ENGLISH));
}
// make scheme and host lowercase so they're readable in dialogs
scheme = scheme.toLowerCase(Locale.ENGLISH);
host = host.toLowerCase(Locale.ENGLISH);
fingerprint = uri.getQueryParameter("fingerprint");
bssid = uri.getQueryParameter("bssid");
ssid = uri.getQueryParameter("ssid");
Log.i("RepoListFragment", "onCreate " + fingerprint);
if (Arrays.asList("fdroidrepos", "fdroidrepo", "https", "http").contains(scheme)) {
uriString = sanitizeRepoUri(uri);
}
this.isValidRepo = true;
}
public String getBssid() {
return bssid;
}
public String getSsid() {
return ssid;
}
public int getPort() {
return port;
}
public String getUriString() {
return uriString;
}
public String getHost() {
return host;
}
public String getScheme() {
return scheme;
}
public String getFingerprint() {
return fingerprint;
}
public boolean isValidRepo() {
return isValidRepo;
}
/*
* The port starts out as 8888, but if there is a conflict, it will be
* incremented until there is a free port found.
*/
public boolean looksLikeLocalRepo() {
return (port >= 8888 && host.matches("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+"));
}
public String getErrorMessage() {
return errorMessage;
}
/** Sanitize and format an incoming repo URI for function and readability */
public static String sanitizeRepoUri(Uri uri) {
String scheme = uri.getScheme();
String host = uri.getHost();
return uri.toString()
.replaceAll("\\?.*$", "") // remove the whole query
.replaceAll("/*$", "") // remove all trailing slashes
.replace(host, host.toLowerCase(Locale.ENGLISH))
.replace(scheme, scheme.toLowerCase(Locale.ENGLISH))
.replace("fdroidrepo", "http") // proper repo address
.replace("/FDROID/REPO", "/fdroid/repo"); // for QR FDroid path
}
}

View File

@ -60,6 +60,7 @@ import org.fdroid.fdroid.ProgressListener;
import org.fdroid.fdroid.R; import org.fdroid.fdroid.R;
import org.fdroid.fdroid.UpdateService; import org.fdroid.fdroid.UpdateService;
import org.fdroid.fdroid.compat.ClipboardCompat; import org.fdroid.fdroid.compat.ClipboardCompat;
import org.fdroid.fdroid.data.NewRepoConfig;
import org.fdroid.fdroid.data.Repo; import org.fdroid.fdroid.data.Repo;
import org.fdroid.fdroid.data.RepoProvider; import org.fdroid.fdroid.data.RepoProvider;
import org.fdroid.fdroid.net.MDnsHelper; import org.fdroid.fdroid.net.MDnsHelper;
@ -443,73 +444,30 @@ public class ManageReposActivity extends ActionBarActivity {
private void addRepoFromIntent(Intent intent) { private void addRepoFromIntent(Intent intent) {
/* an URL from a click, NFC, QRCode scan, etc */ /* an URL from a click, NFC, QRCode scan, etc */
Uri uri = intent.getData(); NewRepoConfig newRepoConfig = new NewRepoConfig(this, intent);
if (uri != null) { if (newRepoConfig.isValidRepo()) {
// scheme and host should only ever be pure ASCII aka Locale.ENGLISH importRepo(newRepoConfig.getUriString(), newRepoConfig.getFingerprint());
String scheme = intent.getScheme(); checkIfNewRepoOnSameWifi(newRepoConfig);
String host = uri.getHost(); } else if (newRepoConfig.getErrorMessage() != null) {
if (scheme == null || host == null) { Toast.makeText(this, newRepoConfig.getErrorMessage(), Toast.LENGTH_LONG).show();
String msg = String.format(getString(R.string.malformed_repo_uri), uri);
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
return;
} }
if (scheme.equals("FDROIDREPO") || scheme.equals("FDROIDREPOS")) {
/*
* QRCodes are more efficient in all upper case, so QR URIs are
* encoded in all upper case, then forced to lower case.
* Checking if the special F-Droid scheme being all is upper
* case means it should be downcased.
*/
uri = Uri.parse(uri.toString().toLowerCase(Locale.ENGLISH));
} else if (uri.getPath().startsWith("/FDROID/REPO")) {
/*
* some QR scanners chop off the fdroidrepo:// and just try
* http://, then the incoming URI does not get downcased
* properly, and the query string is stripped off. So just
* downcase the path, and carry on to get something working.
*/
uri = Uri.parse(uri.toString().toLowerCase(Locale.ENGLISH));
} }
// make scheme and host lowercase so they're readable in dialogs
scheme = scheme.toLowerCase(Locale.ENGLISH);
host = host.toLowerCase(Locale.ENGLISH);
String fingerprint = uri.getQueryParameter("fingerprint");
Log.i("RepoListFragment", "onCreate " + fingerprint);
if (scheme.equals("fdroidrepos") || scheme.equals("fdroidrepo")
|| scheme.equals("https") || scheme.equals("http")) {
/* sanitize and format for function and readability */
String uriString = uri.toString()
.replaceAll("\\?.*$", "") // remove the whole query
.replaceAll("/*$", "") // remove all trailing slashes
.replace(uri.getHost(), host) // downcase host name
.replace(intent.getScheme(), scheme) // downcase scheme
.replace("fdroidrepo", "http"); // proper repo address
importRepo(uriString, fingerprint);
private void checkIfNewRepoOnSameWifi(NewRepoConfig newRepo) {
// if this is a local repo, check we're on the same wifi // if this is a local repo, check we're on the same wifi
String uriBssid = uri.getQueryParameter("bssid"); if (!TextUtils.isEmpty(newRepo.getBssid())) {
if (!TextUtils.isEmpty(uriBssid)) {
if (uri.getPort() != 8888
&& !host.matches("[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+")) {
Log.i("ManageRepo", "URI is not local repo: " + uri);
return;
}
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo(); WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String bssid = wifiInfo.getBSSID().toLowerCase(Locale.ENGLISH); String bssid = wifiInfo.getBSSID().toLowerCase(Locale.ENGLISH);
uriBssid = Uri.decode(uriBssid).toLowerCase(Locale.ENGLISH); String newRepoBssid = Uri.decode(newRepo.getBssid()).toLowerCase(Locale.ENGLISH);
if (!bssid.equals(uriBssid)) { if (!bssid.equals(newRepoBssid)) {
String msg = String.format(getString(R.string.not_on_same_wifi), String msg = String.format(getString(R.string.not_on_same_wifi), newRepo.getSsid());
uri.getQueryParameter("ssid"));
Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
} }
// TODO we should help the user to the right thing here, // TODO we should help the user to the right thing here,
// instead of just showing a message! // instead of just showing a message!
} }
} }
}
}
public static class RepoListFragment extends ListFragment public static class RepoListFragment extends ListFragment
implements LoaderManager.LoaderCallbacks<Cursor>, RepoAdapter.EnabledListener { implements LoaderManager.LoaderCallbacks<Cursor>, RepoAdapter.EnabledListener {