Don't upper case QR code that has a URL.

Firstly, this causes #721, possibly due to a bug in "Barcode
Scanner" whereby it seems to ignore the scheme when in caps,
assuming it is "http".

The relevant RFC is:

> RFC3986 (Uniform Resource Identifier (URI): Generic Syntax

In section 3.1, it describes the scheme:

> Although schemes are case-insensitive, the canonical form is
> lowercase and documents that specify schemes must do so with
> lowercase letters.  An implementation should accept uppercase
> letters as equivalent to lowercase in scheme names (e.g., allow
> "HTTP" as well as "http") for the sake of robustness but should
> only produce lowercase scheme names for consistency.

Secondly, it is not valid to uppercase URLs at will. Although it
seems that there is some sort of more-compact-QR-generating-logic
that doesn't justify this. Funnily enough, I can't find anything
in RFC3986 about the case-insensitivity of URI paths. However
consider the following:

 * https://i.imgur.com/fn33EcW.jpg

That is a valid path to an image. If we upper case it:

 * HTTPS://I.IMGUR.COM/FN33ECW.JPG

or lower case it:

 * https://i.imgur.com/fn33ecw.jpg

Then the server is entitled to treat it differently and indeed
it does. Both the upper case and lower case are no both 404's.
This commit is contained in:
Peter Serwylo 2016-07-22 06:56:08 +10:00
parent b3d88aa333
commit 10144f72c9
2 changed files with 3 additions and 12 deletions

View File

@ -38,8 +38,6 @@ import org.fdroid.fdroid.data.Repo;
import org.fdroid.fdroid.data.RepoProvider; import org.fdroid.fdroid.data.RepoProvider;
import org.fdroid.fdroid.data.Schema.RepoTable; import org.fdroid.fdroid.data.Schema.RepoTable;
import java.util.Locale;
public class RepoDetailsActivity extends ActionBarActivity { public class RepoDetailsActivity extends ActionBarActivity {
private static final String TAG = "RepoDetailsActivity"; private static final String TAG = "RepoDetailsActivity";
@ -112,7 +110,7 @@ public class RepoDetailsActivity extends ActionBarActivity {
Uri uri = Uri.parse(repo.address); Uri uri = Uri.parse(repo.address);
uri = uri.buildUpon().appendQueryParameter("fingerprint", repo.fingerprint).build(); uri = uri.buildUpon().appendQueryParameter("fingerprint", repo.fingerprint).build();
String qrUriString = uri.toString().toUpperCase(Locale.ENGLISH); String qrUriString = uri.toString();
new QrGenAsyncTask(this, R.id.qr_code).execute(qrUriString); new QrGenAsyncTask(this, R.id.qr_code).execute(qrUriString);
} }

View File

@ -132,19 +132,12 @@ public class WifiQrView extends ScrollView implements SwapWorkflowActivity.Inner
TextView ipAddressView = (TextView) findViewById(R.id.device_ip_address); TextView ipAddressView = (TextView) findViewById(R.id.device_ip_address);
ipAddressView.setText(buttonLabel); ipAddressView.setText(buttonLabel);
/*
* Set URL to UPPER for compact QR Code, FDroid will translate it back.
* Remove the SSID from the query string since SSIDs are case-sensitive.
* Instead the receiver will have to rely on the BSSID to find the right
* wifi AP to join. Lots of QR Scanners are buggy and do not respect
* custom URI schemes, so we have to use http:// or https:// :-(
*/
Uri sharingUri = Utils.getSharingUri(FDroidApp.repo); Uri sharingUri = Utils.getSharingUri(FDroidApp.repo);
String qrUriString = (scheme + sharingUri.getHost()).toUpperCase(Locale.ENGLISH); String qrUriString = scheme + sharingUri.getHost();
if (sharingUri.getPort() != 80) { if (sharingUri.getPort() != 80) {
qrUriString += ":" + sharingUri.getPort(); qrUriString += ":" + sharingUri.getPort();
} }
qrUriString += sharingUri.getPath().toUpperCase(Locale.ENGLISH); qrUriString += sharingUri.getPath();
boolean first = true; boolean first = true;
// Andorid provides an API for getting the query parameters and iterating over them: // Andorid provides an API for getting the query parameters and iterating over them: