From 57e92532700a040e008d3a26d01f60cee80059e5 Mon Sep 17 00:00:00 2001 From: Philipp Crocoll Date: Thu, 3 Oct 2019 16:42:50 +0200 Subject: [PATCH] improvements to OneDrive2 implementation: it's now possible select between different access scopes, also fixed several issues --- .../Io/OneDrive2FileStorage.cs | 220 ++++++++++++------ .../Io/OneDrive2PrefixContainer.cs | 26 +++ .../Kp2aBusinessLogic.csproj | 1 + src/keepass2android/CreateDatabaseActivity.cs | 4 +- src/keepass2android/EntryEditActivity.cs | 4 +- .../FileStorageSelectionActivity.cs | 25 +- src/keepass2android/PasswordActivity.cs | 4 +- .../Resources/values/strings.xml | 3 + .../SelectCurrentDbActivity.cs | 2 +- src/keepass2android/app/App.cs | 37 ++- 10 files changed, 246 insertions(+), 80 deletions(-) create mode 100644 src/Kp2aBusinessLogic/Io/OneDrive2PrefixContainer.cs diff --git a/src/Kp2aBusinessLogic/Io/OneDrive2FileStorage.cs b/src/Kp2aBusinessLogic/Io/OneDrive2FileStorage.cs index 4defbea9..94e01dbb 100644 --- a/src/Kp2aBusinessLogic/Io/OneDrive2FileStorage.cs +++ b/src/Kp2aBusinessLogic/Io/OneDrive2FileStorage.cs @@ -11,6 +11,7 @@ using Android.Content; using Android.OS; using Android.Util; using Java.Net; +using keepass2android.Io.ItemLocation; using KeePassLib.Serialization; using KeePassLib.Utility; using Microsoft.Graph; @@ -18,15 +19,13 @@ using Microsoft.Graph.Auth; using Microsoft.Identity.Client; using Newtonsoft.Json; using Exception = System.Exception; +using File = Microsoft.Graph.File; using String = System.String; namespace keepass2android.Io { - public class OneDrive2FileStorage : IFileStorage + namespace ItemLocation { - - public static IPublicClientApplication _publicClientApp = null; - private string ClientID = "8374f801-0f55-407d-80cc-9a04fe86d9b2"; public class User { public string Name { get; set; } @@ -45,21 +44,22 @@ namespace keepass2android.Io public string Id { get; set; } } - public class OneDrive2ItemLocation + + public class OneDrive2ItemLocation where OneDrive2PrefixContainerType: OneDrive2PrefixContainer, new() { - private const string Onedrive2Prefix = "onedrive2://"; + public User User { get; set; } = new User(); public Share Share { get; set; } = new Share(); public string DriveId { get; set; } public List LocalPath { get; set; } = new List(); - public string LocalPathString { get { return string.Join("/", LocalPath.Select(i => i.Name)); }} + public string LocalPathString { get { return string.Join("/", LocalPath.Select(i => i.Name)); } } - public OneDrive2ItemLocation Parent + public OneDrive2ItemLocation Parent { get { - OneDrive2ItemLocation copy = OneDrive2ItemLocation.FromString(this.ToString()); + OneDrive2ItemLocation< OneDrive2PrefixContainerType> copy = OneDrive2ItemLocation< OneDrive2PrefixContainerType>.FromString(this.ToString()); if (copy.LocalPath.Any()) { //pop last: @@ -76,7 +76,7 @@ namespace keepass2android.Io public override string ToString() { - string path = Onedrive2Prefix + string.Join("\\", (new List { User.Id, User.Name, + string path = (new OneDrive2PrefixContainerType()).Onedrive2Prefix + string.Join("\\", (new List { User.Id, User.Name, Share.Id, Share.Name,Share.WebUrl, string.Join("/", LocalPath.Select(i => Encode(i.Id)+":"+Encode(i.Name))), DriveId @@ -90,12 +90,12 @@ namespace keepass2android.Io return WebUtility.UrlEncode(s); } - public static OneDrive2ItemLocation FromString(string p) + public static OneDrive2ItemLocation FromString(string p) { - if ((p == null) || (p == Onedrive2Prefix)) - return new OneDrive2ItemLocation(); + if ((p == null) || (p == (new OneDrive2PrefixContainerType()).Onedrive2Prefix)) + return new OneDrive2ItemLocation(); - if (!p.StartsWith(Onedrive2Prefix)) + if (!p.StartsWith((new OneDrive2PrefixContainerType()).Onedrive2Prefix)) throw new Exception("path not starting with prefix!"); if (!p.Contains("?")) throw new Exception("not found postfix"); @@ -104,10 +104,10 @@ namespace keepass2android.Io if (int.Parse(lengthParts[1]) != p.Length) throw new Exception("Invalid length postfix in " + p); - p = p.Substring(Onedrive2Prefix.Length); + p = p.Substring((new OneDrive2PrefixContainerType()).Onedrive2Prefix.Length); if (p == "") - return new OneDrive2ItemLocation(); - OneDrive2ItemLocation result = new OneDrive2ItemLocation(); + return new OneDrive2ItemLocation(); + OneDrive2ItemLocation result = new OneDrive2ItemLocation(); var parts = p.Split("\\"); if (parts.Length != 7) { @@ -127,7 +127,7 @@ namespace keepass2android.Io var lppsubParts = lpp.Split(":"); if (lppsubParts.Length != 2) throw new Exception("Wrong number of subparts in in path " + p + ", " + lppsubParts); - result.LocalPath.Add(new Item {Id = Decode(lppsubParts[0]), Name = Decode(lppsubParts[1])}); + result.LocalPath.Add(new Item { Id = Decode(lppsubParts[0]), Name = Decode(lppsubParts[1]) }); } } result.DriveId = Decode(parts[6]); @@ -140,18 +140,18 @@ namespace keepass2android.Io return WebUtility.UrlDecode(p0); } - public OneDrive2ItemLocation BuildLocalChildLocation(string name, string id, string parentReferenceDriveId) + public OneDrive2ItemLocation BuildLocalChildLocation(string name, string id, string parentReferenceDriveId) { //copy this: - OneDrive2ItemLocation copy = OneDrive2ItemLocation.FromString(this.ToString()); - copy.LocalPath.Add(new Item { Name = name, Id = id}); + OneDrive2ItemLocation copy = OneDrive2ItemLocation.FromString(this.ToString()); + copy.LocalPath.Add(new Item { Name = name, Id = id }); copy.DriveId = parentReferenceDriveId; return copy; } - public static OneDrive2ItemLocation RootForUser(string accountUsername, string accountHomeAccountId) + public static OneDrive2ItemLocation RootForUser(string accountUsername, string accountHomeAccountId) { - OneDrive2ItemLocation loc = new OneDrive2ItemLocation + OneDrive2ItemLocation loc = new OneDrive2ItemLocation { User = { @@ -163,33 +163,33 @@ namespace keepass2android.Io return loc; } - public OneDrive2ItemLocation BuildShare(string id, string name, string webUrl, string driveId) + public OneDrive2ItemLocation BuildShare(string id, string name, string webUrl, string driveId) { - OneDrive2ItemLocation copy = OneDrive2ItemLocation.FromString(this.ToString()); + OneDrive2ItemLocation copy = OneDrive2ItemLocation.FromString(this.ToString()); copy.Share.Id = id; copy.Share.Name = name; copy.Share.WebUrl = webUrl; copy.DriveId = driveId; - + return copy; } - - } - public static IEnumerable Scopes + } + } + + + + public abstract class OneDrive2FileStorage : IFileStorage where OneDrive2PrefixContainerType: OneDrive2PrefixContainer, new() + { + + public static IPublicClientApplication _publicClientApp = null; + private string ClientID = "8374f801-0f55-407d-80cc-9a04fe86d9b2"; + + + public abstract IEnumerable Scopes { - get - { - return new List - { - "https://graph.microsoft.com/Files.Read", - "https://graph.microsoft.com/Files.Read.All", - "https://graph.microsoft.com/Files.ReadWrite", - "https://graph.microsoft.com/Files.ReadWrite.All", - "https://graph.microsoft.com/User.Read" - }; - } + get; } public OneDrive2FileStorage() @@ -201,10 +201,16 @@ namespace keepass2android.Io class PathItemBuilder { + private readonly string _specialFolder; public IGraphServiceClient client; - public OneDrive2ItemLocation itemLocation; + public OneDrive2ItemLocation itemLocation; + + public PathItemBuilder(string specialFolder) + { + _specialFolder = specialFolder; + } + - public IDriveItemRequestBuilder getPathItem() { IDriveItemRequestBuilder pathItem; @@ -214,7 +220,10 @@ namespace keepass2android.Io } if ("me".Equals(itemLocation.Share.Id)) { - pathItem = client.Me.Drive.Root; + if (_specialFolder == null) + pathItem = client.Me.Drive.Root; + else + pathItem = client.Me.Drive.Special[_specialFolder]; if (itemLocation.LocalPath.Any()) { pathItem = pathItem.ItemWithPath(itemLocation.LocalPathString); @@ -266,17 +275,23 @@ namespace keepass2android.Io } } + private string protocolId; - private const string protocolId = "onedrive2"; - - private string getProtocolId() + protected string ProtocolId { - return protocolId; + get + { + if (protocolId == null) + { + protocolId = (new OneDrive2PrefixContainerType()).Onedrive2ProtocolId; + } + return protocolId; + } } public IEnumerable SupportedProtocols { - get { yield return protocolId; } + get { yield return ProtocolId; } } Dictionary mClientByUser = @@ -284,7 +299,7 @@ namespace keepass2android.Io private IGraphServiceClient tryGetMsGraphClient(String path) { - String userId = OneDrive2ItemLocation.FromString(path).User.Id; + String userId = OneDrive2ItemLocation.FromString(path).User.Id; if (mClientByUser.ContainsKey(userId)) return mClientByUser[userId]; return null; @@ -324,14 +339,14 @@ namespace keepass2android.Io } - + protected abstract string SpecialFolder { get; } private PathItemBuilder GetPathItemBuilder(String path) { - PathItemBuilder result = new PathItemBuilder(); + PathItemBuilder result = new PathItemBuilder(SpecialFolder); - result.itemLocation = OneDrive2ItemLocation.FromString(path); + result.itemLocation = OneDrive2ItemLocation.FromString(path); if (string.IsNullOrEmpty(result.itemLocation.User?.Name)) { throw new Exception("path does not contain user"); @@ -433,10 +448,10 @@ namespace keepass2android.Io class OneDrive2FileStorageWriteTransaction : IWriteTransaction { private readonly string _path; - private readonly OneDrive2FileStorage _filestorage; + private readonly OneDrive2FileStorage _filestorage; private MemoryStream _memoryStream; - public OneDrive2FileStorageWriteTransaction(string path, OneDrive2FileStorage filestorage) + public OneDrive2FileStorageWriteTransaction(string path, OneDrive2FileStorage filestorage) { _path = path; _filestorage = filestorage; @@ -493,12 +508,12 @@ namespace keepass2android.Io public string GetFileExtension(IOConnectionInfo ioc) { - return UrlUtil.GetExtension(OneDrive2ItemLocation.FromString(ioc.Path).LocalPathString); + return UrlUtil.GetExtension(OneDrive2ItemLocation.FromString(ioc.Path).LocalPathString); } private string GetFilename(string path) { - string localPath = "/"+OneDrive2ItemLocation.FromString(path).LocalPath; + string localPath = "/"+OneDrive2ItemLocation.FromString(path).LocalPathString; return localPath.Substring(localPath.LastIndexOf("/", StringComparison.Ordinal) + 1); } @@ -582,7 +597,7 @@ namespace keepass2android.Io } - private FileDescription GetFileDescription(OneDrive2ItemLocation path, DriveItem i) + private FileDescription GetFileDescription(OneDrive2ItemLocation path, DriveItem i) { FileDescription e = new FileDescription(); if (i.Size != null) @@ -643,7 +658,7 @@ namespace keepass2android.Io public void StartSelectFile(IFileStorageSetupInitiatorActivity activity, bool isForSave, int requestCode, string protocolId) { - String path = getProtocolId() + "://"; + String path = ProtocolId+ "://"; activity.StartSelectFileProcess(IOConnectionInfo.FromPath(path), isForSave, requestCode); } @@ -740,7 +755,7 @@ namespace keepass2android.Io IAccount account = null; try { - String userId = OneDrive2ItemLocation.FromString(activity.Ioc.Path).User?.Id; + String userId = OneDrive2ItemLocation.FromString(activity.Ioc.Path).User?.Id; if (mClientByUser.ContainsKey(userId)) { finishActivityWithSuccess(activity); @@ -808,7 +823,7 @@ namespace keepass2android.Io string buildRootPathForUser(AuthenticationResult res) { - return OneDrive2ItemLocation.RootForUser(res.Account.Username, res.Account.HomeAccountId.Identifier).ToString(); + return OneDrive2ItemLocation.RootForUser(res.Account.Username, res.Account.HomeAccountId.Identifier).ToString(); } @@ -828,8 +843,8 @@ namespace keepass2android.Io { try { - var itemLocation = OneDrive2ItemLocation.FromString(ioc.Path); - string result = getProtocolId() + "://"; + var itemLocation = OneDrive2ItemLocation.FromString(ioc.Path); + string result = ProtocolId+ "://"; if (!string.IsNullOrEmpty(itemLocation.User?.Id)) { result += itemLocation.User?.Name; @@ -848,23 +863,31 @@ namespace keepass2android.Io } catch (Exception e) { - return e.ToString(); //TODO throw + Kp2aLog.Log("Invalid OneDrive location " + ioc.Path + + ". Note that SprEnging expressions like {DB_PATH} are not supported with OneDrive!"); + return ProtocolId + "://(invalid)"; } } - private List ListShares(OneDrive2ItemLocation parentPath, IGraphServiceClient client) + private List ListShares(OneDrive2ItemLocation parentPath, IGraphServiceClient client) { + List result = new List(); + DriveItem root = Task.Run(async () => await client.Me.Drive.Root.Request().GetAsync()).Result; FileDescription myEntry = GetFileDescription(parentPath.BuildShare("me","me","me", root.ParentReference?.DriveId), root); - myEntry.DisplayName = "My OneDrive"; + myEntry.DisplayName = MyOneDriveDisplayName; - result.Add(myEntry); + if (!CanListShares) + return result; + + + IDriveSharedWithMeCollectionPage sharedWithMeCollectionPage = Task.Run(async () => await client.Me.Drive.SharedWithMe().Request().GetAsync()).Result; @@ -887,6 +910,10 @@ namespace keepass2android.Io return result; } + protected virtual string MyOneDriveDisplayName { get { return "My OneDrive"; } } + + public abstract bool CanListShares { get; } + DriveItem TryFindFile(PathItemBuilder parent, string filename) { IDriveItemChildrenCollectionPage itemsPage = Task.Run(async () => await parent.getPathItem() @@ -920,7 +947,7 @@ namespace keepass2android.Io { DriveItem driveItem = new DriveItem(); driveItem.Name = newFilename; - + driveItem.File = new File(); PathItemBuilder pathItemBuilder = GetPathItemBuilder(parent); //see if such a file exists already: @@ -951,7 +978,7 @@ namespace keepass2android.Io public IOConnectionInfo GetParentPath(IOConnectionInfo ioc) { - return IOConnectionInfo.FromPath(OneDrive2ItemLocation.FromString(ioc.Path).Parent.ToString()); + return IOConnectionInfo.FromPath(OneDrive2ItemLocation.FromString(ioc.Path).Parent.ToString()); } public IOConnectionInfo GetFilePath(IOConnectionInfo folderPath, string filename) @@ -969,4 +996,61 @@ namespace keepass2android.Io return false; } } + + public class OneDrive2FullFileStorage: OneDrive2FileStorage + { + public override IEnumerable Scopes + { + get + { + return new List + { + "https://graph.microsoft.com/Files.ReadWrite", + "https://graph.microsoft.com/Files.ReadWrite.All" + }; + + } + } + + public override bool CanListShares { get { return true; } } + protected override string SpecialFolder { get { return null; } } + } + + + public class OneDrive2MyFilesFileStorage : OneDrive2FileStorage + { + public override IEnumerable Scopes + { + get + { + return new List + { + "https://graph.microsoft.com/Files.ReadWrite" + }; + + } + } + public override bool CanListShares { get { return false; } } + protected override string SpecialFolder { get { return null; } } + } + + + public class OneDrive2AppFolderFileStorage : OneDrive2FileStorage + { + public override IEnumerable Scopes + { + get + { + return new List + { + "https://graph.microsoft.com/Files.ReadWrite.AppFolder" + }; + + } + } + + protected override string SpecialFolder { get { return "approot"; } } + public override bool CanListShares { get { return false; } } + protected override string MyOneDriveDisplayName { get { return "Keepass2Android App Folder"; } } + } } \ No newline at end of file diff --git a/src/Kp2aBusinessLogic/Io/OneDrive2PrefixContainer.cs b/src/Kp2aBusinessLogic/Io/OneDrive2PrefixContainer.cs new file mode 100644 index 00000000..234e9a86 --- /dev/null +++ b/src/Kp2aBusinessLogic/Io/OneDrive2PrefixContainer.cs @@ -0,0 +1,26 @@ +namespace keepass2android.Io.ItemLocation +{ + public abstract class OneDrive2PrefixContainer + { + public abstract string Onedrive2ProtocolId { get; } + public string Onedrive2Prefix { get { return Onedrive2ProtocolId + "://"; } } + } + + //for permissions including all my files and all shared files + public class OneDrive2FullPrefixContainer : OneDrive2PrefixContainer + { + public override string Onedrive2ProtocolId { get { return "onedrive2_full"; }} + } + + //for permissions including all my files + public class OneDrive2MyFilesPrefixContainer : OneDrive2PrefixContainer + { + public override string Onedrive2ProtocolId { get { return "onedrive2_myfiles"; } } + } + + //for permissions to app folder only + public class OneDrive2AppFolderPrefixContainer : OneDrive2PrefixContainer + { + public override string Onedrive2ProtocolId { get { return "onedrive2_appfolder"; } } + } +} \ No newline at end of file diff --git a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj index 644828f9..e14a1d8e 100644 --- a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj +++ b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj @@ -89,6 +89,7 @@ + diff --git a/src/keepass2android/CreateDatabaseActivity.cs b/src/keepass2android/CreateDatabaseActivity.cs index 0ba1dc13..f16081d0 100644 --- a/src/keepass2android/CreateDatabaseActivity.cs +++ b/src/keepass2android/CreateDatabaseActivity.cs @@ -253,10 +253,10 @@ namespace keepass2android int protocolSeparatorPos = displayPath.IndexOf("://", StringComparison.Ordinal); string protocolId = protocolSeparatorPos < 0 ? "file" : displayPath.Substring(0, protocolSeparatorPos); - Drawable drawable = App.Kp2a.GetResourceDrawable("ic_storage_" + protocolId); + Drawable drawable = App.Kp2a.GetStorageIcon(protocolId); FindViewById(Resource.Id.filestorage_logo).SetImageDrawable(drawable); - String title = App.Kp2a.GetResourceString("filestoragename_" + protocolId); + String title = App.Kp2a.GetStorageDisplayName(protocolId); FindViewById(Resource.Id.filestorage_label).Text = title; FindViewById(Resource.Id.label_filename).Text = protocolSeparatorPos < 0 ? diff --git a/src/keepass2android/EntryEditActivity.cs b/src/keepass2android/EntryEditActivity.cs index b907aff3..e19451b2 100644 --- a/src/keepass2android/EntryEditActivity.cs +++ b/src/keepass2android/EntryEditActivity.cs @@ -968,10 +968,10 @@ namespace keepass2android int protocolSeparatorPos = ioc.Path.IndexOf("://", StringComparison.Ordinal); string protocolId = protocolSeparatorPos < 0 ? "file" : ioc.Path.Substring(0, protocolSeparatorPos); - Drawable drawable = App.Kp2a.GetResourceDrawable("ic_storage_" + protocolId); + Drawable drawable = App.Kp2a.GetStorageIcon(protocolId); ees.FindViewById(Resource.Id.filestorage_logo).SetImageDrawable(drawable); - String fs_title = App.Kp2a.GetResourceString("filestoragename_" + protocolId); + String fs_title = App.Kp2a.GetStorageDisplayName(protocolId); ees.FindViewById(Resource.Id.filestorage_label).Text = fs_title; string displayPath = fileStorage.GetDisplayName(ioc); diff --git a/src/keepass2android/FileStorageSelectionActivity.cs b/src/keepass2android/FileStorageSelectionActivity.cs index b93d07ec..cd931b48 100644 --- a/src/keepass2android/FileStorageSelectionActivity.cs +++ b/src/keepass2android/FileStorageSelectionActivity.cs @@ -86,6 +86,9 @@ namespace keepass2android #if NoNet _displayedProtocolIds.Add("kp2a"); #endif + _displayedProtocolIds = _displayedProtocolIds.GroupBy(p => App.Kp2a.GetStorageMainTypeDisplayName(p)) + .Select(g => string.Join(",", g)).ToList(); + } public override Object GetItem(int position) @@ -135,14 +138,15 @@ namespace keepass2android var protocolId = _displayedProtocolIds[position]; btn.Tag = protocolId; + string firstProtocolInList = protocolId.Split(",").First(); - Drawable drawable = App.Kp2a.GetResourceDrawable("ic_storage_" + protocolId); + Drawable drawable = App.Kp2a.GetStorageIcon(firstProtocolInList); String title = protocolId == "kp2a" ? App.Kp2a.GetResourceString("get_regular_version") : - App.Kp2a.GetResourceString("filestoragename_" + protocolId); + App.Kp2a.GetStorageMainTypeDisplayName(firstProtocolInList); var str = new SpannableString(title); btn.TextFormatted = str; @@ -167,13 +171,28 @@ namespace keepass2android return; } + if (protocolId.Contains(",")) + { + //bring up a selection dialog to select the variant of the file storage + AlertDialog.Builder builder = new AlertDialog.Builder(this); + + builder.SetItems(protocolId.Split(",").Select(singleProtocolId => App.Kp2a.GetStorageDisplayName(singleProtocolId)).ToArray(), + delegate(object sender, DialogClickEventArgs args) + { + string[] singleProtocolIds = protocolId.Split(","); + OnItemSelected(singleProtocolIds[args.Which]); + }); + builder.Show(); + return; + } + var field = typeof(Resource.String).GetField("filestoragehelp_" + protocolId); if (field == null) { //no help available ReturnProtocol(protocolId); } - else + else { //set help: string help = GetString((int)field.GetValue(null)); diff --git a/src/keepass2android/PasswordActivity.cs b/src/keepass2android/PasswordActivity.cs index 3311eafe..9f5a8e05 100644 --- a/src/keepass2android/PasswordActivity.cs +++ b/src/keepass2android/PasswordActivity.cs @@ -346,12 +346,12 @@ namespace keepass2android int protocolSeparatorPos = displayPath.IndexOf("://", StringComparison.Ordinal); string protocolId = protocolSeparatorPos < 0 ? "file" : displayPath.Substring(0, protocolSeparatorPos); - Drawable drawable = App.Kp2a.GetResourceDrawable("ic_storage_" + protocolId); + Drawable drawable = App.Kp2a.GetStorageIcon(protocolId); FindViewById(Resource.Id.filestorage_logo).SetImageDrawable(drawable); FindViewById(Resource.Id.filestorage_logo).Visibility = ViewStates.Visible; - String title = App.Kp2a.GetResourceString("filestoragename_" + protocolId); + String title = App.Kp2a.GetStorageDisplayName(protocolId); FindViewById(Resource.Id.filestorage_label).Text = title; FindViewById(Resource.Id.filestorage_label).Visibility = ViewStates.Visible; diff --git a/src/keepass2android/Resources/values/strings.xml b/src/keepass2android/Resources/values/strings.xml index b496af39..c53d0a6f 100644 --- a/src/keepass2android/Resources/values/strings.xml +++ b/src/keepass2android/Resources/values/strings.xml @@ -553,6 +553,9 @@ This storage type will only request access to the "Applications/Keepass2Android" folder. If you want to use an existing database from your PCloud account, please make sure the file is placed in this folder. OneDrive OneDrive + All files and shared files + My files + Keepass2Android App folder SFTP (SSH File Transfer) System file picker diff --git a/src/keepass2android/SelectCurrentDbActivity.cs b/src/keepass2android/SelectCurrentDbActivity.cs index 4881a404..9efed66c 100644 --- a/src/keepass2android/SelectCurrentDbActivity.cs +++ b/src/keepass2android/SelectCurrentDbActivity.cs @@ -112,7 +112,7 @@ namespace keepass2android if (position < _displayedDatabases.Count) { var db = _displayedDatabases[position]; - drawable = App.Kp2a.GetResourceDrawable("ic_storage_" + Util.GetProtocolId(db.Ioc)); + drawable = App.Kp2a.GetStorageIcon(Util.GetProtocolId(db.Ioc)); displayName = db.KpDatabase.Name; displayName += "\n" + App.Kp2a.GetFileStorage(db.Ioc).GetDisplayName(db.Ioc); btn.SetBackgroundResource(Resource.Drawable.storagetype_button_bg); diff --git a/src/keepass2android/app/App.cs b/src/keepass2android/app/App.cs index 2a7b4d47..954a2ae7 100644 --- a/src/keepass2android/app/App.cs +++ b/src/keepass2android/app/App.cs @@ -492,7 +492,17 @@ namespace keepass2android throw new Exception("Invalid key " + key); return Application.Context.GetString((int)field.GetValue(null)); } - public Drawable GetResourceDrawable(string key) + + public Drawable GetStorageIcon(string protocolId) + { + //storages can provide variants but still use the same icon for all + if (protocolId.Contains("_")) + protocolId = protocolId.Split("_").First(); + return GetResourceDrawable("ic_storage_" + protocolId); + } + + + public Drawable GetResourceDrawable(string key) { if (key == "ic_storage_skydrive") key = "ic_storage_onedrive"; //resource was renamed. do this to avoid crashes with legacy file entries. @@ -688,7 +698,9 @@ namespace keepass2android new DropboxAppFolderFileStorage(Application.Context, this), new GoogleDriveFileStorage(Application.Context, this), new OneDriveFileStorage(Application.Context, this), - new OneDrive2FileStorage(), + new OneDrive2FullFileStorage(), + new OneDrive2MyFilesFileStorage(), + new OneDrive2AppFolderFileStorage(), new SftpFileStorage(Application.Context, this), new NetFtpFileStorage(Application.Context, this), new WebDavFileStorage(this), @@ -1104,6 +1116,27 @@ namespace keepass2android { return _childDatabases.Any(ioc => ioc.IsSameFileAs(db.Ioc)); } + + public string GetStorageMainTypeDisplayName(string protocolId) + { + var parts = protocolId.Split("_"); + return GetResourceString("filestoragename_" + parts[0]); + + } + + public string GetStorageDisplayName(string protocolId) + { + if (protocolId.Contains("_")) + { + var parts = protocolId.Split("_"); + return GetResourceString("filestoragename_" + parts[0]) + " (" + + GetResourceString("filestoragename_" + protocolId) + ")"; + + } + else + return GetResourceString("filestoragename_" + protocolId); + + } }