From b9307d4cb94c00f24bba1341d773c92ac2b850c7 Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Mon, 24 Feb 2020 10:57:51 +0700 Subject: [PATCH] Untie profile picture from auth token --- .../securesms/ApplicationContext.java | 32 +++++++++++++++++++ .../securesms/CreateProfileActivity.java | 9 ++++-- .../redesign/activities/SettingsActivity.kt | 5 ++- .../securesms/util/TextSecurePreferences.java | 8 +++++ 4 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index 041bdd5e86..f8eed2a13d 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -75,6 +75,7 @@ import org.thoughtcrime.securesms.loki.redesign.messaging.LokiUserDatabase; import org.thoughtcrime.securesms.loki.redesign.utilities.Broadcaster; import org.thoughtcrime.securesms.notifications.MessageNotifier; import org.thoughtcrime.securesms.notifications.NotificationChannels; +import org.thoughtcrime.securesms.profiles.AvatarHelper; import org.thoughtcrime.securesms.providers.BlobProvider; import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess; import org.thoughtcrime.securesms.recipients.Recipient; @@ -94,6 +95,7 @@ import org.webrtc.voiceengine.WebRtcAudioManager; import org.webrtc.voiceengine.WebRtcAudioUtils; import org.whispersystems.libsignal.logging.SignalProtocolLoggerProvider; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; +import org.whispersystems.signalservice.api.util.StreamDetails; import org.whispersystems.signalservice.internal.push.SignalServiceProtos; import org.whispersystems.signalservice.loki.api.LokiAPIDatabaseProtocol; import org.whispersystems.signalservice.loki.api.LokiFileServerAPI; @@ -104,8 +106,12 @@ import org.whispersystems.signalservice.loki.api.LokiPublicChat; import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI; import org.whispersystems.signalservice.loki.api.LokiRSSFeed; +import java.io.File; +import java.io.FileInputStream; +import java.security.SecureRandom; import java.security.Security; import java.util.ArrayList; +import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -191,6 +197,8 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc } } } + // Loki - Resubmit profile picture if needed + resubmitProfilePictureIfNeeded(); // Loki - Set up public chat manager lokiPublicChatManager = new LokiPublicChatManager(this); updatePublicChatProfilePictureIfNeeded(); @@ -589,6 +597,30 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc if (lokiMessengerUpdatesFeedPoller != null) lokiMessengerUpdatesFeedPoller.startIfNeeded(); } + private void resubmitProfilePictureIfNeeded() { + String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this); + if (userHexEncodedPublicKey == null) return; + long now = new Date().getTime(); + long lastProfilePictureUpload = TextSecurePreferences.getLastProfilePictureUpload(this); + if (now - lastProfilePictureUpload <= 14 * 24 * 60 * 60 * 1000) return; + AsyncTask.execute(() -> { + String encodedProfileKey = ProfileKeyUtil.generateEncodedProfileKey(this); + byte[] profileKey = ProfileKeyUtil.getProfileKeyFromEncodedString(encodedProfileKey); + try { + File profilePicture = AvatarHelper.getAvatarFile(this, Address.fromSerialized(userHexEncodedPublicKey)); + StreamDetails stream = new StreamDetails(new FileInputStream(profilePicture), "image/jpeg", profilePicture.length()); + LokiFileServerAPI.shared.uploadProfilePicture(LokiFileServerAPI.shared.getServer(), profileKey, stream, () -> { + TextSecurePreferences.setLastProfilePictureUpload(this, new Date().getTime()); + TextSecurePreferences.setProfileAvatarId(this, new SecureRandom().nextInt()); + ProfileKeyUtil.setEncodedProfileKey(this, encodedProfileKey); + return Unit.INSTANCE; + }); + } catch (Exception exception) { + // Do nothing + } + }); + } + public void updatePublicChatProfilePictureIfNeeded() { AsyncTask.execute(() -> { LokiPublicChatAPI publicChatAPI = null; diff --git a/src/org/thoughtcrime/securesms/CreateProfileActivity.java b/src/org/thoughtcrime/securesms/CreateProfileActivity.java index b42dafc29a..f819a8ffbd 100644 --- a/src/org/thoughtcrime/securesms/CreateProfileActivity.java +++ b/src/org/thoughtcrime/securesms/CreateProfileActivity.java @@ -58,14 +58,15 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.crypto.ProfileCipher; import org.whispersystems.signalservice.api.util.StreamDetails; import org.whispersystems.signalservice.loki.api.LokiDotNetAPI; -import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI; import org.whispersystems.signalservice.loki.api.LokiFileServerAPI; +import org.whispersystems.signalservice.loki.api.LokiPublicChatAPI; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.security.SecureRandom; import java.util.Arrays; +import java.util.Date; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.regex.Matcher; @@ -73,6 +74,7 @@ import java.util.regex.Pattern; import javax.inject.Inject; +import kotlin.Unit; import network.loki.messenger.R; @SuppressLint("StaticFieldLeak") @@ -408,7 +410,10 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje if (avatar != null) { Log.d("Loki", "Start uploading profile photo"); LokiFileServerAPI storageAPI = LokiFileServerAPI.shared; - LokiDotNetAPI.UploadResult result = storageAPI.uploadProfilePicture(storageAPI.getServer(), profileKey, avatar); + LokiDotNetAPI.UploadResult result = storageAPI.uploadProfilePicture(storageAPI.getServer(), profileKey, avatar, () -> { + TextSecurePreferences.setLastProfilePictureUpload(CreateProfileActivity.this, new Date().getTime()); + return Unit.INSTANCE; + }); Log.d("Loki", "Profile photo uploaded, the url is " + result.getUrl()); TextSecurePreferences.setProfileAvatarUrl(context, result.getUrl()); } else { diff --git a/src/org/thoughtcrime/securesms/loki/redesign/activities/SettingsActivity.kt b/src/org/thoughtcrime/securesms/loki/redesign/activities/SettingsActivity.kt index cc96abad99..c3298506e5 100644 --- a/src/org/thoughtcrime/securesms/loki/redesign/activities/SettingsActivity.kt +++ b/src/org/thoughtcrime/securesms/loki/redesign/activities/SettingsActivity.kt @@ -45,6 +45,7 @@ import org.whispersystems.signalservice.loki.api.LokiFileServerAPI import java.io.ByteArrayInputStream import java.io.File import java.security.SecureRandom +import java.util.* class SettingsActivity : PassphraseRequiredActionBarActivity() { private lateinit var glide: GlideRequests @@ -163,7 +164,9 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { val deferred = deferred() AsyncTask.execute { val stream = StreamDetails(ByteArrayInputStream(profilePicture), "image/jpeg", profilePicture.size.toLong()) - val (_, url) = storageAPI.uploadProfilePicture(storageAPI.server, profileKey, stream) + val (_, url) = storageAPI.uploadProfilePicture(storageAPI.server, profileKey, stream) { + TextSecurePreferences.setLastProfilePictureUpload(this@SettingsActivity, Date().time) + } TextSecurePreferences.setProfileAvatarUrl(this, url) deferred.resolve(Unit) } diff --git a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java index e9a2691279..7229a8ef0f 100644 --- a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java +++ b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java @@ -1258,6 +1258,14 @@ public class TextSecurePreferences { public static void setHasSeenOpenGroupSuggestionSheet(Context context) { setBooleanPreference(context, "has_seen_open_group_suggestion_sheet", true); } + + public static long getLastProfilePictureUpload(Context context) { + return getLongPreference(context, "last_profile_picture_upload", 0); + } + + public static void setLastProfilePictureUpload(Context context, long newValue) { + setLongPreference(context, "last_profile_picture_upload", newValue); + } // endregion public static void clearAll(Context context) {