That fuck shit the fascists are using
1package org.archiver;
2
3import android.Manifest;
4import android.content.ContentResolver;
5import android.content.ContentUris;
6import android.content.Context;
7import android.content.pm.PackageManager;
8import android.database.Cursor;
9import android.net.Uri;
10import android.os.Build;
11import android.os.Environment;
12import android.provider.DocumentsContract;
13import android.provider.MediaStore;
14import android.webkit.MimeTypeMap;
15
16import com.tm.logger.Log;
17
18import org.jetbrains.annotations.Nullable;
19import org.tm.archive.attachments.Attachment;
20import org.tm.archive.attachments.AttachmentId;
21import org.tm.archive.attachments.DatabaseAttachment;
22import org.tm.archive.contactshare.Contact;
23import org.tm.archive.database.SignalDatabase;
24import org.tm.archive.dependencies.ApplicationDependencies;
25import org.tm.archive.providers.BlobProvider;
26
27import java.io.File;
28import java.io.FileNotFoundException;
29import java.io.FileOutputStream;
30import java.io.FileWriter;
31import java.io.IOException;
32import java.io.InputStream;
33import java.io.OutputStream;
34import java.util.Random;
35
36public class ArchiveFileUtil {
37
38
39 public static String getPath(Context context, Uri uri){
40 String[] projection = {MediaStore.MediaColumns.DATA};
41 String path = "";
42 ContentResolver cr = context.getApplicationContext().getContentResolver();
43 Cursor metaCursor = cr.query(uri, projection, null, null, null);
44 if (metaCursor != null) {
45 try {
46 if (metaCursor.moveToFirst()) {
47 path = metaCursor.getString(0);
48 }
49 } finally {
50 metaCursor.close();
51 }
52 }
53 return path;
54 }
55
56 /*
57This method can parse out the real local file path from a file URI.
58*/
59 public static String getUriRealPath(Context ctx, Uri uri)
60 {
61 String ret = "";
62
63 if( isAboveKitKat() )
64 {
65 // Android sdk version number bigger than 19.
66 ret = getUriRealPathAboveKitkat(ctx, uri);
67 }else
68 {
69 // Android sdk version number smaller than 19.
70 ret = getImageRealPath(ctx.getContentResolver(), uri, null);
71 }
72
73 return ret;
74 }
75
76 /*
77 This method will parse out the real local file path from the file content URI.
78 The method is only applied to android sdk version number that is bigger than 19.
79 */
80 public static String getUriRealPathAboveKitkat(Context ctx, Uri uri)
81 {
82 String ret = "";
83
84 if(ctx != null && uri != null) {
85
86 if(isContentUri(uri))
87 {
88 if(isGooglePhotoDoc(uri.getAuthority()))
89 {
90 ret = uri.getLastPathSegment();
91 }else {
92 ret = getImageRealPath(ctx.getContentResolver(), uri, null);
93 }
94 }else if(isFileUri(uri)) {
95 ret = uri.getPath();
96 }else if(isDocumentUri(ctx, uri)){
97
98 // Get uri related document id.
99 String documentId = DocumentsContract.getDocumentId(uri);
100
101 // Get uri authority.
102 String uriAuthority = uri.getAuthority();
103
104 if(isMediaDoc(uriAuthority))
105 {
106 String idArr[] = documentId.split(":");
107 if(idArr.length == 2)
108 {
109 // First item is document type.
110 String docType = idArr[0];
111
112 // Second item is document real id.
113 String realDocId = idArr[1];
114
115 // Get content uri by document type.
116 Uri mediaContentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
117 if("image".equals(docType))
118 {
119 mediaContentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
120 }else if("video".equals(docType))
121 {
122 mediaContentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
123 }else if("audio".equals(docType))
124 {
125 mediaContentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
126 }
127
128 // Get where clause with real document id.
129 String whereClause = MediaStore.Images.Media._ID + " = " + realDocId;
130
131 ret = getImageRealPath(ctx.getContentResolver(), mediaContentUri, whereClause);
132 }
133
134 }else if(isDownloadDoc(uriAuthority))
135 {
136 // Build download uri.
137 Uri downloadUri = Uri.parse("content://downloads/public_downloads");
138
139 // Append download document id at uri end.
140 Uri downloadUriAppendId = ContentUris.withAppendedId(downloadUri, Long.valueOf(documentId));
141
142 ret = getImageRealPath(ctx.getContentResolver(), downloadUriAppendId, null);
143
144 }else if(isExternalStoreDoc(uriAuthority))
145 {
146 String idArr[] = documentId.split(":");
147 if(idArr.length == 2)
148 {
149 String type = idArr[0];
150 String realDocId = idArr[1];
151
152 if("primary".equalsIgnoreCase(type))
153 {
154 ret = Environment.getExternalStorageDirectory() + "/" + realDocId;
155 }
156 }
157 }
158 }
159 }
160
161 return ret;
162 }
163
164 /* Check whether current android os version is bigger than kitkat or not. */
165 public static boolean isAboveKitKat()
166 {
167 boolean ret = false;
168 ret = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
169 return ret;
170 }
171
172 /* Check whether this uri represent a document or not. */
173 public static boolean isDocumentUri(Context ctx, Uri uri)
174 {
175 boolean ret = false;
176 if(ctx != null && uri != null) {
177 ret = DocumentsContract.isDocumentUri(ctx, uri);
178 }
179 return ret;
180 }
181
182 /* Check whether this uri is a content uri or not.
183 * content uri like content://media/external/images/media/1302716
184 * */
185 public static boolean isContentUri(Uri uri)
186 {
187 boolean ret = false;
188 if(uri != null) {
189 String uriSchema = uri.getScheme();
190 if("content".equalsIgnoreCase(uriSchema))
191 {
192 ret = true;
193 }
194 }
195 return ret;
196 }
197
198 /* Check whether this uri is a file uri or not.
199 * file uri like file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg
200 * */
201 public static boolean isFileUri(Uri uri)
202 {
203 boolean ret = false;
204 if(uri != null) {
205 String uriSchema = uri.getScheme();
206 if("file".equalsIgnoreCase(uriSchema))
207 {
208 ret = true;
209 }
210 }
211 return ret;
212 }
213
214
215 /* Check whether this document is provided by ExternalStorageProvider. Return true means the file is saved in external storage. */
216 public static boolean isExternalStoreDoc(String uriAuthority)
217 {
218 boolean ret = false;
219
220 if("com.android.externalstorage.documents".equals(uriAuthority))
221 {
222 ret = true;
223 }
224
225 return ret;
226 }
227
228 /* Check whether this document is provided by DownloadsProvider. return true means this file is a downloaed file. */
229 public static boolean isDownloadDoc(String uriAuthority)
230 {
231 boolean ret = false;
232
233 if("com.android.providers.downloads.documents".equals(uriAuthority))
234 {
235 ret = true;
236 }
237
238 return ret;
239 }
240
241 /*
242 Check if MediaProvider provide this document, if true means this image is created in android media app.
243 */
244 public static boolean isMediaDoc(String uriAuthority)
245 {
246 boolean ret = false;
247
248 if("com.android.providers.media.documents".equals(uriAuthority))
249 {
250 ret = true;
251 }
252
253 return ret;
254 }
255
256 /*
257 Check whether google photos provide this document, if true means this image is created in google photos app.
258 */
259 public static boolean isGooglePhotoDoc(String uriAuthority)
260 {
261 boolean ret = false;
262
263 if("com.google.android.apps.photos.content".equals(uriAuthority))
264 {
265 ret = true;
266 }
267
268 return ret;
269 }
270
271 /* Return uri represented document file real local path.*/
272 public static String getImageRealPath(ContentResolver contentResolver, Uri uri, String whereClause)
273 {
274 String ret = "";
275
276 // Query the uri with condition.
277 Cursor cursor = contentResolver.query(uri, null, whereClause, null, null);
278
279 if(cursor!=null)
280 {
281 boolean moveToFirst = cursor.moveToFirst();
282 if(moveToFirst)
283 {
284
285 // Get columns name by uri type.
286 String columnName = MediaStore.Images.Media.DATA;
287
288 if( uri==MediaStore.Images.Media.EXTERNAL_CONTENT_URI )
289 {
290 columnName = MediaStore.Images.Media.DATA;
291 }else if( uri==MediaStore.Audio.Media.EXTERNAL_CONTENT_URI )
292 {
293 columnName = MediaStore.Audio.Media.DATA;
294 }else if( uri==MediaStore.Video.Media.EXTERNAL_CONTENT_URI )
295 {
296 columnName = MediaStore.Video.Media.DATA;
297 }
298
299 // Get column index.
300 int imageColumnIndex = cursor.getColumnIndex(columnName);
301
302 // Get column value which is the uri related file local path.
303 ret = cursor.getString(imageColumnIndex);
304 }
305 }
306
307 return ret;
308 }
309
310 public static String getRealPath(final Context context, final Uri uri) {
311 final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
312
313 // DocumentProvider
314 if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
315 System.out.println("getPath() uri: " + uri.toString());
316 System.out.println("getPath() uri authority: " + uri.getAuthority());
317 System.out.println("getPath() uri path: " + uri.getPath());
318
319 // ExternalStorageProvider
320 if ("com.android.externalstorage.documents".equals(uri.getAuthority())) {
321 final String docId = DocumentsContract.getDocumentId(uri);
322 final String[] split = docId.split(":");
323 final String type = split[0];
324 System.out.println("getPath() docId: " + docId + ", split: " + split.length + ", type: " + type);
325
326 // This is for checking Main Memory
327 if ("primary".equalsIgnoreCase(type)) {
328 if (split.length > 1) {
329 return Environment.getExternalStorageDirectory() + "/" + split[1] + "/";
330 } else {
331 return Environment.getExternalStorageDirectory() + "/";
332 }
333 // This is for checking SD Card
334 } else {
335 return "storage" + "/" + docId.replace(":", "/");
336 }
337
338 }
339 }
340 return null;
341 }
342
343 public static void copyInputStreamToFile(InputStream in, File file) {
344 OutputStream out = null;
345
346 try {
347 out = new FileOutputStream(file);
348 byte[] buf = new byte[1024];
349 int len;
350 while((len=in.read(buf))>0){
351 out.write(buf,0,len);
352 }
353 }
354 catch (Exception e) {
355 e.printStackTrace();
356 }
357 finally {
358 // Ensure that the InputStreams are closed even if there's an exception.
359 try {
360 if ( out != null ) {
361 out.close();
362 }
363
364 // If you want to close the "in" InputStream yourself then remove this
365 // from here but ensure that you close it yourself eventually.
366 in.close();
367 }
368 catch ( IOException e ) {
369 e.printStackTrace();
370 }
371 }
372 }
373
374 public static void deleteFile(Context context,String dirName,String fileName){
375
376 File dir = new File(context.getCacheDir().toString());
377 if(dir.exists()){
378 for (File file : dir.listFiles()) {
379 if(file.getName().equalsIgnoreCase(fileName)){
380 file.delete();
381 break;
382 }
383 }
384 }
385 }
386
387 public static File createFileFromContentUri(Context context, String contentUri){
388 File resultFile = null;
389 if(contentUri.contains(ArchiveConstants.SIGNAL_PART_PATH) ) {
390 resultFile = getFileFromDataBaseUri(context, contentUri);
391 }else if(contentUri.contains(ArchiveConstants.SIGNAL_STICKER_PATH)){
392 resultFile = getStickerFileFromBlobProvider(context, contentUri);
393 }else if(contentUri.contains(ArchiveConstants.SIGNAL_BLOB_PATH)){
394 resultFile = getFileFromBlobProvider(context, contentUri);
395 }else {
396 resultFile = getFileFromDeviceUri(context, contentUri);
397 }
398 return resultFile;
399 }
400
401 public static File getFileFromDataBaseUri(Context context, String contentUri) {
402
403 String[] splitUri = contentUri.split("/");
404 int splitLength = splitUri.length;
405// DatabaseAttachment databaseAttachment = SignalDatabase.attachments().getAttachment(new AttachmentId(Long.parseLong(splitUri[splitLength - 1]),Long.parseLong(splitUri[splitLength - 2])));
406 DatabaseAttachment databaseAttachment = SignalDatabase.attachments().getAttachment(new AttachmentId(Long.parseLong(splitUri[splitLength - 1])));
407
408 InputStream attachmentInputStream = null;
409 try {
410 attachmentInputStream = SignalDatabase.attachments().getAttachmentStream(databaseAttachment.attachmentId,0);
411 } catch (IOException e) {
412 e.printStackTrace();
413 }
414
415 String fileName = getFileNameWithType(databaseAttachment.fileName, 0 ,databaseAttachment.attachmentId.id,databaseAttachment.contentType);
416 File resultFile = new File(context.getCacheDir(), fileName);
417 ArchiveFileUtil.copyInputStreamToFile(attachmentInputStream, resultFile);
418
419 return resultFile;
420 }
421
422 public static String getFileType(DatabaseAttachment databaseAttachment) {
423 String fileType;
424 try {
425 fileType = databaseAttachment.fileName.split("\\.")[1];
426 }catch (Exception e){
427 fileType = MimeTypeMap.getSingleton().getExtensionFromMimeType(databaseAttachment.contentType);
428 }
429 return fileType;
430 }
431
432 public static String getFileType(String fileName, String contentType) {
433 String fileType;
434 try {
435 if(fileName != null) {
436 fileType = fileName.split("\\.")[fileName.split("\\.").length - 1];
437 }else{
438 fileType = MimeTypeMap.getSingleton().getExtensionFromMimeType(contentType);
439 }
440 }catch (Exception e){
441 fileType = MimeTypeMap.getSingleton().getExtensionFromMimeType(contentType);
442 }
443 return fileType;
444 }
445
446 public static String getFileType(Attachment attachment) {
447 String fileType;
448 try {
449 fileType = attachment.fileName.split("\\.")[1];
450 }catch (Exception e){
451 fileType = MimeTypeMap.getSingleton().getExtensionFromMimeType(attachment.contentType);
452 }
453 return fileType;
454 }
455
456 private static File getFileFromBlobProvider(Context context, String contentUri) {
457 File resultFile = null;
458 String fileName = "";
459 String fileType = MimeTypeMap.getSingleton().getExtensionFromMimeType(context.getContentResolver().getType(Uri.parse(contentUri)));
460 InputStream stream = null;
461 try {
462 stream = BlobProvider.getInstance().getStream(ApplicationDependencies.getApplication(), Uri.parse(contentUri));
463 } catch (IOException e) {
464 e.printStackTrace();
465 Log.e("ArchiveFileUtil", "getFileFromBlobProvider -> error getStream!!!!--------------");
466 return null;
467 }
468 fileName = contentUri.split("/")[contentUri.split("/").length - 1].split("\\.")[0] + "." + fileType;
469
470 resultFile = new File(context.getCacheDir(), fileName);
471
472 ArchiveFileUtil.copyInputStreamToFile(stream, resultFile);
473
474 return resultFile;
475 }
476
477 private static File getStickerFileFromBlobProvider(Context context, String contentUri) {
478 File resultFile = null;
479 String fileName = "";
480 InputStream stream = null;
481 try {
482 stream = SignalDatabase.stickers().getStickerStream(ContentUris.parseId(Uri.parse(contentUri)));
483 } catch (IOException e) {
484 e.printStackTrace();
485 }
486
487 fileName = contentUri.split("/")[contentUri.split("/").length - 1].split("\\.")[0] + "." + "webp";
488
489 resultFile = new File(context.getCacheDir(), fileName);
490
491 ArchiveFileUtil.copyInputStreamToFile(stream, resultFile);
492
493 return resultFile;
494 }
495
496 public static boolean checkWriteExternalPermission(Context context)
497 {
498 String permission = Manifest.permission.READ_EXTERNAL_STORAGE;
499 int res = context.checkCallingOrSelfPermission(permission);
500 return (res == PackageManager.PERMISSION_GRANTED);
501 }
502
503 @Nullable
504 private static File getFileFromDeviceUri(Context context, String contentUri) {
505 if(checkWriteExternalPermission(context)) {
506 File resultFile = null;
507 String fileName = "";
508 String fileType = MimeTypeMap.getSingleton().getExtensionFromMimeType(context.getContentResolver().getType(Uri.parse(contentUri)));
509 InputStream inputStream = null;
510
511 fileName = contentUri.split("/")[contentUri.split("/").length - 1].split("\\.")[0] + "." + fileType;
512
513 resultFile = new File(context.getCacheDir(), fileName);
514 try {
515 inputStream = context.getContentResolver().openInputStream(Uri.parse(contentUri));
516 ArchiveFileUtil.copyInputStreamToFile(inputStream, resultFile);
517
518 } catch (Exception e) {
519 e.printStackTrace();
520 }
521
522 return resultFile;
523 }
524 return null;
525 }
526
527 public static File createVCFFileFromContact(Context context, Contact contact){
528
529 File vcfFile = new File(context.getCacheDir(), contact.getName().isEmpty()? "contact" : contact.getName().getDisplayName().replaceAll(" ","_") + ".vcf");
530 FileWriter fw = null;
531 try {
532 fw = new FileWriter(vcfFile);
533 fw.write("BEGIN:VCARD\r\n");
534 fw.write("VERSION:3.0\r\n");
535 fw.write("N:" + contact.getName().getFamilyName() + ";" + contact.getName().getGivenName() + "\r\n");
536 fw.write("FN:" + contact.getName().getGivenName() + " " + contact.getName().getFamilyName() + "\r\n");
537 if(contact.getOrganization() != null) {
538 fw.write("ORG:" + contact.getOrganization() + "\r\n");
539 }
540 for (int i = 0; i < contact.getPostalAddresses().size(); i++) {
541 fw.write("TEL;TYPE=WORK,VOICE:" + contact.getPostalAddresses().get(0).getLabel() + "\r\n");
542 }
543
544 for (int i = 0; i < contact.getPhoneNumbers().size(); i++) {
545 fw.write("TEL;TYPE=WORK,VOICE:" + contact.getPhoneNumbers().get(i).getNumber() + "\r\n");
546 }
547
548 fw.write("ADR;TYPE=WORK:;;" + contact.getPostalAddresses()+ "\r\n");
549 for (int i = 0; i < contact.getEmails().size(); i++) {
550 fw.write("EMAIL;TYPE=PREF,INTERNET:" + contact.getEmails().get(i).getEmail() + "\r\n");
551 }
552
553 fw.write("END:VCARD\r\n");
554 fw.close();
555 } catch (IOException e) {
556 e.printStackTrace();
557 }
558
559 return vcfFile;
560
561 }
562
563
564 public static String getFileNameWithType(String fileName, long messageId, long attachmentId, String contentType) {
565 return getFileNameWithType(fileName, messageId, attachmentId, contentType, false);
566 }
567
568 public static String getFileNameWithType(String fileName, long messageId, long attachmentId, String contentType, boolean isIncoming) {
569
570 if (isIncoming || fileName == null){
571 return ArchiveUtil.Companion.generateAttachmentName(messageId, attachmentId) + "." + ArchiveFileUtil.getFileType(fileName, contentType);
572 }else{
573 return fileName.replace(" ", "_");
574 }
575 }
576
577}