From 1704e44afce6996deccb751e76e234f4c3fb15b8 Mon Sep 17 00:00:00 2001 From: Philipp Crocoll Date: Mon, 16 Dec 2013 06:50:02 +0100 Subject: [PATCH] Implemented GetFilename method in JavaFileStorage providers and updated usage in C# components. This resolves a bug with loading the OTP aux file in SkyDrive and Google Drive. Fixed bug which prohibited creating databases on FTP/HTTP/WebDav (no credentials were queried) Fixed bug which prohibited to use the Android 4.4 KITKAT file picker Removed permission for internal file browser to allow using the internal picker in 4.4 as well (Security Exception) --- .../Io/CachingFileStorage.cs | 3 +- src/Kp2aBusinessLogic/Io/JavaFileStorage.cs | 2 +- src/java/JavaFileStorage/.classpath | 4 +- .../javafilestorage/DropboxFileStorage.java | 5 +++ .../GoogleDriveFileStorage.java | 32 ++++++++++++++ .../javafilestorage/JavaFileStorage.java | 3 ++ .../javafilestorage/SkyDriveFileStorage.java | 20 +++------ src/java/KP2ASoftKeyboard/.classpath | 2 +- src/java/android-filechooser/code/.classpath | 4 +- src/keepass2android/CreateDatabaseActivity.cs | 39 +++++++++++------ .../Properties/AndroidManifest_net.xml | 4 +- .../Resources/Resource.designer.cs | 2 +- src/keepass2android/Utils/Util.cs | 43 ++++++++++++++++--- .../fileselect/FileSelectActivity.cs | 38 ++++++---------- src/keepass2android/keepass2android.csproj | 2 +- 15 files changed, 135 insertions(+), 68 deletions(-) diff --git a/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs b/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs index 95dd50cf..13732716 100644 --- a/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs +++ b/src/Kp2aBusinessLogic/Io/CachingFileStorage.cs @@ -430,8 +430,7 @@ namespace keepass2android.Io public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc) { - return UrlUtil.StripExtension( - UrlUtil.GetFileName(ioc.Path)); + return _cachedStorage.GetFilenameWithoutPathAndExt(ioc); } public bool RequiresCredentials(IOConnectionInfo ioc) diff --git a/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs b/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs index 0cb5c666..b423a093 100644 --- a/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs +++ b/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs @@ -154,7 +154,7 @@ namespace keepass2android.Io public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc) { return UrlUtil.StripExtension( - UrlUtil.GetFileName(IocToPath(ioc))); + _jfs.GetFilename(IocToPath(ioc))); } public bool RequiresCredentials(IOConnectionInfo ioc) diff --git a/src/java/JavaFileStorage/.classpath b/src/java/JavaFileStorage/.classpath index 2cde4747..88ceb869 100644 --- a/src/java/JavaFileStorage/.classpath +++ b/src/java/JavaFileStorage/.classpath @@ -1,11 +1,11 @@ - - + + diff --git a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/DropboxFileStorage.java b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/DropboxFileStorage.java index 029d52e6..df6932f6 100644 --- a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/DropboxFileStorage.java +++ b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/DropboxFileStorage.java @@ -507,4 +507,9 @@ public class DropboxFileStorage extends JavaFileStorageBase { return path; } + @Override + public String getFilename(String path) throws Exception { + return path.substring(path.lastIndexOf("/")+1); + } + } diff --git a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/GoogleDriveFileStorage.java b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/GoogleDriveFileStorage.java index 3fb7d685..35b8c935 100644 --- a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/GoogleDriveFileStorage.java +++ b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/GoogleDriveFileStorage.java @@ -11,6 +11,8 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import keepass2android.javafilestorage.JavaFileStorageBase.InvalidPathException; + import com.google.api.client.extensions.android.http.AndroidHttp; import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential; import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException; @@ -238,6 +240,27 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase { return mAccount; } + public String getFilename() throws InvalidPathException { + + String[] parts = mAccountLocalPath.split("/"); + + String lastPart = parts[parts.length-1]; + int indexOfSeparator = lastPart.lastIndexOf(NAME_ID_SEP); + if (indexOfSeparator < 0) { + throw new InvalidPathException("cannot extract filename from " + mAccountLocalPath); + } + String name = lastPart.substring(0, indexOfSeparator); + try { + name = decode(name); + } catch (UnsupportedEncodingException e) { + // ignore + } + return name; + + + } + + }; @@ -805,6 +828,15 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase { } return gdrivePath.getDisplayName(); } + + @Override + public String getFilename(String path) throws Exception + { + GDrivePath gdrivePath = new GDrivePath(); + gdrivePath.setPathWithoutVerify(path); + + return gdrivePath.getFilename(); + } } diff --git a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorage.java b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorage.java index 6de3036b..a7963d3e 100644 --- a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorage.java +++ b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorage.java @@ -120,6 +120,9 @@ public class FileEntry { public String getDisplayName(String path); + //returns something like "myfile.txt" from the given path, i.e. it's displayable and only the last part of the path + public String getFilename(String path) throws Exception; + public boolean checkForFileChangeFast(String path, String previousFileVersion) throws Exception; public String getCurrentFileVersionFast(String path); diff --git a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/SkyDriveFileStorage.java b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/SkyDriveFileStorage.java index 7f472893..73618a37 100644 --- a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/SkyDriveFileStorage.java +++ b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/SkyDriveFileStorage.java @@ -404,19 +404,6 @@ public class SkyDriveFileStorage extends JavaFileStorageBase { throw new SkyDriveException(message, code); } } - - private SkyDriveObject tryAddFileToCache(SkyDrivePath skyDrivePath) { - try { - SkyDriveObject obj = getSkyDriveObject(skyDrivePath); - if (obj != null) { - mFolderCache.put(obj.getId(), obj); - } - return obj; - } catch (Exception e) { - return null; - } - - } private SkyDriveObject tryAddToCache(String skyDriveId) { try { @@ -799,4 +786,11 @@ public class SkyDriveFileStorage extends JavaFileStorageBase { } + @Override + public String getFilename(String path) throws Exception { + SkyDrivePath p = new SkyDrivePath(); + p.setPathWithoutVerify(path); + return p.getFilename(); + } + } diff --git a/src/java/KP2ASoftKeyboard/.classpath b/src/java/KP2ASoftKeyboard/.classpath index d57ec025..51769745 100644 --- a/src/java/KP2ASoftKeyboard/.classpath +++ b/src/java/KP2ASoftKeyboard/.classpath @@ -2,8 +2,8 @@ + - diff --git a/src/java/android-filechooser/code/.classpath b/src/java/android-filechooser/code/.classpath index 7bc01d9a..51769745 100644 --- a/src/java/android-filechooser/code/.classpath +++ b/src/java/android-filechooser/code/.classpath @@ -1,9 +1,9 @@ - - + + diff --git a/src/keepass2android/CreateDatabaseActivity.cs b/src/keepass2android/CreateDatabaseActivity.cs index 75c387fc..b3bf43c4 100644 --- a/src/keepass2android/CreateDatabaseActivity.cs +++ b/src/keepass2android/CreateDatabaseActivity.cs @@ -388,7 +388,7 @@ namespace keepass2android return filename; } - private void OnCreateButton(string filename) + private bool OnCreateButton(string filename) { // Make sure file name exists if (filename.Length == 0) @@ -396,20 +396,21 @@ namespace keepass2android Toast.MakeText(this, Resource.String.error_filename_required, ToastLength.Long).Show(); - return; + return false; } IOConnectionInfo ioc = new IOConnectionInfo { Path = filename }; + IFileStorage fileStorage; try { - App.Kp2a.GetFileStorage(ioc); + fileStorage = App.Kp2a.GetFileStorage(ioc); } catch (NoFileStorageFoundException) { Toast.MakeText(this, "Unexpected scheme in "+filename, ToastLength.Long).Show(); - return; + return false; } if (ioc.IsLocalFile()) @@ -425,7 +426,7 @@ namespace keepass2android Toast.MakeText(this, Resource.String.error_invalid_path, ToastLength.Long).Show(); - return; + return false; } if (!parent.Exists()) @@ -436,7 +437,7 @@ namespace keepass2android Toast.MakeText(this, Resource.String.error_could_not_create_parent, ToastLength.Long).Show(); - return; + return false; } } @@ -450,16 +451,30 @@ namespace keepass2android GetText(Resource.String.error_file_not_create) + " " + ex.LocalizedMessage, ToastLength.Long).Show(); - return; + return false; } - _ioc = ioc; - UpdateIocView(); - - } + if (fileStorage.RequiresCredentials(ioc)) + { + Util.QueryCredentials(ioc, AfterQueryCredentials, this); + } + else + { + _ioc = ioc; + UpdateIocView(); + } + + + return true; } - + + private void AfterQueryCredentials(IOConnectionInfo ioc) + { + _ioc = ioc; + UpdateIocView(); + } + private class LaunchGroupActivity : FileOnFinish { readonly CreateDatabaseActivity _activity; diff --git a/src/keepass2android/Properties/AndroidManifest_net.xml b/src/keepass2android/Properties/AndroidManifest_net.xml index 42221f32..8a2e441f 100644 --- a/src/keepass2android/Properties/AndroidManifest_net.xml +++ b/src/keepass2android/Properties/AndroidManifest_net.xml @@ -1,5 +1,5 @@  - + @@ -21,7 +21,7 @@ - + diff --git a/src/keepass2android/Resources/Resource.designer.cs b/src/keepass2android/Resources/Resource.designer.cs index aad91775..c1a968a9 100644 --- a/src/keepass2android/Resources/Resource.designer.cs +++ b/src/keepass2android/Resources/Resource.designer.cs @@ -5834,7 +5834,7 @@ namespace keepass2android 16843055, 16843056, 16843057, - 16843788}; + 16843754}; // aapt resource value: 4 public const int MenuView_android_headerBackground = 4; diff --git a/src/keepass2android/Utils/Util.cs b/src/keepass2android/Utils/Util.cs index 0751091b..686390d6 100644 --- a/src/keepass2android/Utils/Util.cs +++ b/src/keepass2android/Utils/Util.cs @@ -114,12 +114,14 @@ namespace keepass2android * @return True if an Intent with the specified action can be sent and * responded to, false otherwise. */ - static bool IsIntentAvailable(Context context, String action, String type) + static bool IsIntentAvailable(Context context, String action, String type, List categories ) { PackageManager packageManager = context.PackageManager; Intent intent = new Intent(action); if (type != null) intent.SetType(type); + if (categories != null) + categories.ForEach(c => intent.AddCategory(c)); IList list = packageManager.QueryIntentActivities(intent, PackageInfoFlags.MatchDefaultOnly); @@ -130,10 +132,11 @@ namespace keepass2android public static void ShowBrowseDialog(string filename, Activity act, int requestCodeBrowse, bool forSaving) { - if ((!forSaving) && (IsIntentAvailable(act, Intent.ActionGetContent, "file/*"))) + if ((!forSaving) && (IsIntentAvailable(act, Intent.ActionGetContent, "*/*", new List { Intent.CategoryOpenable}))) { Intent i = new Intent(Intent.ActionGetContent); - i.SetType("file/*"); + i.SetType("*/*"); + i.AddCategory(Intent.CategoryOpenable); act.StartActivityForResult(i, requestCodeBrowse); } @@ -207,7 +210,7 @@ namespace keepass2android return ((int)Android.OS.Build.VERSION.SdkInt >= 14) && (activity.ActionBar != null); } - public delegate void FileSelectedHandler(string filename); + public delegate bool FileSelectedHandler(string filename); public static void ShowFilenameDialog(Activity activity, FileSelectedHandler onOpen, FileSelectedHandler onCreate, bool showBrowseButton, string defaultFilename, string detailsText, int requestCodeBrowse) @@ -233,7 +236,8 @@ namespace keepass2android openButton.Click += (sender, args) => { String fileName = ((EditText) dialog.FindViewById(Resource.Id.file_filename)).Text; - onOpen(fileName); + if (onOpen(fileName)) + dialog.Dismiss(); }; // Create button @@ -241,7 +245,8 @@ namespace keepass2android createButton.Click += (sender, args) => { String fileName = ((EditText)dialog.FindViewById(Resource.Id.file_filename)).Text; - onCreate(fileName); + if (onCreate(fileName)) + dialog.Dismiss(); }; Button cancelButton = (Button) dialog.FindViewById(Resource.Id.fnv_cancel); @@ -261,6 +266,32 @@ namespace keepass2android }; } + + public static void QueryCredentials(IOConnectionInfo ioc, Action afterQueryCredentials, Activity activity) + { + //Build dialog to query credentials: + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.SetTitle(activity.GetString(Resource.String.credentials_dialog_title)); + builder.SetPositiveButton(activity.GetString(Android.Resource.String.Ok), (dlgSender, dlgEvt) => + { + Dialog dlg = (Dialog)dlgSender; + string username = ((EditText)dlg.FindViewById(Resource.Id.cred_username)).Text; + string password = ((EditText)dlg.FindViewById(Resource.Id.cred_password)).Text; + int credentialRememberMode = ((Spinner)dlg.FindViewById(Resource.Id.cred_remember_mode)).SelectedItemPosition; + ioc.UserName = username; + ioc.Password = password; + ioc.CredSaveMode = (IOCredSaveMode)credentialRememberMode; + afterQueryCredentials(ioc); + }); + builder.SetView(activity.LayoutInflater.Inflate(Resource.Layout.url_credentials, null)); + builder.SetNeutralButton(activity.GetString(Android.Resource.String.Cancel), + (dlgSender, dlgEvt) => { }); + Dialog dialog = builder.Create(); + dialog.Show(); + ((EditText)dialog.FindViewById(Resource.Id.cred_username)).Text = ioc.UserName; + ((EditText)dialog.FindViewById(Resource.Id.cred_password)).Text = ioc.Password; + ((Spinner)dialog.FindViewById(Resource.Id.cred_remember_mode)).SetSelection((int)ioc.CredSaveMode); + } } } diff --git a/src/keepass2android/fileselect/FileSelectActivity.cs b/src/keepass2android/fileselect/FileSelectActivity.cs index 65dce0e3..613bfac0 100644 --- a/src/keepass2android/fileselect/FileSelectActivity.cs +++ b/src/keepass2android/fileselect/FileSelectActivity.cs @@ -236,29 +236,7 @@ namespace keepass2android if (fileStorage.RequiresCredentials(ioc)) { - //Build dialog to query credentials: - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.SetTitle(GetString(Resource.String.credentials_dialog_title)); - builder.SetPositiveButton(GetString(Android.Resource.String.Ok), (dlgSender, dlgEvt) => - { - Dialog dlg = (Dialog)dlgSender; - string username = ((EditText)dlg.FindViewById(Resource.Id.cred_username)).Text; - string password = ((EditText)dlg.FindViewById(Resource.Id.cred_password)).Text; - int credentialRememberMode = ((Spinner)dlg.FindViewById(Resource.Id.cred_remember_mode)).SelectedItemPosition; - ioc.UserName = username; - ioc.Password = password; - ioc.CredSaveMode = (IOCredSaveMode)credentialRememberMode; - PasswordActivity.Launch(this, ioc, AppTask); - Finish(); - }); - builder.SetView(LayoutInflater.Inflate(Resource.Layout.url_credentials, null)); - builder.SetNeutralButton(GetString(Android.Resource.String.Cancel), - (dlgSender, dlgEvt) => {}); - Dialog dialog = builder.Create(); - dialog.Show(); - ((EditText)dialog.FindViewById(Resource.Id.cred_username)).Text = ioc.UserName; - ((EditText)dialog.FindViewById(Resource.Id.cred_password)).Text = ioc.Password; - ((Spinner)dialog.FindViewById(Resource.Id.cred_remember_mode)).SetSelection((int)ioc.CredSaveMode); + Util.QueryCredentials(ioc, AfterQueryCredentials, this); } else { @@ -272,7 +250,15 @@ namespace keepass2android } } } + + + private void AfterQueryCredentials(IOConnectionInfo ioc) + { + PasswordActivity.Launch(this, ioc, AppTask); + Finish(); + } + protected override void OnListItemClick(ListView l, View v, int position, long id) { base.OnListItemClick(l, v, position, id); @@ -284,7 +270,7 @@ namespace keepass2android App.Kp2a.GetFileStorage(ioc) .PrepareFileUsage(new FileStorageSetupInitiatorActivity(this, OnActivityResult, null), ioc, 0, false); } - private void OnOpenButton(String fileName) + private bool OnOpenButton(String fileName) { IOConnectionInfo ioc = new IOConnectionInfo @@ -293,7 +279,9 @@ namespace keepass2android }; LaunchPasswordActivityForIoc(ioc); - + + return true; + } protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) diff --git a/src/keepass2android/keepass2android.csproj b/src/keepass2android/keepass2android.csproj index 76203524..6f20ace0 100644 --- a/src/keepass2android/keepass2android.csproj +++ b/src/keepass2android/keepass2android.csproj @@ -29,7 +29,7 @@ full False bin\Debug - DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE + DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE prompt 4 False