From 6699154ad6720aa653575bee2b0db0db485fe055 Mon Sep 17 00:00:00 2001 From: Philipp Crocoll Date: Wed, 27 Nov 2013 22:21:29 +0100 Subject: [PATCH] Added DropboxAppFolderFileStorage don't disclose protected strings --- .../Io/DropboxFileStorage.cs | 24 +- src/Kp2aBusinessLogic/Io/IFileStorage.cs | 38 ++- .../FileStorageSelectionActivity.cs | 25 +- .../Properties/AndroidManifest_net.xml | 9 +- .../Resources/Resource.designer.cs | 261 +++++++++--------- .../drawable-hdpi/ic_storage_dropboxKP2A.png | Bin 0 -> 5543 bytes .../drawable/ic_storage_dropboxKP2A.png | Bin 0 -> 4711 bytes .../layout/filestorage_selection_listitem.xml | 21 +- .../Resources/values/strings.xml | 2 + src/keepass2android/app/App.cs | 1 + src/keepass2android/keepass2android.csproj | 10 +- src/keepass2android/search/SearchProvider.cs | 4 +- src/keepass2android/views/FileStorageView.cs | 15 +- src/keepass2android/views/TextWithHelp.cs | 11 +- 14 files changed, 248 insertions(+), 173 deletions(-) create mode 100644 src/keepass2android/Resources/drawable-hdpi/ic_storage_dropboxKP2A.png create mode 100644 src/keepass2android/Resources/drawable/ic_storage_dropboxKP2A.png diff --git a/src/Kp2aBusinessLogic/Io/DropboxFileStorage.cs b/src/Kp2aBusinessLogic/Io/DropboxFileStorage.cs index 1fb205fb..20dd1ecf 100644 --- a/src/Kp2aBusinessLogic/Io/DropboxFileStorage.cs +++ b/src/Kp2aBusinessLogic/Io/DropboxFileStorage.cs @@ -1,18 +1,5 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; - -using Android.App; using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; -using KeePassLib.Serialization; #if !EXCLUDE_JAVAFILESTORAGE -using Keepass2android.Javafilestorage; namespace keepass2android.Io { @@ -25,5 +12,16 @@ namespace keepass2android.Io } + + public partial class DropboxAppFolderFileStorage: JavaFileStorage + { + public DropboxAppFolderFileStorage(Context ctx, IKp2aApp app) : + base(new Keepass2android.Javafilestorage.DropboxAppFolderFileStorage(ctx, AppKey, AppSecret), app) + { + } + + + } + } #endif \ No newline at end of file diff --git a/src/Kp2aBusinessLogic/Io/IFileStorage.cs b/src/Kp2aBusinessLogic/Io/IFileStorage.cs index 84ee9a14..31a68ae3 100644 --- a/src/Kp2aBusinessLogic/Io/IFileStorage.cs +++ b/src/Kp2aBusinessLogic/Io/IFileStorage.cs @@ -28,24 +28,18 @@ namespace keepass2android.Io } - /// - /// Called as a callback from CheckForFileChangeAsync. - /// - /// - /// - public delegate void OnCheckForFileChangeCompleted(IOConnectionInfo ioc, bool fileChanged); - /// /// Interface to encapsulate all access to disk or cloud. /// - /// This interface might be implemented for different cloud storage providers in the future to extend the possibilities of the - /// "built-in" IOConnection class in the Keepass-Lib. - /// Note that it was decided to use the IOConnectionInfo also for cloud storage (unless it turns out that this isn't possible, but - /// with prefixes like dropbox:// it should be). The advantage is that the database for saving recent files etc. will then work without + /// Note that it was decided to use the IOConnectionInfo also for cloud storage. + /// The advantage is that the database for saving recent files etc. will then work without /// much work to do. Furthermore, the IOConnectionInfo seems generic info to capture all required data, even though it might be nicer to /// have an IIoStorageId interface in few cases.*/ public interface IFileStorage { + /// + /// returns the protocol ids supported by this FileStorage. Can return pseudo-protocols like "dropbox" or real protocols like "ftp" + /// IEnumerable SupportedProtocols { get; } /// @@ -162,4 +156,26 @@ namespace keepass2android.Io Stream OpenFile(); void CommitWrite(); } + + public class FileStorageSelectionInfo + { + public enum FileStorageSelectionMessageType + { + Info, //show only ok button + CancellableInfo, //show Ok/Cancel + Error //show cancel only + } + + public UiStringKey SelectionMessage { get; set; } + public FileStorageSelectionMessageType MessageType { get; set; } + } + + /// + /// Can be implemented by IFileStorage implementers to add additional information for the + /// process of selecting the file storage + /// + public interface IFileStorageSelectionInfoProvider + { + FileStorageSelectionInfo TryGetSelectionInfo(string protocolId); + } } \ No newline at end of file diff --git a/src/keepass2android/FileStorageSelectionActivity.cs b/src/keepass2android/FileStorageSelectionActivity.cs index c853a099..5a8792a6 100644 --- a/src/keepass2android/FileStorageSelectionActivity.cs +++ b/src/keepass2android/FileStorageSelectionActivity.cs @@ -66,7 +66,26 @@ namespace keepass2android private void OnItemSelected(string protocolId) { - ReturnProtocol(protocolId); + var field = typeof(Resource.String).GetField("filestoragehelp_" + protocolId); + if (field == null) + { + //no help available + ReturnProtocol(protocolId); + } + else + { + //set help: + string help = GetString((int)field.GetValue(null)); + + new AlertDialog.Builder(this) + .SetTitle(GetString(Resource.String.app_name)) + .SetMessage(help) + .SetPositiveButton(Android.Resource.String.Ok, (sender, args) => ReturnProtocol(protocolId)) + .Create() + .Show(); + } + + } private void ReturnProtocol(string protocolId) @@ -87,8 +106,10 @@ namespace keepass2android _fileStorageAdapter = new FileStorageAdapter(this); ListAdapter = _fileStorageAdapter; - FindViewById(Android.Resource.Id.List).ItemClick += + ListView listView = FindViewById(Android.Resource.Id.List); + listView.ItemClick += (sender, args) => OnItemSelected((string)_fileStorageAdapter.GetItem(args.Position)); + //listView.ItemsCanFocus = true; } diff --git a/src/keepass2android/Properties/AndroidManifest_net.xml b/src/keepass2android/Properties/AndroidManifest_net.xml index 398f42a0..7fa9426c 100644 --- a/src/keepass2android/Properties/AndroidManifest_net.xml +++ b/src/keepass2android/Properties/AndroidManifest_net.xml @@ -1,5 +1,5 @@  - + @@ -11,6 +11,13 @@ + + + + + + + diff --git a/src/keepass2android/Resources/Resource.designer.cs b/src/keepass2android/Resources/Resource.designer.cs index ae73570a..fc4dfee6 100644 --- a/src/keepass2android/Resources/Resource.designer.cs +++ b/src/keepass2android/Resources/Resource.designer.cs @@ -1863,88 +1863,91 @@ namespace keepass2android public const int ic_storage_dropbox = 2130837810; // aapt resource value: 0x7f020133 - public const int ic_storage_file = 2130837811; + public const int ic_storage_dropboxKP2A = 2130837811; // aapt resource value: 0x7f020134 - public const int ic_storage_ftp = 2130837812; + public const int ic_storage_file = 2130837812; // aapt resource value: 0x7f020135 - public const int ic_storage_gdrive = 2130837813; + public const int ic_storage_ftp = 2130837813; // aapt resource value: 0x7f020136 - public const int ic_storage_http = 2130837814; + public const int ic_storage_gdrive = 2130837814; // aapt resource value: 0x7f020137 - public const int ic_storage_https = 2130837815; + public const int ic_storage_http = 2130837815; // aapt resource value: 0x7f020138 - public const int ic_storage_skydrive = 2130837816; + public const int ic_storage_https = 2130837816; // aapt resource value: 0x7f020139 - public const int ic_unlocked_gray = 2130837817; + public const int ic_storage_skydrive = 2130837817; // aapt resource value: 0x7f02013a - public const int location_web_site = 2130837818; + public const int ic_unlocked_gray = 2130837818; // aapt resource value: 0x7f02013b - public const int navigation_accept = 2130837819; + public const int location_web_site = 2130837819; // aapt resource value: 0x7f02013c - public const int navigation_accept_dark = 2130837820; + public const int navigation_accept = 2130837820; // aapt resource value: 0x7f02013d - public const int navigation_cancel = 2130837821; + public const int navigation_accept_dark = 2130837821; // aapt resource value: 0x7f02013e - public const int navigation_previous_item = 2130837822; + public const int navigation_cancel = 2130837822; // aapt resource value: 0x7f02013f - public const int navigation_previous_item_dark = 2130837823; + public const int navigation_previous_item = 2130837823; // aapt resource value: 0x7f020140 - public const int notify = 2130837824; + public const int navigation_previous_item_dark = 2130837824; // aapt resource value: 0x7f020141 - public const int notify_keyboard = 2130837825; + public const int notify = 2130837825; // aapt resource value: 0x7f020142 - public const int oktoberfest = 2130837826; + public const int notify_keyboard = 2130837826; // aapt resource value: 0x7f020143 - public const int RedButton = 2130837827; + public const int oktoberfest = 2130837827; // aapt resource value: 0x7f020144 - public const int section_header = 2130837828; + public const int RedButton = 2130837828; // aapt resource value: 0x7f020145 - public const int sym_keyboard = 2130837829; + public const int section_header = 2130837829; // aapt resource value: 0x7f020146 - public const int sym_keyboard_delete = 2130837830; + public const int sym_keyboard = 2130837830; // aapt resource value: 0x7f020147 - public const int sym_keyboard_done = 2130837831; + public const int sym_keyboard_delete = 2130837831; // aapt resource value: 0x7f020148 - public const int sym_keyboard_kp2a = 2130837832; + public const int sym_keyboard_done = 2130837832; // aapt resource value: 0x7f020149 - public const int sym_keyboard_return = 2130837833; + public const int sym_keyboard_kp2a = 2130837833; // aapt resource value: 0x7f02014a - public const int sym_keyboard_search = 2130837834; + public const int sym_keyboard_return = 2130837834; // aapt resource value: 0x7f02014b - public const int sym_keyboard_shift = 2130837835; + public const int sym_keyboard_search = 2130837835; // aapt resource value: 0x7f02014c - public const int sym_keyboard_space = 2130837836; + public const int sym_keyboard_shift = 2130837836; // aapt resource value: 0x7f02014d - public const int transparent = 2130837837; + public const int sym_keyboard_space = 2130837837; // aapt resource value: 0x7f02014e - public const int YellowButton = 2130837838; + public const int transparent = 2130837838; + + // aapt resource value: 0x7f02014f + public const int YellowButton = 2130837839; static Drawable() { @@ -3335,47 +3338,47 @@ namespace keepass2android // aapt resource value: 0x7f0801cb public const int CannotMoveGroupHere = 2131231179; - // aapt resource value: 0x7f080202 - public const int ChangeLog = 2131231234; + // aapt resource value: 0x7f080204 + public const int ChangeLog = 2131231236; + + // aapt resource value: 0x7f080203 + public const int ChangeLog_0_7 = 2131231235; // aapt resource value: 0x7f080201 - public const int ChangeLog_0_7 = 2131231233; - - // aapt resource value: 0x7f0801ff - public const int ChangeLog_0_8 = 2131231231; - - // aapt resource value: 0x7f0801fe - public const int ChangeLog_0_8_1 = 2131231230; - - // aapt resource value: 0x7f0801fd - public const int ChangeLog_0_8_2 = 2131231229; - - // aapt resource value: 0x7f0801fc - public const int ChangeLog_0_8_3 = 2131231228; - - // aapt resource value: 0x7f0801fb - public const int ChangeLog_0_8_4 = 2131231227; - - // aapt resource value: 0x7f0801fa - public const int ChangeLog_0_8_5 = 2131231226; - - // aapt resource value: 0x7f0801f9 - public const int ChangeLog_0_8_6 = 2131231225; - - // aapt resource value: 0x7f0801f8 - public const int ChangeLog_0_9 = 2131231224; - - // aapt resource value: 0x7f0801f7 - public const int ChangeLog_0_9_1 = 2131231223; - - // aapt resource value: 0x7f0801f6 - public const int ChangeLog_0_9_2 = 2131231222; + public const int ChangeLog_0_8 = 2131231233; // aapt resource value: 0x7f080200 - public const int ChangeLog_keptDonate = 2131231232; + public const int ChangeLog_0_8_1 = 2131231232; - // aapt resource value: 0x7f0801f5 - public const int ChangeLog_title = 2131231221; + // aapt resource value: 0x7f0801ff + public const int ChangeLog_0_8_2 = 2131231231; + + // aapt resource value: 0x7f0801fe + public const int ChangeLog_0_8_3 = 2131231230; + + // aapt resource value: 0x7f0801fd + public const int ChangeLog_0_8_4 = 2131231229; + + // aapt resource value: 0x7f0801fc + public const int ChangeLog_0_8_5 = 2131231228; + + // aapt resource value: 0x7f0801fb + public const int ChangeLog_0_8_6 = 2131231227; + + // aapt resource value: 0x7f0801fa + public const int ChangeLog_0_9 = 2131231226; + + // aapt resource value: 0x7f0801f9 + public const int ChangeLog_0_9_1 = 2131231225; + + // aapt resource value: 0x7f0801f8 + public const int ChangeLog_0_9_2 = 2131231224; + + // aapt resource value: 0x7f080202 + public const int ChangeLog_keptDonate = 2131231234; + + // aapt resource value: 0x7f0801f7 + public const int ChangeLog_title = 2131231223; // aapt resource value: 0x7f080093 public const int CheckForFileChangesOnSave_key = 2131230867; @@ -3410,11 +3413,11 @@ namespace keepass2android // aapt resource value: 0x7f0801bd public const int CouldNotSaveToRemote = 2131231165; - // aapt resource value: 0x7f0801ea - public const int CouldntLoadOtpAuxFile = 2131231210; + // aapt resource value: 0x7f0801ec + public const int CouldntLoadOtpAuxFile = 2131231212; - // aapt resource value: 0x7f0801f0 - public const int CouldntParseOtpSecret = 2131231216; + // aapt resource value: 0x7f0801f2 + public const int CouldntParseOtpSecret = 2131231218; // aapt resource value: 0x7f0800a1 public const int CreditsText = 2131230881; @@ -3434,8 +3437,8 @@ namespace keepass2android // aapt resource value: 0x7f0801c9 public const int ErrorOcurred = 2131231177; - // aapt resource value: 0x7f0801f2 - public const int ErrorUpdatingOtpAuxFile = 2131231218; + // aapt resource value: 0x7f0801f4 + public const int ErrorUpdatingOtpAuxFile = 2131231220; // aapt resource value: 0x7f0800b9 public const int FileHandling_prefs = 2131230905; @@ -3491,8 +3494,8 @@ namespace keepass2android // aapt resource value: 0x7f080191 public const int OpenKp2aKeyboardAutomatically_title = 2131231121; - // aapt resource value: 0x7f0801f1 - public const int OtpKeyError = 2131231217; + // aapt resource value: 0x7f0801f3 + public const int OtpKeyError = 2131231219; // aapt resource value: 0x7f0801af public const int ParsingDatabase = 2131231151; @@ -3596,8 +3599,8 @@ namespace keepass2android // aapt resource value: 0x7f080176 public const int SaveAttachment_doneMessage = 2131231094; - // aapt resource value: 0x7f0801f3 - public const int SavingOtpAuxFile = 2131231219; + // aapt resource value: 0x7f0801f5 + public const int SavingOtpAuxFile = 2131231221; // aapt resource value: 0x7f0801ab public const int SettingPassword = 2131231147; @@ -4010,8 +4013,8 @@ namespace keepass2android // aapt resource value: 0x7f0800ba public const int brackets = 2131230906; - // aapt resource value: 0x7f0801de - public const int button_change_location = 2131231198; + // aapt resource value: 0x7f0801e0 + public const int button_change_location = 2131231200; // aapt resource value: 0x7f0800bb public const int cancel = 2131230907; @@ -4121,8 +4124,8 @@ namespace keepass2android // aapt resource value: 0x7f080181 public const int database_loaded_unlocked = 2131231105; - // aapt resource value: 0x7f0801db - public const int database_location = 2131231195; + // aapt resource value: 0x7f0801dd + public const int database_location = 2131231197; // aapt resource value: 0x7f080137 public const int database_name = 2131231031; @@ -4232,8 +4235,8 @@ namespace keepass2android // aapt resource value: 0x7f0800da public const int entry_user_name = 2131230938; - // aapt resource value: 0x7f0801e6 - public const int error_adding_keyfile = 2131231206; + // aapt resource value: 0x7f0801e8 + public const int error_adding_keyfile = 2131231208; // aapt resource value: 0x7f0800dd public const int error_can_not_handle_uri = 2131230941; @@ -4304,8 +4307,11 @@ namespace keepass2android // aapt resource value: 0x7f0800ef public const int file_browser = 2131230959; - // aapt resource value: 0x7f0801da - public const int filestorage_setup_title = 2131231194; + // aapt resource value: 0x7f0801dc + public const int filestorage_setup_title = 2131231196; + + // aapt resource value: 0x7f0801d8 + public const int filestoragehelp_dropboxKP2A = 2131231192; // aapt resource value: 0x7f0801d1 public const int filestoragename_androidget = 2131231185; @@ -4316,14 +4322,17 @@ namespace keepass2android // aapt resource value: 0x7f0801d6 public const int filestoragename_dropbox = 2131231190; + // aapt resource value: 0x7f0801d7 + public const int filestoragename_dropboxKP2A = 2131231191; + // aapt resource value: 0x7f0801d0 public const int filestoragename_file = 2131231184; // aapt resource value: 0x7f0801d3 public const int filestoragename_ftp = 2131231187; - // aapt resource value: 0x7f0801d7 - public const int filestoragename_gdrive = 2131231191; + // aapt resource value: 0x7f0801d9 + public const int filestoragename_gdrive = 2131231193; // aapt resource value: 0x7f0801d4 public const int filestoragename_http = 2131231188; @@ -4331,11 +4340,11 @@ namespace keepass2android // aapt resource value: 0x7f0801d5 public const int filestoragename_https = 2131231189; - // aapt resource value: 0x7f0801d9 - public const int filestoragename_sftp = 2131231193; + // aapt resource value: 0x7f0801db + public const int filestoragename_sftp = 2131231195; - // aapt resource value: 0x7f0801d8 - public const int filestoragename_skydrive = 2131231192; + // aapt resource value: 0x7f0801da + public const int filestoragename_skydrive = 2131231194; // aapt resource value: 0x7f08006d public const int further_author_names = 2131230829; @@ -4349,14 +4358,14 @@ namespace keepass2android // aapt resource value: 0x7f0800f1 public const int group = 2131230961; - // aapt resource value: 0x7f0801dc - public const int help_database_location = 2131231196; + // aapt resource value: 0x7f0801de + public const int help_database_location = 2131231198; - // aapt resource value: 0x7f0801e3 - public const int help_key_file = 2131231203; + // aapt resource value: 0x7f0801e5 + public const int help_key_file = 2131231205; - // aapt resource value: 0x7f0801e0 - public const int help_master_password = 2131231200; + // aapt resource value: 0x7f0801e2 + public const int help_master_password = 2131231202; // aapt resource value: 0x7f0800f2 public const int hint_comment = 2131230962; @@ -4364,8 +4373,8 @@ namespace keepass2android // aapt resource value: 0x7f0800f3 public const int hint_conf_pass = 2131230963; - // aapt resource value: 0x7f0801dd - public const int hint_database_location = 2131231197; + // aapt resource value: 0x7f0801df + public const int hint_database_location = 2131231199; // aapt resource value: 0x7f0800f4 public const int hint_generated_password = 2131230964; @@ -4373,8 +4382,8 @@ namespace keepass2android // aapt resource value: 0x7f0800f5 public const int hint_group_name = 2131230965; - // aapt resource value: 0x7f0801e4 - public const int hint_key_file = 2131231204; + // aapt resource value: 0x7f0801e6 + public const int hint_key_file = 2131231206; // aapt resource value: 0x7f0800f6 public const int hint_keyfile = 2131230966; @@ -4385,8 +4394,8 @@ namespace keepass2android // aapt resource value: 0x7f0800f9 public const int hint_login_pass = 2131230969; - // aapt resource value: 0x7f0801e1 - public const int hint_master_password = 2131231201; + // aapt resource value: 0x7f0801e3 + public const int hint_master_password = 2131231203; // aapt resource value: 0x7f0800fc public const int hint_override_url = 2131230972; @@ -4418,8 +4427,8 @@ namespace keepass2android // aapt resource value: 0x7f080015 public const int ime_name = 2131230741; - // aapt resource value: 0x7f0801e7 - public const int init_otp = 2131231207; + // aapt resource value: 0x7f0801e9 + public const int init_otp = 2131231209; // aapt resource value: 0x7f080145 public const int insert_element_here = 2131231045; @@ -4433,8 +4442,8 @@ namespace keepass2android // aapt resource value: 0x7f08006e public const int issues = 2131230830; - // aapt resource value: 0x7f0801e2 - public const int key_file = 2131231202; + // aapt resource value: 0x7f0801e4 + public const int key_file = 2131231204; // aapt resource value: 0x7f080102 public const int keyfile_does_not_exist = 2131230978; @@ -4481,8 +4490,8 @@ namespace keepass2android // aapt resource value: 0x7f080105 public const int list_size_title = 2131230981; - // aapt resource value: 0x7f0801f4 - public const int loading = 2131231220; + // aapt resource value: 0x7f0801f6 + public const int loading = 2131231222; // aapt resource value: 0x7f080107 public const int loading_database = 2131230983; @@ -4502,8 +4511,8 @@ namespace keepass2android // aapt resource value: 0x7f08012b public const int master_key_type = 2131231019; - // aapt resource value: 0x7f0801df - public const int master_password = 2131231199; + // aapt resource value: 0x7f0801e1 + public const int master_password = 2131231201; // aapt resource value: 0x7f08010c public const int menu_about = 2131230988; @@ -4616,26 +4625,26 @@ namespace keepass2android // aapt resource value: 0x7f0801c8 public const int otp_aux_file = 2131231176; + // aapt resource value: 0x7f0801ef + public const int otp_discarded_because_db_open = 2131231215; + // aapt resource value: 0x7f0801ed - public const int otp_discarded_because_db_open = 2131231213; - - // aapt resource value: 0x7f0801eb - public const int otp_discarded_because_no_db = 2131231211; - - // aapt resource value: 0x7f0801ec - public const int otp_discarded_no_space = 2131231212; - - // aapt resource value: 0x7f0801e8 - public const int otp_explanation = 2131231208; - - // aapt resource value: 0x7f0801e9 - public const int otp_hint = 2131231209; + public const int otp_discarded_because_no_db = 2131231213; // aapt resource value: 0x7f0801ee - public const int otps_pending = 2131231214; + public const int otp_discarded_no_space = 2131231214; - // aapt resource value: 0x7f0801ef - public const int otpsecret_hint = 2131231215; + // aapt resource value: 0x7f0801ea + public const int otp_explanation = 2131231210; + + // aapt resource value: 0x7f0801eb + public const int otp_hint = 2131231211; + + // aapt resource value: 0x7f0801f0 + public const int otps_pending = 2131231216; + + // aapt resource value: 0x7f0801f1 + public const int otpsecret_hint = 2131231217; // aapt resource value: 0x7f080129 public const int pass_filename = 2131231017; @@ -4799,8 +4808,8 @@ namespace keepass2android // aapt resource value: 0x7f080149 public const int uppercase = 2131231049; - // aapt resource value: 0x7f0801e5 - public const int use_key_file = 2131231205; + // aapt resource value: 0x7f0801e7 + public const int use_key_file = 2131231207; // aapt resource value: 0x7f08014d public const int version_history = 2131231053; diff --git a/src/keepass2android/Resources/drawable-hdpi/ic_storage_dropboxKP2A.png b/src/keepass2android/Resources/drawable-hdpi/ic_storage_dropboxKP2A.png new file mode 100644 index 0000000000000000000000000000000000000000..3170535d41b7e989308e181223632bae82a02a7b GIT binary patch literal 5543 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 literal 0 HcmV?d00001 diff --git a/src/keepass2android/Resources/drawable/ic_storage_dropboxKP2A.png b/src/keepass2android/Resources/drawable/ic_storage_dropboxKP2A.png new file mode 100644 index 0000000000000000000000000000000000000000..27b8fc406518a3c363f5cc6724831e555d806fc7 GIT binary patch literal 4711 zcmV-t5}56YP)4Tx07wm;mUmPX*B8g%%xo{TU6vwc>AklFq%OTkl_mFQv@x1^BM1TV}0C2duqR=S6Xn?LjUp6xrb&~O43j*Nv zEr418u3H3zGns$s|L;SQD-ufpfWpxLJ03rmi*g~#S@{x?OrJ!Vo{}kJ7$ajbnjp%m zGEV!%=70KpVow?KvV}a4moSaFCQKV= zXBIPnpP$8-NG!rR+)R#`$7JVZi#Wn10DSspSrkx`)s~4C+0n+?(b2-z5-tDd^^cpM zz5W?wz5V3zGUCskL5!X++LzcbT23thtSPiMTfS&1I{|204}j|3FPi>70OSh+Xzlyz zdl<5LNtZ}OE>>3g`T3RtKG#xK(9i3CI(+v0d-&=+OWAp!Ysd8Ar*foO5~i%E+?=c& zshF87;&Ay)i~kOm zCIB-Z!^JGdti+UJsxgN!t(Y#%b<8kk67vyD#cE*9urAm@Y#cTXn~yERR$}Y1E!Yd# zo7hq8Ya9;8z!~A3Z~?e@Tn26#t`xT$*Ni)h>&K1Yrto;Y8r}@=h7ZGY@Dh9xekcA2 z{tSKqKZ<`tAQQ9+wgf*y0zpVvOQ<9qCY&Y=5XJ~ILHOG0j2XwBQ%7jM`P2tv~{#P+6CGu9Y;5!2hua>CG_v;z4S?CC1rc%807-x z8s$^ULkxsr$OvR)G0GUn7`GVjR5Vq*RQM{JRGL%DRgX~5SKp(4L49HleU9rK?wsN|$L8GCfHh1tA~lw29MI^|n9|hJ z^w$(=?$kW5IibbS^3=-Es?a*EHLgw5cGnhYS7@Kne#%s4dNH$@Rm?8tq>hG8fR0pW zzfP~tjINRHeBHIW&AJctNO~;2RJ{tlPQ6KeZT(RF<@$~KcMXUJEQ54|9R}S7(}qTd zv4$HA+YFx=sTu_uEj4O1x^GN1_Ap*-Tx)#81ZToB$u!w*a?KPrbudjgtugI0gUuYx z1ZKO<`pvQC&gMe%TJu2*iiMX&o<*a@uqDGX#B!}=o8@yWeX9hktybMuAFUm%v#jf^ z@7XBX1lg>$>9G0T*3_13TVs2}j%w#;x5}>F?uEUXJ>Pzh{cQ)DL#V?BhfaqNj!uqZ z$0o;dCw-@6r(I5iEIKQkRm!^LjCJ;QUgdn!`K^nii^S!a%Wtk0u9>cfU7yS~n#-SC zH+RHM*Nx-0-)+d9>7MMq&wa>4$AjZh>+#4_&y(j_?>XjW;+5fb#Ot}YwYS*2#e16V z!d}5X>x20C`xN{1`YQR(_pSDQ=%?$K=GW*q>F?mb%>QfvHXt})YrtTjW*|4PA#gIt zDQHDdS1=_wD!4lMQHW`XIHV&K4h;(37J7f4!93x-wlEMD7`83!LAX));_x3Ma1r4V zH4%>^Z6cRPc1O{olA;bry^i*dE{nc5-*~=serJq)Okzw!%yg_zYWi`#ol25V;v^kU#wN!mA5MPH z3FFjqrcwe^cBM>m+1wr6XFN|{1#g`1#xLiOrMjh-r#?w@OWT$Wgg6&&5F%x&L(6hXP*!%2{VOVIa)adIsGCtQITk9vCHD^izmgw;`&@D zcVTY3gpU49^+=7S>!rha?s+wNZ}MaEj~6Hw2n%|am@e70WNfM5(r=exmT{MLF4tMU zX8G_6uNC`OLMu~NcCOM}Rk&(&wg2ivYe;J{*Zj2BdTsgISLt?eJQu}$~QLORDCnMIdyYynPb_W zEx0YhEw{FMY&}%2SiZD;WLxOA)(U1tamB0cN!u@1+E?z~LE0hRF;o>&)xJ}I=a!xC ztJAA*)_B)6@6y<{Y1i~_-tK`to_m`1YVIxB`);3L-|hYW`&(-bYby`n4&)tpTo+T< z{VnU;hI;k-lKKw^g$IWYMIP#EaB65ctZ}%k5pI+=jvq-pa_u{x@7kLzn)Wv{noEv? zqtc^Kzfb=D*0JDYoyS?nn|?6(VOI;SrMMMpUD7()mfkkh9^c-7BIrbChiga6kCs0k zJgIZC=9KcOveTr~g{NoFEIl)IR&;jaT-v#j&ZN$J=i|=b=!)p-y%2oi(nY_E=exbS z&s=i5bn>#xz3Ke>~2=f&N;yEFGz-^boBexUH6@}b7V+Mi8+ZXR+R zIyLMw-18{v(Y+Dw$g^K^e|bMz_?Y^*a!h-y;fd{&ljDBl*PbqTI{HlXY-Xb9SH)j< zJvV;-!*8Cy^-RW1j=m7TnEk!{$Ld^Z-avE-FA%e+%Q z{Z4pX6IaIo!vqNDCrTPw_6i{A2TF4+Gj_T6k;6|m?$*g_Zp2^pqv(hxu8ab40`f_N zv3JU#BICelOcQx|RnHQC9|H;uS^3k4$ulwX%*`a;c#O&*N5xmrkXwI8F*yx6282Ey zznM_nwkF875rdS9tNnY!7CX z0*4>*Vt$odCf}#wg~dAdt@7cvAT4riGNYdaWD@!;MW+z8J?z7G=6U6QAxygECZTz^2psu}AM+~7qgiZ8a7HqRlsnU7YZx(n^EVyny)=~7%!%^@Xx_XJ zo8CT$cmLXtIZwCa<^5+6F81Xc9(0Uvkase3C?A1cK6Tf5MoQwvd2 zn^0j(s@58d0GGP))q6r%F{c(AUOSGyz;tMNC2m2-i1Tr*<e6+U zTib-XY70|Kd+q<;hMKVz0oGH6$Pz zLr%0wXljuMuRj>XtV;EnbY#7SSB{V3`6DA3H8KG$Z^*$zEF$%f}OYBiPwP zuV@yM+mc^Gb`Ck?=*%JNH`nNR@3E337}lo?4I4k3kH37q49gpQ$(*Pu)bQr2Aa*<) zOoCzgT(5@LRs`|Fy#?ffM7}uf*jEAT<^?LL=*E?URHakOKR(-wvV67E)Qsv?6?({c z3HF?g;^6r){CH_l8c&zA#}74nv8!9)#6>#a4$|1Lsm_mh9T z<)1J(lHJ`SV+PtfPb1ua8QuTtcbIW^TRYC7>3h3z{9Ip#9ckZEr!0BwrI&2iC0h%k zY8H0%>QY(Ti4R;>E({Fg@n64(?=G8;ZI3qMk6jnh+R^Khxj1+o55BkuUu)?>q`Zla zeLzJdX@d_Ghf(FQ8&DQ6vDdUf1^SC;Va=~jV(m-q7#NDuPA_B2uJ`ft^@~woo(m7< z)s|JW5Vd@GZs&2BbON^>I*re4dJFAWN+2p`&?Q6Wve~e~(N+{7LZ{s3e!1-%R32BM zL)>x~*4{rC8-Leu zAv5e_&kW@Zb1OpczRy}QgaMi5;qbFH}uDbnMD=fN8D#~6hzfe@QIZm(wESs0KtqA z0G$=s00g;)y~Ds1kNc$5E~JY4Ox&OQ5Nt}d?XNRJ!Dyd^-FcqV@cp#HyTt_^Vc)d}7kw4~<$akvFWL zF^pWkAOVdTJ^NqJZ(8$I++wq2fB`WG8;spbFbWjQ$RhX3tJq74a3#SgU~vXWF>|%d zBRMwcp~^UQ;0@|ZK*N{Xx4u;opC}C6{lFS;pk#`mH-|km87P(HN*RN)iEPNw$u?oo z1tI~8BcVKIAvQ92<$Cwt-Qo6^eouOaSsj^1(ChV1GflHj_zOyXMdbyOE!6f|AVoBC zGg4E|9%r#kWyO?3#p2*e=EQLLx)~h`3nBh#7{&+0yhfqq6C;1)=MjT07SLS}{vvbi pokstAB4CtG6ecRe+!B`fzX2Ke%+}q=Nl*X)002ovPDHLkV1k;i78n2k literal 0 HcmV?d00001 diff --git a/src/keepass2android/Resources/layout/filestorage_selection_listitem.xml b/src/keepass2android/Resources/layout/filestorage_selection_listitem.xml index ae77705b..7452dfb5 100644 --- a/src/keepass2android/Resources/layout/filestorage_selection_listitem.xml +++ b/src/keepass2android/Resources/layout/filestorage_selection_listitem.xml @@ -19,13 +19,20 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical"> - - + + + + + + + diff --git a/src/keepass2android/Resources/values/strings.xml b/src/keepass2android/Resources/values/strings.xml index 2fcee608..bc7509b2 100644 --- a/src/keepass2android/Resources/values/strings.xml +++ b/src/keepass2android/Resources/values/strings.xml @@ -332,6 +332,8 @@ HTTP (WebDav) HTTPS (WebDav) Dropbox + Dropbox (KP2A folder) + If you do not want to give KP2A access to your full Dropbox, you may select this option. It will request only access to the folder Apps/Keepass2Android. This is especially suited when creating a new database. If you already have a database, click this option to create the folder, then place your file inside the folder (from your PC) and then select this option again for opening the file. Google Drive SkyDrive SFTP (SSH File Transfer Protocol) diff --git a/src/keepass2android/app/App.cs b/src/keepass2android/app/App.cs index 57d300e1..4d9d80fe 100644 --- a/src/keepass2android/app/App.cs +++ b/src/keepass2android/app/App.cs @@ -395,6 +395,7 @@ namespace keepass2android { #if !EXCLUDE_JAVAFILESTORAGE new DropboxFileStorage(Application.Context, this), + new DropboxAppFolderFileStorage(Application.Context, this), new GoogleDriveFileStorage(Application.Context, this), new SkyDriveFileStorage(Application.Context, this), #endif diff --git a/src/keepass2android/keepass2android.csproj b/src/keepass2android/keepass2android.csproj index b5a53e81..1544cb70 100644 --- a/src/keepass2android/keepass2android.csproj +++ b/src/keepass2android/keepass2android.csproj @@ -390,7 +390,9 @@ - + + Designer + @@ -887,4 +889,10 @@ + + + + + + \ No newline at end of file diff --git a/src/keepass2android/search/SearchProvider.cs b/src/keepass2android/search/SearchProvider.cs index 6b6f5e71..91eabc67 100644 --- a/src/keepass2android/search/SearchProvider.cs +++ b/src/keepass2android/search/SearchProvider.cs @@ -277,7 +277,9 @@ namespace keepass2android.search intlResourceId = Resource.String.entry_tags; break; default: - // Other fields aren't part of the default SearchParameters, so we won't ever get them as context anyway + //don't disclose protected strings: + if (CurrentEntry.Strings.Get(rawName).IsProtected) + return null; break; } diff --git a/src/keepass2android/views/FileStorageView.cs b/src/keepass2android/views/FileStorageView.cs index b5f5a4ea..9a4f9c91 100644 --- a/src/keepass2android/views/FileStorageView.cs +++ b/src/keepass2android/views/FileStorageView.cs @@ -27,14 +27,13 @@ using Android.Text; using Android.Text.Style; using Android.Preferences; using keepass2android.Io; +using keepass2android.views; namespace keepass2android.view { public sealed class FileStorageView : ClickView { private readonly TextView _textView; - private readonly TextView _textviewDetails; - public FileStorageView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) @@ -45,13 +44,10 @@ namespace keepass2android.view public FileStorageView(Activity activity, string protocolId, int pos) : base(activity) { - View ev = Inflate(activity, Resource.Layout.entry_list_entry, null); - _textView = (TextView)ev.FindViewById(Resource.Id.entry_text); + View ev = Inflate(activity, Resource.Layout.filestorage_selection_listitem, null); + _textView = (TextView)ev.FindViewById(Resource.Id.filestorage_label); _textView.TextSize = PrefsUtil.GetListTextSize(activity); - _textviewDetails = (TextView)ev.FindViewById(Resource.Id.entry_text_detail); - _textviewDetails.TextSize = PrefsUtil.GetListDetailTextSize(activity); - PopulateView(ev, protocolId, pos); LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent); @@ -62,7 +58,7 @@ namespace keepass2android.view private void PopulateView(View ev, string protocolId, int pos) { - ImageView iv = (ImageView)ev.FindViewById(Resource.Id.entry_icon); + ImageView iv = (ImageView)ev.FindViewById(Resource.Id.filestorage_logo); Drawable drawable = App.Kp2a.GetResourceDrawable("ic_storage_" + protocolId); iv.SetImageDrawable(drawable); @@ -71,8 +67,7 @@ namespace keepass2android.view var str = new SpannableString(title); _textView.TextFormatted = str; - _textviewDetails.Visibility = ViewStates.Gone; - + } diff --git a/src/keepass2android/views/TextWithHelp.cs b/src/keepass2android/views/TextWithHelp.cs index 96865a6a..641a537f 100644 --- a/src/keepass2android/views/TextWithHelp.cs +++ b/src/keepass2android/views/TextWithHelp.cs @@ -16,6 +16,8 @@ namespace keepass2android.views { public class TextWithHelp : RelativeLayout { + private Kp2aShortHelpView _kp2AShortHelpView; + public TextWithHelp(Context context, IAttributeSet attrs) : base(context, attrs) { @@ -36,11 +38,18 @@ namespace keepass2android.views TypedArray a = Context.ObtainStyledAttributes( attrs, Resource.Styleable.TextWithHelp); - ((Kp2aShortHelpView)FindViewById(Resource.Id.help)).HelpText = a.GetString(Resource.Styleable.TextWithHelp_help_text); + _kp2AShortHelpView = ((Kp2aShortHelpView)FindViewById(Resource.Id.help)); + _kp2AShortHelpView.HelpText = a.GetString(Resource.Styleable.TextWithHelp_help_text); const string xmlns = "http://schemas.android.com/apk/res/android"; ((TextView)FindViewById(Resource.Id.text)).Text = Context.GetString(attrs.GetAttributeResourceValue(xmlns, "text",Resource.String.ellipsis)); } + + public string HelpText + { + get { return _kp2AShortHelpView.HelpText; } + set { _kp2AShortHelpView.HelpText = value; } + } } } \ No newline at end of file