From b1c3d647484ce5c2a5a316da35c5ba9d6a55b461 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 13 Jun 2018 17:45:18 +0200 Subject: [PATCH] add expert option to send debug version/UUID on each HTTP download When debugging issues, tracking the client can be quite useful. This makes an "Expert" preference that adds the app version and a randomly generated, stored UUID to the query string each time it downloads an index or an app package. This is also useful in whitelabeling, for use cases where there needs to be some kind of identifier to make it work. --- app/src/basic/res/xml/preferences.xml | 6 ++++ .../java/org/fdroid/fdroid/FDroidApp.java | 35 ++++++++++++++++++- .../java/org/fdroid/fdroid/Preferences.java | 9 +++++ .../java/org/fdroid/fdroid/RepoUpdater.java | 7 +--- .../org/fdroid/fdroid/net/HttpDownloader.java | 32 ++++++++++++++++- app/src/main/res/values/strings.xml | 3 ++ app/src/main/res/xml/preferences.xml | 6 ++++ 7 files changed, 90 insertions(+), 8 deletions(-) diff --git a/app/src/basic/res/xml/preferences.xml b/app/src/basic/res/xml/preferences.xml index 6744145bb..ceccd9c9f 100644 --- a/app/src/basic/res/xml/preferences.xml +++ b/app/src/basic/res/xml/preferences.xml @@ -150,6 +150,12 @@ android:summary="@string/hide_all_notifications_summary" android:defaultValue="false" android:dependency="expert"/> + + * Copyright (C) 2014-2018 Hans-Christoph Steiner + * Copyright (C) 2015-2016 Daniel Martí + * Copyright (c) 2018 Senecto Limited * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -33,11 +37,13 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.graphics.Bitmap; +import android.net.Uri; import android.os.Build; import android.os.Environment; import android.os.StrictMode; import android.support.v4.util.LongSparseArray; import android.text.TextUtils; +import android.util.Base64; import android.util.Log; import android.view.Display; import android.view.WindowManager; @@ -66,14 +72,17 @@ import org.fdroid.fdroid.data.RepoProvider; import org.fdroid.fdroid.installer.ApkFileProvider; import org.fdroid.fdroid.installer.InstallHistoryService; import org.fdroid.fdroid.net.ConnectivityMonitorService; +import org.fdroid.fdroid.net.HttpDownloader; import org.fdroid.fdroid.net.ImageLoaderForUIL; import org.fdroid.fdroid.net.WifiStateChangeService; import org.fdroid.fdroid.views.hiding.HidingManager; import javax.microedition.khronos.opengles.GL10; import java.io.IOException; +import java.nio.ByteBuffer; import java.security.Security; import java.util.List; +import java.util.UUID; @ReportsCrashes(mailTo = "reports@f-droid.org", mode = ReportingInteractionMode.DIALOG, @@ -480,6 +489,30 @@ public class FDroidApp extends Application { UpdateService.forceUpdateRepo(this); } atStartTime.edit().putInt("build-version", Build.VERSION.SDK_INT).apply(); + + final String queryStringKey = "http-downloader-query-string"; + if (Preferences.get().sendVersionAndUUIDToServers()) { + HttpDownloader.queryString = atStartTime.getString(queryStringKey, null); + if (HttpDownloader.queryString == null) { + UUID uuid = UUID.randomUUID(); + ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE / Byte.SIZE * 2); + buffer.putLong(uuid.getMostSignificantBits()); + buffer.putLong(uuid.getLeastSignificantBits()); + String id = Base64.encodeToString(buffer.array(), + Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING); + StringBuilder builder = new StringBuilder("id=").append(id); + String versionName = Uri.encode(Utils.getVersionName(this)); + if (versionName != null) { + builder.append("&client_version=").append(versionName); + } + HttpDownloader.queryString = builder.toString(); + } + if (!atStartTime.contains(queryStringKey)) { + atStartTime.edit().putString(queryStringKey, HttpDownloader.queryString).apply(); + } + } else { + atStartTime.edit().remove(queryStringKey).apply(); + } } /** diff --git a/app/src/main/java/org/fdroid/fdroid/Preferences.java b/app/src/main/java/org/fdroid/fdroid/Preferences.java index 59c0f7565..3a6a27074 100644 --- a/app/src/main/java/org/fdroid/fdroid/Preferences.java +++ b/app/src/main/java/org/fdroid/fdroid/Preferences.java @@ -106,6 +106,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh public static final String PREF_PANIC_HIDE = "pref_panic_hide"; public static final String PREF_HIDE_ON_LONG_PRESS_SEARCH = "hideOnLongPressSearch"; public static final String PREF_HIDE_ALL_NOTIFICATIONS = "hideAllNotifications"; + public static final String PREF_SEND_VERSION_AND_UUID_TO_SERVERS = "sendVersionAndUUIDToServers"; public static final int OVER_NETWORK_NEVER = 0; public static final int OVER_NETWORK_ON_DEMAND = 1; @@ -498,6 +499,14 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh return preferences.getBoolean(PREF_HIDE_ALL_NOTIFICATIONS, IGNORED_B); } + /** + * Whether to include the version of this app and a randomly generated ID + * to the server when downloading from it. + */ + public boolean sendVersionAndUUIDToServers() { + return preferences.getBoolean(PREF_SEND_VERSION_AND_UUID_TO_SERVERS, IGNORED_B); + } + /** * This is cached as it is called several times inside app list adapters. * Providing it here means the shared preferences file only needs to be diff --git a/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java b/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java index 80e1ad988..08e25cd41 100644 --- a/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java +++ b/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java @@ -111,12 +111,7 @@ public class RepoUpdater { } protected String getIndexUrl(@NonNull Repo repo) { - String url = repo.address + "/index.jar"; - String versionName = Utils.getVersionName(context); - if (versionName != null) { - url += "?client_version=" + versionName; - } - return url; + return repo.address + "/index.jar"; } public boolean hasChanged() { diff --git a/app/src/main/java/org/fdroid/fdroid/net/HttpDownloader.java b/app/src/main/java/org/fdroid/fdroid/net/HttpDownloader.java index 218dd71a7..75f9416e5 100644 --- a/app/src/main/java/org/fdroid/fdroid/net/HttpDownloader.java +++ b/app/src/main/java/org/fdroid/fdroid/net/HttpDownloader.java @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2014-2017 Peter Serwylo + * Copyright (C) 2014-2018 Hans-Christoph Steiner + * Copyright (C) 2015-2016 Daniel Martí + * Copyright (c) 2018 Senecto Limited + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 3 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + package org.fdroid.fdroid.net; import android.annotation.TargetApi; @@ -40,6 +61,11 @@ public class HttpDownloader extends Downloader { private HttpURLConnection connection; private boolean newFileAvailableOnServer; + /** + * String to append to all HTTP downloads, created in {@link FDroidApp#onCreate()} + */ + public static String queryString; + HttpDownloader(Uri uri, File destFile) throws FileNotFoundException, MalformedURLException { this(uri, destFile, null, null); @@ -142,7 +168,11 @@ public class HttpDownloader extends Downloader { // swap never works with a proxy, its unrouted IP on the same subnet connection = (HttpURLConnection) sourceUrl.openConnection(); } else { - connection = NetCipher.getHttpURLConnection(sourceUrl); + if (queryString != null) { + connection = NetCipher.getHttpURLConnection(new URL(urlString + "?" + queryString)); + } else { + connection = NetCipher.getHttpURLConnection(sourceUrl); + } } connection.setRequestProperty("User-Agent", "F-Droid " + BuildConfig.VERSION_NAME); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b2a2912ef..5b71f95a7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -22,6 +22,9 @@ Keep install history Store a log of all installs and uninstalls in a private store + Send version and UUID to servers + Include this app\'s version and a random, unique ID when + downloading, takes affect next app restart. Force old index format In case there are bugs or compatibility issues, use the XML app index Other diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 3d9e4526f..3e9c38c74 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -171,6 +171,12 @@ android:summary="@string/hide_all_notifications_summary" android:defaultValue="false" android:dependency="expert"/> +