improvements to OneDrive2 implementation: it's now possible select between different access scopes, also fixed several issues
This commit is contained in:
@@ -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<OneDrive2PrefixContainerType> 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<Item> LocalPath { get; set; } = new List<Item>();
|
||||
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<OneDrive2PrefixContainerType> 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<string> { User.Id, User.Name,
|
||||
string path = (new OneDrive2PrefixContainerType()).Onedrive2Prefix + string.Join("\\", (new List<string> { 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<OneDrive2PrefixContainerType> FromString(string p)
|
||||
{
|
||||
if ((p == null) || (p == Onedrive2Prefix))
|
||||
return new OneDrive2ItemLocation();
|
||||
if ((p == null) || (p == (new OneDrive2PrefixContainerType()).Onedrive2Prefix))
|
||||
return new OneDrive2ItemLocation<OneDrive2PrefixContainerType>();
|
||||
|
||||
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<OneDrive2PrefixContainerType>();
|
||||
OneDrive2ItemLocation<OneDrive2PrefixContainerType> result = new OneDrive2ItemLocation<OneDrive2PrefixContainerType>();
|
||||
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<OneDrive2PrefixContainerType> 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<OneDrive2PrefixContainerType> copy = OneDrive2ItemLocation<OneDrive2PrefixContainerType>.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<OneDrive2PrefixContainerType> RootForUser(string accountUsername, string accountHomeAccountId)
|
||||
{
|
||||
OneDrive2ItemLocation loc = new OneDrive2ItemLocation
|
||||
OneDrive2ItemLocation<OneDrive2PrefixContainerType> loc = new OneDrive2ItemLocation<OneDrive2PrefixContainerType>
|
||||
{
|
||||
User =
|
||||
{
|
||||
@@ -163,9 +163,9 @@ namespace keepass2android.Io
|
||||
return loc;
|
||||
}
|
||||
|
||||
public OneDrive2ItemLocation BuildShare(string id, string name, string webUrl, string driveId)
|
||||
public OneDrive2ItemLocation<OneDrive2PrefixContainerType> BuildShare(string id, string name, string webUrl, string driveId)
|
||||
{
|
||||
OneDrive2ItemLocation copy = OneDrive2ItemLocation.FromString(this.ToString());
|
||||
OneDrive2ItemLocation<OneDrive2PrefixContainerType> copy = OneDrive2ItemLocation<OneDrive2PrefixContainerType>.FromString(this.ToString());
|
||||
copy.Share.Id = id;
|
||||
copy.Share.Name = name;
|
||||
copy.Share.WebUrl = webUrl;
|
||||
@@ -176,20 +176,20 @@ namespace keepass2android.Io
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static IEnumerable<string> Scopes
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<string>
|
||||
{
|
||||
"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"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
public abstract class OneDrive2FileStorage<OneDrive2PrefixContainerType> : IFileStorage where OneDrive2PrefixContainerType: OneDrive2PrefixContainer, new()
|
||||
{
|
||||
|
||||
public static IPublicClientApplication _publicClientApp = null;
|
||||
private string ClientID = "8374f801-0f55-407d-80cc-9a04fe86d9b2";
|
||||
|
||||
|
||||
public abstract IEnumerable<string> Scopes
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public OneDrive2FileStorage()
|
||||
@@ -201,8 +201,14 @@ namespace keepass2android.Io
|
||||
|
||||
class PathItemBuilder
|
||||
{
|
||||
private readonly string _specialFolder;
|
||||
public IGraphServiceClient client;
|
||||
public OneDrive2ItemLocation itemLocation;
|
||||
public OneDrive2ItemLocation<OneDrive2PrefixContainerType> itemLocation;
|
||||
|
||||
public PathItemBuilder(string specialFolder)
|
||||
{
|
||||
_specialFolder = specialFolder;
|
||||
}
|
||||
|
||||
|
||||
public IDriveItemRequestBuilder getPathItem()
|
||||
@@ -214,7 +220,10 @@ namespace keepass2android.Io
|
||||
}
|
||||
if ("me".Equals(itemLocation.Share.Id))
|
||||
{
|
||||
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
|
||||
{
|
||||
get
|
||||
{
|
||||
if (protocolId == null)
|
||||
{
|
||||
protocolId = (new OneDrive2PrefixContainerType()).Onedrive2ProtocolId;
|
||||
}
|
||||
return protocolId;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> SupportedProtocols
|
||||
{
|
||||
get { yield return protocolId; }
|
||||
get { yield return ProtocolId; }
|
||||
}
|
||||
|
||||
Dictionary<String /*userid*/, IGraphServiceClient> mClientByUser =
|
||||
@@ -284,7 +299,7 @@ namespace keepass2android.Io
|
||||
|
||||
private IGraphServiceClient tryGetMsGraphClient(String path)
|
||||
{
|
||||
String userId = OneDrive2ItemLocation.FromString(path).User.Id;
|
||||
String userId = OneDrive2ItemLocation<OneDrive2PrefixContainerType>.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<OneDrive2PrefixContainerType>.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<OneDrive2PrefixContainerType> _filestorage;
|
||||
private MemoryStream _memoryStream;
|
||||
|
||||
public OneDrive2FileStorageWriteTransaction(string path, OneDrive2FileStorage filestorage)
|
||||
public OneDrive2FileStorageWriteTransaction(string path, OneDrive2FileStorage<OneDrive2PrefixContainerType> 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<OneDrive2PrefixContainerType>.FromString(ioc.Path).LocalPathString);
|
||||
}
|
||||
|
||||
private string GetFilename(string path)
|
||||
{
|
||||
string localPath = "/"+OneDrive2ItemLocation.FromString(path).LocalPath;
|
||||
string localPath = "/"+OneDrive2ItemLocation<OneDrive2PrefixContainerType>.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<OneDrive2PrefixContainerType> 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<OneDrive2PrefixContainerType>.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<OneDrive2PrefixContainerType>.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<OneDrive2PrefixContainerType>.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<FileDescription> ListShares(OneDrive2ItemLocation parentPath, IGraphServiceClient client)
|
||||
private List<FileDescription> ListShares(OneDrive2ItemLocation<OneDrive2PrefixContainerType> parentPath, IGraphServiceClient client)
|
||||
{
|
||||
|
||||
List<FileDescription> result = new List<FileDescription>();
|
||||
|
||||
|
||||
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<OneDrive2PrefixContainerType>.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<OneDrive2FullPrefixContainer>
|
||||
{
|
||||
public override IEnumerable<string> Scopes
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<string>
|
||||
{
|
||||
"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<OneDrive2MyFilesPrefixContainer>
|
||||
{
|
||||
public override IEnumerable<string> Scopes
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<string>
|
||||
{
|
||||
"https://graph.microsoft.com/Files.ReadWrite"
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
public override bool CanListShares { get { return false; } }
|
||||
protected override string SpecialFolder { get { return null; } }
|
||||
}
|
||||
|
||||
|
||||
public class OneDrive2AppFolderFileStorage : OneDrive2FileStorage<OneDrive2AppFolderPrefixContainer>
|
||||
{
|
||||
public override IEnumerable<string> Scopes
|
||||
{
|
||||
get
|
||||
{
|
||||
return new List<string>
|
||||
{
|
||||
"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"; } }
|
||||
}
|
||||
}
|
26
src/Kp2aBusinessLogic/Io/OneDrive2PrefixContainer.cs
Normal file
26
src/Kp2aBusinessLogic/Io/OneDrive2PrefixContainer.cs
Normal file
@@ -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"; } }
|
||||
}
|
||||
}
|
@@ -89,6 +89,7 @@
|
||||
<Compile Include="Io\NetFtpFileStorage.cs" />
|
||||
<Compile Include="Io\OfflineSwitchableFileStorage.cs" />
|
||||
<Compile Include="Io\OneDrive2FileStorage.cs" />
|
||||
<Compile Include="Io\OneDrive2PrefixContainer.cs" />
|
||||
<Compile Include="Io\PCloudFileStorage.cs" />
|
||||
<Compile Include="Io\SftpFileStorage.cs" />
|
||||
<Compile Include="Io\OneDriveFileStorage.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<ImageView>(Resource.Id.filestorage_logo).SetImageDrawable(drawable);
|
||||
|
||||
String title = App.Kp2a.GetResourceString("filestoragename_" + protocolId);
|
||||
String title = App.Kp2a.GetStorageDisplayName(protocolId);
|
||||
FindViewById<TextView>(Resource.Id.filestorage_label).Text = title;
|
||||
|
||||
FindViewById<TextView>(Resource.Id.label_filename).Text = protocolSeparatorPos < 0 ?
|
||||
|
@@ -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<ImageView>(Resource.Id.filestorage_logo).SetImageDrawable(drawable);
|
||||
|
||||
String fs_title = App.Kp2a.GetResourceString("filestoragename_" + protocolId);
|
||||
String fs_title = App.Kp2a.GetStorageDisplayName(protocolId);
|
||||
ees.FindViewById<TextView>(Resource.Id.filestorage_label).Text = fs_title;
|
||||
|
||||
string displayPath = fileStorage.GetDisplayName(ioc);
|
||||
|
@@ -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,6 +171,21 @@ 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)
|
||||
{
|
||||
|
@@ -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<ImageView>(Resource.Id.filestorage_logo).SetImageDrawable(drawable);
|
||||
FindViewById<ImageView>(Resource.Id.filestorage_logo).Visibility = ViewStates.Visible;
|
||||
|
||||
|
||||
String title = App.Kp2a.GetResourceString("filestoragename_" + protocolId);
|
||||
String title = App.Kp2a.GetStorageDisplayName(protocolId);
|
||||
FindViewById<TextView>(Resource.Id.filestorage_label).Text = title;
|
||||
FindViewById<TextView>(Resource.Id.filestorage_label).Visibility = ViewStates.Visible;
|
||||
|
||||
|
@@ -553,6 +553,9 @@
|
||||
<string name="filestoragehelp_pcloud">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.</string>
|
||||
<string name="filestoragename_onedrive">OneDrive</string>
|
||||
<string name="filestoragename_onedrive2">OneDrive</string>
|
||||
<string name="filestoragename_onedrive2_full">All files and shared files</string>
|
||||
<string name="filestoragename_onedrive2_myfiles">My files</string>
|
||||
<string name="filestoragename_onedrive2_appfolder">Keepass2Android App folder</string>
|
||||
<string name="filestoragename_sftp">SFTP (SSH File Transfer)</string>
|
||||
<string name="filestoragename_content">System file picker</string>
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -492,6 +492,16 @@ namespace keepass2android
|
||||
throw new Exception("Invalid key " + key);
|
||||
return Application.Context.GetString((int)field.GetValue(null));
|
||||
}
|
||||
|
||||
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")
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user