From 297c0a792f79ee7f10a99a6712a8d6d63d4ed008 Mon Sep 17 00:00:00 2001 From: Ignacio Quezada Date: Tue, 8 Nov 2016 11:45:20 +0100 Subject: Private files using a boolean flag from Config.java. --- src/main/java/eu/siacs/conversations/Config.java | 2 + .../conversations/persistance/FileBackend.java | 38 ++++++++--- .../conversations/services/ExportLogsService.java | 2 +- .../conversations/ui/ConversationActivity.java | 9 ++- .../siacs/conversations/ui/SettingsActivity.java | 74 ++++++++++++++++++++++ .../siacs/conversations/ui/SettingsFragment.java | 12 ++++ .../conversations/ui/adapter/MessageAdapter.java | 10 ++- src/main/res/values/strings.xml | 4 ++ src/main/res/xml/file_paths.xml | 3 + src/main/res/xml/preferences.xml | 11 +++- 10 files changed, 147 insertions(+), 18 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 821de698..28496b37 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -97,6 +97,8 @@ public final class Config { public static final boolean X509_VERIFICATION = false; //use x509 certificates to verify OMEMO keys + public static final boolean ONLY_INTERNAL_STORAGE = false; //use internal storage instead of sdcard to save attachments + public static final boolean IGNORE_ID_REWRITE_IN_MUC = true; public static final boolean PARSE_REAL_JID_FROM_MUC_MAM = false; //dangerous if server doesn’t filter diff --git a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java index bc919788..921ac12a 100644 --- a/src/main/java/eu/siacs/conversations/persistance/FileBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/FileBackend.java @@ -151,14 +151,26 @@ public class FileBackend { return true; } - public static String getConversationsFileDirectory() { - return Environment.getExternalStorageDirectory().getAbsolutePath()+"/Conversations/"; + public String getConversationsFileDirectory() { + if (Config.ONLY_INTERNAL_STORAGE) { + return mXmppConnectionService.getFilesDir().getAbsolutePath() + "/Files/"; + } else { + return Environment.getExternalStorageDirectory().getAbsolutePath() + "/Conversations/"; + } } - public static String getConversationsImageDirectory() { - return Environment.getExternalStoragePublicDirectory( - Environment.DIRECTORY_PICTURES).getAbsolutePath() - + "/Conversations/"; + public String getConversationsImageDirectory() { + if (Config.ONLY_INTERNAL_STORAGE) { + return mXmppConnectionService.getFilesDir().getAbsolutePath()+"/Pictures/"; + } else { + return Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_PICTURES).getAbsolutePath() + + "/Conversations/"; + } + } + + public static String getConversationsLogsDirectory() { + return Environment.getExternalStorageDirectory().getAbsolutePath()+"/Conversations/"; } public Bitmap resize(Bitmap originalBitmap, int size) { @@ -438,9 +450,14 @@ public class FileBackend { } public Uri getTakePhotoUri() { - File file = new File(getTakePhotoPath()+"IMG_" + this.IMAGE_DATE_FORMAT.format(new Date()) + ".jpg"); + File file; + if (Config.ONLY_INTERNAL_STORAGE) { + file = new File(mXmppConnectionService.getCacheDir().getAbsolutePath(), "Camera/IMG_" + this.IMAGE_DATE_FORMAT.format(new Date()) + ".jpg"); + } else { + file = new File(getTakePhotoPath() + "IMG_" + this.IMAGE_DATE_FORMAT.format(new Date()) + ".jpg"); + } file.getParentFile().mkdirs(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N || Config.ONLY_INTERNAL_STORAGE) { return FileProvider.getUriForFile(mXmppConnectionService, CONVERSATIONS_FILE_PROVIDER, file); } else { return Uri.fromFile(file); @@ -448,7 +465,7 @@ public class FileBackend { } public static Uri getIndexableTakePhotoUri(Uri original) { - if ("file".equals(original.getScheme())) { + if (Config.ONLY_INTERNAL_STORAGE || "file".equals(original.getScheme())) { return original; } else { List segments = original.getPathSegments(); @@ -695,7 +712,8 @@ public class FileBackend { public Uri getJingleFileUri(Message message) { File file = getFile(message); - return Uri.parse("file://" + file.getAbsolutePath()); + return FileProvider.getUriForFile(mXmppConnectionService, + CONVERSATIONS_FILE_PROVIDER, file); } public void updateFileParams(Message message) { diff --git a/src/main/java/eu/siacs/conversations/services/ExportLogsService.java b/src/main/java/eu/siacs/conversations/services/ExportLogsService.java index 87e65931..51eced05 100644 --- a/src/main/java/eu/siacs/conversations/services/ExportLogsService.java +++ b/src/main/java/eu/siacs/conversations/services/ExportLogsService.java @@ -26,7 +26,7 @@ import eu.siacs.conversations.xmpp.jid.Jid; public class ExportLogsService extends Service { private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - private static final String DIRECTORY_STRING_FORMAT = FileBackend.getConversationsFileDirectory() + "/logs/%s"; + private static final String DIRECTORY_STRING_FORMAT = FileBackend.getConversationsLogsDirectory() + "/logs/%s"; private static final String MESSAGE_STRING_FORMAT = "(%s) %s: %s\n"; private static final int NOTIFICATION_ID = 1; private static AtomicBoolean running = new AtomicBoolean(false); diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java index 82b59dfc..b2c4efda 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java @@ -494,6 +494,7 @@ public class ConversationActivity extends XmppActivity case ATTACHMENT_CHOICE_TAKE_PHOTO: Uri uri = xmppConnectionService.getFileBackend().getTakePhotoUri(); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); mPendingImageUris.clear(); @@ -1412,9 +1413,11 @@ public class ConversationActivity extends XmppActivity attachImageToConversation(getSelectedConversation(), uri); mPendingImageUris.clear(); } - Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); - intent.setData(uri); - sendBroadcast(intent); + if (!Config.ONLY_INTERNAL_STORAGE) { + Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + intent.setData(uri); + sendBroadcast(intent); + } } else { mPendingImageUris.clear(); } diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java index c2bf20ac..5dc38a9d 100644 --- a/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/SettingsActivity.java @@ -7,6 +7,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.preference.ListPreference; @@ -14,8 +15,10 @@ import android.preference.Preference; import android.preference.PreferenceCategory; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; +import android.util.Log; import android.widget.Toast; +import java.io.File; import java.security.KeyStoreException; import java.util.ArrayList; import java.util.Arrays; @@ -156,6 +159,26 @@ public class SettingsActivity extends XmppActivity implements } }); + if (Config.ONLY_INTERNAL_STORAGE) { + final Preference cleanCachePreference = mSettingsFragment.findPreference("clean_cache"); + cleanCachePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + cleanCache(); + return true; + } + }); + + final Preference cleanPrivateStoragePreference = mSettingsFragment.findPreference("clean_private_storage"); + cleanPrivateStoragePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + cleanPrivateStorage(); + return true; + } + }); + } + final Preference deleteOmemoPreference = mSettingsFragment.findPreference("delete_omemo_identities"); deleteOmemoPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override @@ -166,6 +189,57 @@ public class SettingsActivity extends XmppActivity implements }); } + private void cleanCache() { + Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + intent.setData(Uri.parse("package:" + getPackageName())); + startActivity(intent); + } + + private void cleanPrivateStorage() { + cleanPrivatePictures(); + cleanPrivateFiles(); + } + + private void cleanPrivatePictures() { + try { + File dir = new File(getFilesDir().getAbsolutePath(), "/Pictures/"); + File[] array = dir.listFiles(); + if (array != null) { + for (int b = 0; b < array.length; b++) { + String name = array[b].getName().toLowerCase(); + if (name.equals(".nomedia")) { + continue; + } + if (array[b].isFile()) { + array[b].delete(); + } + } + } + } catch (Throwable e) { + Log.e("CleanCache", e.toString()); + } + } + + private void cleanPrivateFiles() { + try { + File dir = new File(getFilesDir().getAbsolutePath(), "/Files/"); + File[] array = dir.listFiles(); + if (array != null) { + for (int b = 0; b < array.length; b++) { + String name = array[b].getName().toLowerCase(); + if (name.equals(".nomedia")) { + continue; + } + if (array[b].isFile()) { + array[b].delete(); + } + } + } + } catch (Throwable e) { + Log.e("CleanCache", e.toString()); + } + } + private void deleteOmemoIdentities() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.pref_delete_omemo_identities); diff --git a/src/main/java/eu/siacs/conversations/ui/SettingsFragment.java b/src/main/java/eu/siacs/conversations/ui/SettingsFragment.java index e4185abc..b5529bad 100644 --- a/src/main/java/eu/siacs/conversations/ui/SettingsFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/SettingsFragment.java @@ -3,6 +3,7 @@ package eu.siacs.conversations.ui; import android.app.Dialog; import android.os.Bundle; import android.preference.Preference; +import android.preference.PreferenceCategory; import android.preference.PreferenceFragment; import android.preference.PreferenceScreen; import android.view.View; @@ -11,6 +12,7 @@ import android.view.ViewParent; import android.widget.FrameLayout; import android.widget.LinearLayout; +import eu.siacs.conversations.Config; import eu.siacs.conversations.R; public class SettingsFragment extends PreferenceFragment { @@ -52,6 +54,16 @@ public class SettingsFragment extends PreferenceFragment { // Load the preferences from an XML resource addPreferencesFromResource(R.xml.preferences); + + // Remove from standard preferences if the flag ONLY_INTERNAL_STORAGE is not true + if (!Config.ONLY_INTERNAL_STORAGE) { + PreferenceCategory mCategory = (PreferenceCategory) findPreference("security_options"); + Preference mPref1 = findPreference("clean_cache"); + Preference mPref2 = findPreference("clean_private_storage"); + mCategory.removePreference(mPref1); + mCategory.removePreference(mPref2); + } + } @Override diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index 496d8ab5..6a785594 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -697,12 +697,16 @@ public class MessageAdapter extends ArrayAdapter { mime = "*/*"; } Uri uri; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N || Config.ONLY_INTERNAL_STORAGE) { try { uri = FileProvider.getUriForFile(activity, FileBackend.CONVERSATIONS_FILE_PROVIDER, file); } catch (IllegalArgumentException e) { - Toast.makeText(activity,activity.getString(R.string.no_permission_to_access_x,file.getAbsolutePath()), Toast.LENGTH_SHORT).show(); - return; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Toast.makeText(activity, activity.getString(R.string.no_permission_to_access_x, file.getAbsolutePath()), Toast.LENGTH_SHORT).show(); + return; + } else { + uri = Uri.fromFile(file); + } } openIntent.setDataAndType(uri, mime); openIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 170cbfff..580b56c4 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -693,4 +693,8 @@ Regenerate your OMEMO keys. All your contacts will have to verify you again. Use this only as a last resort. Delete selected keys You need to be connected to publish your avatar. + Clean cache folder (used by Camera Application) + Clean cache + Clean private storage + Clean private storage where files are kept (They can be re-downloaded from the server) diff --git a/src/main/res/xml/file_paths.xml b/src/main/res/xml/file_paths.xml index 2a8bc766..6a5e2609 100644 --- a/src/main/res/xml/file_paths.xml +++ b/src/main/res/xml/file_paths.xml @@ -1,4 +1,7 @@ + + + \ No newline at end of file diff --git a/src/main/res/xml/preferences.xml b/src/main/res/xml/preferences.xml index cee43491..569876f4 100644 --- a/src/main/res/xml/preferences.xml +++ b/src/main/res/xml/preferences.xml @@ -163,7 +163,8 @@ android:key="expert" android:summary="@string/pref_expert_options_summary" android:title="@string/pref_expert_options"> - + + +