That fuck shit the fascists are using
1package org.tm.archive;
2
3import android.Manifest;
4import android.annotation.SuppressLint;
5import android.content.Context;
6import android.content.Intent;
7import android.net.Uri;
8import android.os.AsyncTask;
9import android.os.Bundle;
10import android.os.Vibrator;
11import android.text.TextUtils;
12import android.transition.TransitionInflater;
13import android.view.Menu;
14import android.view.MenuItem;
15import android.view.View;
16import android.widget.Button;
17import android.widget.Toast;
18
19import androidx.annotation.NonNull;
20import androidx.appcompat.widget.Toolbar;
21
22import org.signal.core.util.ThreadUtil;
23import org.signal.core.util.logging.Log;
24import org.signal.libsignal.protocol.IdentityKeyPair;
25import org.signal.libsignal.protocol.InvalidKeyException;
26import org.signal.libsignal.protocol.ecc.Curve;
27import org.signal.libsignal.protocol.ecc.ECPublicKey;
28import org.signal.libsignal.zkgroup.profiles.ProfileKey;
29import org.signal.qr.kitkat.ScanListener;
30import org.tm.archive.crypto.ProfileKeyUtil;
31import org.tm.archive.dependencies.ApplicationDependencies;
32import org.tm.archive.jobs.LinkedDeviceInactiveCheckJob;
33import org.tm.archive.keyvalue.SignalStore;
34import org.tm.archive.permissions.Permissions;
35import org.signal.core.util.Base64;
36import org.tm.archive.util.DynamicLanguage;
37import org.tm.archive.util.DynamicNoActionBarTheme;
38import org.tm.archive.util.DynamicTheme;
39import org.tm.archive.util.TextSecurePreferences;
40import org.tm.archive.util.task.ProgressDialogAsyncTask;
41import org.whispersystems.signalservice.api.SignalServiceAccountManager;
42import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
43import org.whispersystems.signalservice.internal.push.DeviceLimitExceededException;
44
45import java.io.IOException;
46
47public class DeviceActivity extends PassphraseRequiredActivity
48 implements Button.OnClickListener, ScanListener, DeviceLinkFragment.LinkClickedListener
49{
50
51 private static final String TAG = Log.tag(DeviceActivity.class);
52
53 private static final String EXTRA_DIRECT_TO_SCANNER = "add";
54
55 private final DynamicTheme dynamicTheme = new DynamicNoActionBarTheme();
56 private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
57
58 private DeviceAddFragment deviceAddFragment;
59 private DeviceListFragment deviceListFragment;
60 private DeviceLinkFragment deviceLinkFragment;
61 private MenuItem cameraSwitchItem = null;
62
63
64 public static Intent getIntentForScanner(Context context) {
65 Intent intent = new Intent(context, DeviceActivity.class);
66 intent.putExtra(EXTRA_DIRECT_TO_SCANNER, true);
67 return intent;
68 }
69
70 @Override
71 public void onPreCreate() {
72 dynamicTheme.onCreate(this);
73 dynamicLanguage.onCreate(this);
74 }
75
76 @Override
77 public void onCreate(Bundle bundle, boolean ready) {
78 setContentView(R.layout.device_activity);
79
80 Toolbar toolbar = findViewById(R.id.toolbar);
81
82 setSupportActionBar(toolbar);
83 requireSupportActionBar().setDisplayHomeAsUpEnabled(true);
84 requireSupportActionBar().setTitle(R.string.AndroidManifest__linked_devices);
85
86 this.deviceAddFragment = new DeviceAddFragment();
87 this.deviceListFragment = new DeviceListFragment();
88 this.deviceLinkFragment = new DeviceLinkFragment();
89
90 this.deviceListFragment.setAddDeviceButtonListener(this);
91 this.deviceAddFragment.setScanListener(this);
92
93 if (getIntent().getBooleanExtra(EXTRA_DIRECT_TO_SCANNER, false)) {
94 initFragment(R.id.fragment_container, deviceAddFragment, dynamicLanguage.getCurrentLocale());
95 } else {
96 initFragment(R.id.fragment_container, deviceListFragment, dynamicLanguage.getCurrentLocale());
97 }
98 }
99
100 @Override
101 public void onResume() {
102 super.onResume();
103 dynamicTheme.onResume(this);
104 dynamicLanguage.onResume(this);
105 }
106
107 @Override
108 public boolean onOptionsItemSelected(MenuItem item) {
109 if (item.getItemId() == android.R.id.home) {
110 finish();
111 return true;
112 }
113
114 return false;
115 }
116
117 @Override
118 public boolean onCreateOptionsMenu(Menu menu) {
119 getMenuInflater().inflate(R.menu.device_add, menu);
120 cameraSwitchItem = menu.findItem(R.id.device_add_camera_switch);
121 cameraSwitchItem.setVisible(false);
122 return super.onCreateOptionsMenu(menu);
123 }
124
125 public MenuItem getCameraSwitchItem() {
126 return cameraSwitchItem;
127 }
128
129 @Override
130 public void onClick(View v) {
131 Permissions.with(this)
132 .request(Manifest.permission.CAMERA)
133 .ifNecessary()
134 .withPermanentDenialDialog(getString(R.string.DeviceActivity_signal_needs_the_camera_permission_in_order_to_scan_a_qr_code))
135 .onAllGranted(() -> {
136 getSupportFragmentManager().beginTransaction()
137 .replace(R.id.fragment_container, deviceAddFragment)
138 .addToBackStack(null)
139 .commitAllowingStateLoss();
140 })
141 .onAnyDenied(() -> Toast.makeText(this, R.string.DeviceActivity_unable_to_scan_a_qr_code_without_the_camera_permission, Toast.LENGTH_LONG).show())
142 .execute();
143 }
144
145 @Override
146 public void onQrDataFound(@NonNull final String data) {
147 ThreadUtil.runOnMain(() -> {
148 ((Vibrator)getSystemService(Context.VIBRATOR_SERVICE)).vibrate(50);
149 Uri uri = Uri.parse(data);
150 deviceLinkFragment.setLinkClickedListener(uri, DeviceActivity.this);
151
152 deviceAddFragment.setSharedElementReturnTransition(TransitionInflater.from(DeviceActivity.this).inflateTransition(R.transition.fragment_shared));
153 deviceAddFragment.setExitTransition(TransitionInflater.from(DeviceActivity.this).inflateTransition(android.R.transition.fade));
154
155 deviceLinkFragment.setSharedElementEnterTransition(TransitionInflater.from(DeviceActivity.this).inflateTransition(R.transition.fragment_shared));
156 deviceLinkFragment.setEnterTransition(TransitionInflater.from(DeviceActivity.this).inflateTransition(android.R.transition.fade));
157
158 getSupportFragmentManager().beginTransaction()
159 .addToBackStack(null)
160 .addSharedElement(deviceAddFragment.getDevicesImage(), "devices")
161 .replace(R.id.fragment_container, deviceLinkFragment)
162 .commit();
163
164 });
165 }
166
167 @SuppressLint("MissingSuperCall")
168 @Override
169 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
170 Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
171 }
172
173 @SuppressLint("StaticFieldLeak")
174 @Override
175 public void onLink(final Uri uri) {
176 new ProgressDialogAsyncTask<Void, Void, Integer>(this,
177 R.string.DeviceProvisioningActivity_content_progress_title,
178 R.string.DeviceProvisioningActivity_content_progress_content)
179 {
180 private static final int SUCCESS = 0;
181 private static final int NO_DEVICE = 1;
182 private static final int NETWORK_ERROR = 2;
183 private static final int KEY_ERROR = 3;
184 private static final int LIMIT_EXCEEDED = 4;
185 private static final int BAD_CODE = 5;
186
187 @Override
188 protected Integer doInBackground(Void... params) {
189 boolean isMultiDevice = TextSecurePreferences.isMultiDevice(DeviceActivity.this);
190
191 try {
192 Context context = DeviceActivity.this;
193 SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager();
194 String verificationCode = accountManager.getNewDeviceVerificationCode();
195 String ephemeralId = uri.getQueryParameter("uuid");
196 String publicKeyEncoded = uri.getQueryParameter("pub_key");
197
198 if (TextUtils.isEmpty(ephemeralId) || TextUtils.isEmpty(publicKeyEncoded)) {
199 Log.w(TAG, "UUID or Key is empty!");
200 return BAD_CODE;
201 }
202
203 ECPublicKey publicKey = Curve.decodePoint(Base64.decode(publicKeyEncoded), 0);
204 IdentityKeyPair aciIdentityKeyPair = SignalStore.account().getAciIdentityKey();
205 IdentityKeyPair pniIdentityKeyPair = SignalStore.account().getPniIdentityKey();
206 ProfileKey profileKey = ProfileKeyUtil.getSelfProfileKey();
207
208 TextSecurePreferences.setMultiDevice(DeviceActivity.this, true);
209 accountManager.addDevice(ephemeralId, publicKey, aciIdentityKeyPair, pniIdentityKeyPair, profileKey, SignalStore.svr().getOrCreateMasterKey(), verificationCode);
210
211 return SUCCESS;
212 } catch (NotFoundException e) {
213 Log.w(TAG, e);
214 TextSecurePreferences.setMultiDevice(DeviceActivity.this, isMultiDevice);
215 return NO_DEVICE;
216 } catch (DeviceLimitExceededException e) {
217 Log.w(TAG, e);
218 TextSecurePreferences.setMultiDevice(DeviceActivity.this, isMultiDevice);
219 return LIMIT_EXCEEDED;
220 } catch (IOException e) {
221 Log.w(TAG, e);
222 TextSecurePreferences.setMultiDevice(DeviceActivity.this, isMultiDevice);
223 return NETWORK_ERROR;
224 } catch (InvalidKeyException e) {
225 Log.w(TAG, e);
226 TextSecurePreferences.setMultiDevice(DeviceActivity.this, isMultiDevice);
227 return KEY_ERROR;
228 }
229 }
230
231 @Override
232 protected void onPostExecute(Integer result) {
233 super.onPostExecute(result);
234
235 LinkedDeviceInactiveCheckJob.enqueue();
236
237 Context context = DeviceActivity.this;
238
239 switch (result) {
240 case SUCCESS:
241 Toast.makeText(context, R.string.DeviceProvisioningActivity_content_progress_success, Toast.LENGTH_SHORT).show();
242 finish();
243 return;
244 case NO_DEVICE:
245 Toast.makeText(context, R.string.DeviceProvisioningActivity_content_progress_no_device, Toast.LENGTH_LONG).show();
246 break;
247 case NETWORK_ERROR:
248 Toast.makeText(context, R.string.DeviceProvisioningActivity_content_progress_network_error, Toast.LENGTH_LONG).show();
249 break;
250 case KEY_ERROR:
251 Toast.makeText(context, R.string.DeviceProvisioningActivity_content_progress_key_error, Toast.LENGTH_LONG).show();
252 break;
253 case LIMIT_EXCEEDED:
254 Toast.makeText(context, R.string.DeviceProvisioningActivity_sorry_you_have_too_many_devices_linked_already, Toast.LENGTH_LONG).show();
255 break;
256 case BAD_CODE:
257 Toast.makeText(context, R.string.DeviceActivity_sorry_this_is_not_a_valid_device_link_qr_code, Toast.LENGTH_LONG).show();
258 break;
259 }
260
261 getSupportFragmentManager().popBackStackImmediate();
262 }
263 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
264 }
265}