fix build issues related to removal of deprecated OneDrive API jars. onedrive:// is now no longer supported, but has been replaced with onedrive2:// a long time ago already.
This commit is contained in:
@@ -1,31 +1,23 @@
|
||||
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;
|
||||
using Exception = Java.Lang.Exception;
|
||||
|
||||
namespace keepass2android.Io
|
||||
{
|
||||
public class OneDriveFileStorage: JavaFileStorage
|
||||
/// <summary>
|
||||
/// This IFileStorage implementation becomes picked if a user is using a skydrive:// or onedrive:// file.
|
||||
/// These refer to an old (Java) implementation which was replaced starting in 2019. The successor uses onedrive2:// (see OneDrive2FileStorage)
|
||||
/// The Java implementation was removed in 2024 when the jar files became unavailable. We are keeping this file to notify any user who haven't updated their
|
||||
/// file storage within 5 years.
|
||||
/// This file should be removed around mid 2025.
|
||||
/// </summary>
|
||||
public class OneDriveFileStorage: IFileStorage
|
||||
{
|
||||
private const string ClientId = "000000004010C234";
|
||||
|
||||
public OneDriveFileStorage(Context ctx, IKp2aApp app) :
|
||||
base(new Keepass2android.Javafilestorage.OneDriveStorage(ctx, ClientId), app)
|
||||
{
|
||||
}
|
||||
|
||||
public override IEnumerable<string> SupportedProtocols
|
||||
|
||||
public IEnumerable<string> SupportedProtocols
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -34,10 +26,146 @@ namespace keepass2android.Io
|
||||
}
|
||||
}
|
||||
|
||||
public override bool UserShouldBackup
|
||||
private Exception GetDeprecatedMessage()
|
||||
{
|
||||
return new Exception(
|
||||
"You have opened your file through a deprecated Microsoft API. Please select Change database, Open Database and then select One Drive again.");
|
||||
}
|
||||
|
||||
public bool UserShouldBackup
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
public void Delete(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public bool CheckForFileChangeFast(IOConnectionInfo ioc, string previousFileVersion)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public string GetCurrentFileVersionFast(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public Stream OpenFileForRead(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public string GetFileExtension(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public bool RequiresCredentials(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public void CreateDirectory(IOConnectionInfo ioc, string newDirName)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public IEnumerable<FileDescription> ListContents(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public FileDescription GetFileDescription(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public bool RequiresSetup(IOConnectionInfo ioConnection)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public string IocToPath(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public void StartSelectFile(IFileStorageSetupInitiatorActivity activity, bool isForSave, int requestCode, string protocolId)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public void PrepareFileUsage(IFileStorageSetupInitiatorActivity activity, IOConnectionInfo ioc, int requestCode,
|
||||
bool alwaysReturnSuccess)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public void PrepareFileUsage(Context ctx, IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public void OnCreate(IFileStorageSetupActivity activity, Bundle savedInstanceState)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public void OnResume(IFileStorageSetupActivity activity)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public void OnStart(IFileStorageSetupActivity activity)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public void OnActivityResult(IFileStorageSetupActivity activity, int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public string GetDisplayName(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public string CreateFilePath(string parent, string newFilename)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public IOConnectionInfo GetParentPath(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public IOConnectionInfo GetFilePath(IOConnectionInfo folderPath, string filename)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public bool IsPermanentLocation(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public bool IsReadOnly(IOConnectionInfo ioc, OptionalOut<UiStringKey> reason = null)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -4,11 +4,10 @@ android {
|
||||
|
||||
namespace 'keepass2android.javafilestorage'
|
||||
|
||||
compileSdkVersion 33
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 15
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 33
|
||||
compileSdk 34
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
@@ -22,6 +21,10 @@ android {
|
||||
sourceCompatibility 11
|
||||
targetCompatibility 11
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude 'META-INF/DEPENDENCIES'
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -31,7 +34,7 @@ NOTE: If you change dependencies here, don't forget to update the jar files in J
|
||||
dependencies {
|
||||
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.10.0-RC1'
|
||||
implementation 'com.burgstaller:okhttp-digest:2.5'
|
||||
implementation 'io.github.rburgst:okhttp-digest:2.5'
|
||||
|
||||
implementation 'com.google.http-client:google-http-client-gson:1.20.0'
|
||||
implementation('com.google.api-client:google-api-client-android:1.30.5') {
|
||||
@@ -43,14 +46,8 @@ dependencies {
|
||||
implementation 'com.google.api-client:google-api-client-android:1.30.5'
|
||||
|
||||
implementation 'com.google.android.gms:play-services-auth:20.4.0'
|
||||
//onedrive:
|
||||
implementation('com.onedrive.sdk:onedrive-sdk-android:1.2.0') {
|
||||
transitive = false
|
||||
}
|
||||
implementation 'com.pcloud.sdk:java-core:1.9.1'
|
||||
implementation 'com.pcloud.sdk:android:1.9.1'
|
||||
implementation 'com.google.code.gson:gson:2.8.6'
|
||||
implementation 'com.microsoft.services.msa:msa-auth:0.8.6'
|
||||
implementation 'com.microsoft.aad:adal:1.14.0'
|
||||
|
||||
}
|
||||
|
@@ -1,436 +0,0 @@
|
||||
package keepass2android.javafilestorage;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import com.onedrive.sdk.core.DefaultClientConfig;
|
||||
import com.onedrive.sdk.core.IClientConfig;
|
||||
import com.onedrive.sdk.core.OneDriveErrorCodes;
|
||||
import com.onedrive.sdk.extensions.IItemCollectionPage;
|
||||
import com.onedrive.sdk.extensions.IItemCollectionRequestBuilder;
|
||||
import com.onedrive.sdk.extensions.IOneDriveClient;
|
||||
import com.onedrive.sdk.extensions.Item;
|
||||
import com.onedrive.sdk.extensions.OneDriveClient;
|
||||
import com.onedrive.sdk.http.OneDriveServiceException;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Philipp on 20.11.2016.
|
||||
*/
|
||||
public class OneDriveStorage extends JavaFileStorageBase
|
||||
{
|
||||
final IClientConfig oneDriveConfig;
|
||||
final keepass2android.javafilestorage.onedrive.MyMSAAuthenticator msaAuthenticator;
|
||||
|
||||
IOneDriveClient oneDriveClient;
|
||||
|
||||
public OneDriveStorage(final Context context, final String clientId) {
|
||||
msaAuthenticator = new keepass2android.javafilestorage.onedrive.MyMSAAuthenticator(context) {
|
||||
@Override
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getScopes() {
|
||||
return new String[] { "offline_access", "onedrive.readwrite" };
|
||||
}
|
||||
};
|
||||
oneDriveConfig = DefaultClientConfig.createWithAuthenticator(msaAuthenticator);
|
||||
initAuthenticator(null);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean requiresSetup(String path) {
|
||||
return !isConnected(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startSelectFile(FileStorageSetupInitiatorActivity activity, boolean isForSave, int requestCode) {
|
||||
|
||||
initAuthenticator((Activity)activity.getActivity());
|
||||
|
||||
String path = getProtocolId()+":///";
|
||||
Log.d("KP2AJ", "startSelectFile "+path+", connected: "+path);
|
||||
if (isConnected(null))
|
||||
{
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(EXTRA_IS_FOR_SAVE, isForSave);
|
||||
intent.putExtra(EXTRA_PATH, path);
|
||||
activity.onImmediateResult(requestCode, RESULT_FILECHOOSER_PREPARED, intent);
|
||||
}
|
||||
else
|
||||
{
|
||||
activity.startSelectFileProcess(path, isForSave, requestCode);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isConnected(Activity activity) {
|
||||
if (oneDriveClient == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log.d("KP2AJ", "trying silent login");
|
||||
if (msaAuthenticator.loginSilent() != null)
|
||||
{
|
||||
Log.d("KP2AJ", "ok: silent login");
|
||||
|
||||
oneDriveClient = buildClient(activity);
|
||||
|
||||
|
||||
}
|
||||
else Log.d("KP2AJ", "trying silent login failed.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return oneDriveClient != null;
|
||||
}
|
||||
|
||||
private void initAuthenticator(Activity activity) {
|
||||
msaAuthenticator.init(
|
||||
oneDriveConfig.getExecutors(),
|
||||
oneDriveConfig.getHttpProvider(),
|
||||
activity,
|
||||
oneDriveConfig.getLogger());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void prepareFileUsage(FileStorageSetupInitiatorActivity activity, String path, int requestCode, boolean alwaysReturnSuccess) {
|
||||
initAuthenticator((Activity)activity.getActivity());
|
||||
if (isConnected((Activity)activity.getActivity()))
|
||||
{
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(EXTRA_PATH, path);
|
||||
activity.onImmediateResult(requestCode, RESULT_FILEUSAGE_PREPARED, intent);
|
||||
}
|
||||
else
|
||||
{
|
||||
activity.startFileUsageProcess(path, requestCode, alwaysReturnSuccess);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocolId() {
|
||||
return "onedrive";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareFileUsage(Context appContext, String path) throws UserInteractionRequiredException {
|
||||
if (!isConnected(null))
|
||||
{
|
||||
throw new UserInteractionRequiredException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(FileStorageSetupActivity activity, Bundle savedInstanceState) {
|
||||
|
||||
Log.d("KP2AJ", "OnCreate");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume(final FileStorageSetupActivity activity) {
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private IOneDriveClient buildClient(Activity activity) {
|
||||
|
||||
return new OneDriveClient.Builder()
|
||||
.fromConfig(oneDriveConfig)
|
||||
.loginAndBuildClient(activity);
|
||||
|
||||
}
|
||||
|
||||
String getPathFromSkydrivePath(String skydrivePath)
|
||||
{
|
||||
String path = "";
|
||||
if (skydrivePath.equals(""))
|
||||
return "";
|
||||
|
||||
String[] parts = skydrivePath.split("/");
|
||||
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
String part = parts[i];
|
||||
logDebug("parsing part " + part);
|
||||
int indexOfSeparator = part.lastIndexOf(NAME_ID_SEP);
|
||||
if (indexOfSeparator < 0) {
|
||||
// seems invalid, but we're very generous here
|
||||
path += "/" + part;
|
||||
continue;
|
||||
}
|
||||
String name = part.substring(0, indexOfSeparator);
|
||||
try {
|
||||
name = decode(name);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// ignore
|
||||
}
|
||||
path += "/" + name;
|
||||
}
|
||||
logDebug("return " +path + ". original was " + skydrivePath);
|
||||
return path;
|
||||
|
||||
}
|
||||
|
||||
String removeProtocol(String path) throws Exception {
|
||||
if (path == null)
|
||||
return null;
|
||||
if (path.startsWith("skydrive"))
|
||||
return getPathFromSkydrivePath(path.substring("skydrive://".length()));
|
||||
return path.substring(getProtocolId().length()+3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName(String path) {
|
||||
|
||||
if (path == null)
|
||||
return null;
|
||||
if (path.startsWith("skydrive"))
|
||||
return getProtocolId()+"://"+getPathFromSkydrivePath(path.substring("skydrive://".length()));
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilename(String path) throws Exception {
|
||||
return path.substring(path.lastIndexOf("/")+1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkForFileChangeFast(String path, String previousFileVersion) throws Exception {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentFileVersionFast(String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream openFileForRead(String path) throws Exception {
|
||||
try {
|
||||
path = removeProtocol(path);
|
||||
logDebug("openFileForRead. Path="+path);
|
||||
InputStream result = oneDriveClient.getDrive()
|
||||
.getRoot()
|
||||
.getItemWithPath(path)
|
||||
.getContent()
|
||||
.buildRequest()
|
||||
.get();
|
||||
logDebug("ok");
|
||||
return result;
|
||||
|
||||
}
|
||||
catch (OneDriveServiceException e)
|
||||
{
|
||||
throw convertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Exception convertException(OneDriveServiceException e) {
|
||||
if (e.isError(OneDriveErrorCodes.ItemNotFound))
|
||||
return new FileNotFoundException(e.getMessage());
|
||||
return e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uploadFile(String path, byte[] data, boolean writeTransactional) throws Exception {
|
||||
try {
|
||||
path = removeProtocol(path);
|
||||
oneDriveClient.getDrive()
|
||||
.getRoot()
|
||||
.getItemWithPath(path)
|
||||
.getContent()
|
||||
.buildRequest()
|
||||
.put(data);
|
||||
} catch (OneDriveServiceException e) {
|
||||
throw convertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createFolder(String parentPath, String newDirName) throws Exception {
|
||||
throw new Exception("not implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createFilePath(String parentPath, String newFileName) throws Exception {
|
||||
String path = parentPath;
|
||||
if (!path.endsWith("/"))
|
||||
path = path + "/";
|
||||
path = path + newFileName;
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FileEntry> listFiles(String parentPath) throws Exception {
|
||||
try {
|
||||
ArrayList<FileEntry> result = new ArrayList<FileEntry>();
|
||||
parentPath = removeProtocol(parentPath);
|
||||
IItemCollectionPage itemsPage = oneDriveClient.getDrive()
|
||||
.getRoot()
|
||||
.getItemWithPath(parentPath)
|
||||
.getChildren()
|
||||
.buildRequest()
|
||||
.get();
|
||||
if (parentPath.endsWith("/"))
|
||||
parentPath = parentPath.substring(0,parentPath.length()-1);
|
||||
while (true)
|
||||
{
|
||||
List<Item> items = itemsPage.getCurrentPage();
|
||||
if (items.isEmpty())
|
||||
return result;
|
||||
|
||||
for (Item i: items)
|
||||
{
|
||||
FileEntry e = getFileEntry(parentPath + "/" + i.name, i);
|
||||
Log.d("KP2AJ", e.path);
|
||||
result.add(e);
|
||||
}
|
||||
IItemCollectionRequestBuilder nextPageReqBuilder = itemsPage.getNextPage();
|
||||
if (nextPageReqBuilder == null)
|
||||
return result;
|
||||
itemsPage = nextPageReqBuilder.buildRequest().get();
|
||||
|
||||
}
|
||||
} catch (OneDriveServiceException e) {
|
||||
throw convertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private FileEntry getFileEntry(String path, Item i) {
|
||||
FileEntry e = new FileEntry();
|
||||
if (i.size != null)
|
||||
e.sizeInBytes = i.size;
|
||||
else if ((i.remoteItem != null) && (i.remoteItem.size != null))
|
||||
e.sizeInBytes = i.remoteItem.size;
|
||||
|
||||
e.displayName = i.name;
|
||||
e.canRead = e.canWrite = true;
|
||||
e.path = getProtocolId() +"://"+path;
|
||||
if (i.lastModifiedDateTime != null)
|
||||
e.lastModifiedTime = i.lastModifiedDateTime.getTimeInMillis();
|
||||
else if ((i.remoteItem != null)&&(i.remoteItem.lastModifiedDateTime != null))
|
||||
e.lastModifiedTime = i.remoteItem.lastModifiedDateTime.getTimeInMillis();
|
||||
e.isDirectory = (i.folder != null) || ((i.remoteItem != null) && (i.remoteItem.folder != null));
|
||||
return e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileEntry getFileEntry(String filename) throws Exception {
|
||||
try {
|
||||
filename = removeProtocol(filename);
|
||||
Item item = oneDriveClient.getDrive()
|
||||
.getRoot()
|
||||
.getItemWithPath(filename)
|
||||
.buildRequest()
|
||||
.get();
|
||||
return getFileEntry(filename, item);
|
||||
} catch (OneDriveServiceException e) {
|
||||
throw convertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String path) throws Exception {
|
||||
try {
|
||||
path = removeProtocol(path);
|
||||
oneDriveClient.getDrive()
|
||||
.getRoot()
|
||||
.getItemWithPath(path)
|
||||
.buildRequest()
|
||||
.delete();
|
||||
} catch (OneDriveServiceException e) {
|
||||
throw convertException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(final FileStorageSetupActivity activity) {
|
||||
Log.d("KP2AJ", "onStart");
|
||||
if (activity.getProcessName().equals(PROCESS_NAME_SELECTFILE))
|
||||
activity.getState().putString(EXTRA_PATH, activity.getPath());
|
||||
|
||||
JavaFileStorage.FileStorageSetupActivity storageSetupAct = activity;
|
||||
|
||||
if (oneDriveClient != null) {
|
||||
Log.d("KP2AJ", "auth successful");
|
||||
try {
|
||||
|
||||
finishActivityWithSuccess(activity);
|
||||
return;
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.d("KP2AJ", "finish with error: " + e.toString());
|
||||
finishWithError(activity, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
Log.d("KP2AJ", "Starting auth");
|
||||
new AsyncTask<Object, Object, Object>() {
|
||||
|
||||
@Override
|
||||
protected Object doInBackground(Object... params) {
|
||||
try {
|
||||
return buildClient((Activity) activity);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Object o) {
|
||||
if (o == null)
|
||||
{
|
||||
Log.i(TAG, "authenticating not successful");
|
||||
Intent data = new Intent();
|
||||
data.putExtra(EXTRA_ERROR_MESSAGE, "authenticating not succesful");
|
||||
((Activity)activity).setResult(Activity.RESULT_CANCELED, data);
|
||||
((Activity)activity).finish();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.i(TAG, "authenticating successful");
|
||||
|
||||
oneDriveClient = (IOneDriveClient) o;
|
||||
finishActivityWithSuccess(activity);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(FileStorageSetupActivity activity, int requestCode, int resultCode, Intent data) {
|
||||
|
||||
}
|
||||
}
|
@@ -1,102 +0,0 @@
|
||||
package keepass2android.javafilestorage.onedrive;
|
||||
|
||||
/**
|
||||
* Created by Philipp on 22.11.2016.
|
||||
*/
|
||||
|
||||
import com.microsoft.services.msa.LiveConnectSession;
|
||||
import com.onedrive.sdk.authentication.AccountType;
|
||||
import com.onedrive.sdk.authentication.IAccountInfo;
|
||||
import com.onedrive.sdk.authentication.MSAAccountInfo;
|
||||
import com.onedrive.sdk.authentication.MSAAuthenticator;
|
||||
import com.onedrive.sdk.logger.ILogger;
|
||||
|
||||
import com.microsoft.services.msa.LiveConnectSession;
|
||||
import com.onedrive.sdk.logger.ILogger;
|
||||
|
||||
/**
|
||||
* Account information for a MSA based account.
|
||||
*/
|
||||
public class MyMSAAccountInfo implements IAccountInfo {
|
||||
|
||||
/**
|
||||
* The service root for the OneDrive personal API.
|
||||
*/
|
||||
public static final String ONE_DRIVE_PERSONAL_SERVICE_ROOT = "https://api.onedrive.com/v1.0";
|
||||
|
||||
/**
|
||||
* The authenticator that can refresh this account.
|
||||
*/
|
||||
private final MyMSAAuthenticator mAuthenticator;
|
||||
|
||||
/**
|
||||
* The session this account is based off of.
|
||||
*/
|
||||
private LiveConnectSession mSession;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private final ILogger mLogger;
|
||||
|
||||
/**
|
||||
* Creates an MSAAccountInfo object.
|
||||
* @param authenticator The authenticator that this account info was created from.
|
||||
* @param liveConnectSession The session this account is based off of.
|
||||
* @param logger The logger.
|
||||
*/
|
||||
public MyMSAAccountInfo(final MyMSAAuthenticator authenticator,
|
||||
final LiveConnectSession liveConnectSession,
|
||||
final ILogger logger) {
|
||||
mAuthenticator = authenticator;
|
||||
mSession = liveConnectSession;
|
||||
mLogger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the account.
|
||||
* @return The MicrosoftAccount account type.
|
||||
*/
|
||||
@Override
|
||||
public AccountType getAccountType() {
|
||||
return AccountType.MicrosoftAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the access token for requests against the service root.
|
||||
* @return The access token for requests against the service root.
|
||||
*/
|
||||
@Override
|
||||
public String getAccessToken() {
|
||||
return mSession.getAccessToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the OneDrive service root for this account.
|
||||
* @return the OneDrive service root for this account.
|
||||
*/
|
||||
@Override
|
||||
public String getServiceRoot() {
|
||||
return ONE_DRIVE_PERSONAL_SERVICE_ROOT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the account access token is expired and needs to be refreshed.
|
||||
* @return true if refresh() needs to be called and
|
||||
* false if the account is still valid.
|
||||
*/
|
||||
@Override
|
||||
public boolean isExpired() {
|
||||
return mSession.isExpired();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the authentication token for this account info.
|
||||
*/
|
||||
@Override
|
||||
public void refresh() {
|
||||
mLogger.logDebug("Refreshing access token...");
|
||||
final MyMSAAccountInfo newInfo = (MyMSAAccountInfo)mAuthenticator.loginSilent();
|
||||
mSession = newInfo.mSession;
|
||||
}
|
||||
}
|
@@ -1,446 +0,0 @@
|
||||
package keepass2android.javafilestorage.onedrive;
|
||||
|
||||
/**
|
||||
* Created by Philipp on 22.11.2016.
|
||||
*/
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
import com.microsoft.onedrivesdk.BuildConfig;
|
||||
import com.microsoft.services.msa.LiveAuthClient;
|
||||
import com.microsoft.services.msa.LiveAuthException;
|
||||
import com.microsoft.services.msa.LiveAuthListener;
|
||||
import com.microsoft.services.msa.LiveConnectSession;
|
||||
import com.microsoft.services.msa.LiveStatus;
|
||||
import com.onedrive.sdk.authentication.ClientAuthenticatorException;
|
||||
import com.onedrive.sdk.authentication.IAccountInfo;
|
||||
import com.onedrive.sdk.authentication.IAuthenticator;
|
||||
import com.onedrive.sdk.authentication.MSAAccountInfo;
|
||||
import com.onedrive.sdk.concurrency.ICallback;
|
||||
import com.onedrive.sdk.core.ClientException;
|
||||
import com.onedrive.sdk.concurrency.SimpleWaiter;
|
||||
import com.onedrive.sdk.concurrency.IExecutors;
|
||||
import com.onedrive.sdk.core.OneDriveErrorCodes;
|
||||
import com.onedrive.sdk.http.IHttpProvider;
|
||||
import com.onedrive.sdk.logger.ILogger;
|
||||
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Wrapper around the MSA authentication library.
|
||||
* https://github.com/MSOpenTech/msa-auth-for-android
|
||||
*/
|
||||
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
|
||||
public abstract class MyMSAAuthenticator implements IAuthenticator {
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
public MyMSAAuthenticator(Context context)
|
||||
{
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* The sign in cancellation message.
|
||||
*/
|
||||
private static final String SIGN_IN_CANCELLED_MESSAGE = "The user cancelled the login operation.";
|
||||
|
||||
/**
|
||||
* The preferences for this authenticator.
|
||||
*/
|
||||
private static final String MSA_AUTHENTICATOR_PREFS = "MSAAuthenticatorPrefs";
|
||||
|
||||
/**
|
||||
* The key for the user id.
|
||||
*/
|
||||
private static final String USER_ID_KEY = "userId";
|
||||
|
||||
/**
|
||||
* The key for the version code
|
||||
*/
|
||||
public static final String VERSION_CODE_KEY = "versionCode";
|
||||
|
||||
/**
|
||||
* The default user id
|
||||
*/
|
||||
private static final String DEFAULT_USER_ID = "@@defaultUser";
|
||||
|
||||
/**
|
||||
* The active user id.
|
||||
*/
|
||||
private final AtomicReference<String> mUserId = new AtomicReference<>();
|
||||
|
||||
/**
|
||||
* The executors.
|
||||
*/
|
||||
private IExecutors mExecutors;
|
||||
|
||||
/**
|
||||
* Indicates whether this authenticator has been initialized.
|
||||
*/
|
||||
private boolean mInitialized;
|
||||
|
||||
/**
|
||||
* The context UI interactions should happen with.
|
||||
*/
|
||||
private Activity mActivity;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private ILogger mLogger;
|
||||
|
||||
/**
|
||||
* The client id for this authenticator.
|
||||
* https://dev.onedrive.com/auth/msa_oauth.htm#to-register-your-app
|
||||
* @return The client id.
|
||||
*/
|
||||
public abstract String getClientId();
|
||||
|
||||
/**
|
||||
* The scopes for this application.
|
||||
* https://dev.onedrive.com/auth/msa_oauth.htm#authentication-scopes
|
||||
* @return The scopes for this application.
|
||||
*/
|
||||
public abstract String[] getScopes();
|
||||
|
||||
/**
|
||||
* The live authentication client.
|
||||
*/
|
||||
private LiveAuthClient mAuthClient;
|
||||
|
||||
/**
|
||||
* Initializes the authenticator.
|
||||
* @param executors The executors to schedule foreground and background tasks.
|
||||
* @param httpProvider The http provider for sending requests.
|
||||
* @param activity The activity to create interactive UI on.
|
||||
* @param logger The logger for diagnostic information.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void init(final IExecutors executors,
|
||||
final IHttpProvider httpProvider,
|
||||
final Activity activity,
|
||||
final ILogger logger) {
|
||||
mActivity = activity;
|
||||
|
||||
if (mInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
mExecutors = executors;
|
||||
mLogger = logger;
|
||||
mInitialized = true;
|
||||
mAuthClient = new LiveAuthClient(mContext, getClientId(), Arrays.asList(getScopes()));
|
||||
|
||||
final SharedPreferences prefs = getSharedPreferences();
|
||||
mUserId.set(prefs.getString(USER_ID_KEY, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an interactive login asynchronously.
|
||||
* @param emailAddressHint The hint for the email address during the interactive login.
|
||||
* @param loginCallback The callback to be called when the login is complete.
|
||||
*/
|
||||
@Override
|
||||
public void login(final String emailAddressHint, final ICallback<IAccountInfo> loginCallback) {
|
||||
Log.d("KP2AJ", "login()");
|
||||
if (!mInitialized) {
|
||||
throw new IllegalStateException("init must be called");
|
||||
}
|
||||
|
||||
if (loginCallback == null) {
|
||||
throw new InvalidParameterException("loginCallback");
|
||||
}
|
||||
|
||||
mLogger.logDebug("Starting login async");
|
||||
|
||||
mExecutors.performOnBackground(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
mExecutors.performOnForeground(login(emailAddressHint), loginCallback);
|
||||
} catch (final ClientException e) {
|
||||
mExecutors.performOnForeground(e, loginCallback);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an interactive login.
|
||||
* @param emailAddressHint The hint for the email address during the interactive login.
|
||||
* @return The account info.
|
||||
* @throws ClientException An exception occurs if the login was unable to complete for any reason.
|
||||
*/
|
||||
@Override
|
||||
public synchronized IAccountInfo login(final String emailAddressHint) throws ClientException {
|
||||
if (!mInitialized) {
|
||||
throw new IllegalStateException("init must be called");
|
||||
}
|
||||
|
||||
mLogger.logDebug("Starting login");
|
||||
|
||||
final AtomicReference<ClientException> error = new AtomicReference<>();
|
||||
final SimpleWaiter waiter = new SimpleWaiter();
|
||||
|
||||
final LiveAuthListener listener = new LiveAuthListener() {
|
||||
@Override
|
||||
public void onAuthComplete(final LiveStatus liveStatus,
|
||||
final LiveConnectSession liveConnectSession,
|
||||
final Object o) {
|
||||
if (liveStatus == LiveStatus.NOT_CONNECTED) {
|
||||
mLogger.logDebug("Received invalid login failure from silent authentication with MSA, ignoring.");
|
||||
} else {
|
||||
mLogger.logDebug("Successful interactive login");
|
||||
waiter.signal();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthError(final LiveAuthException e,
|
||||
final Object o) {
|
||||
OneDriveErrorCodes code = OneDriveErrorCodes.AuthenticationFailure;
|
||||
if (e.getError().equals(SIGN_IN_CANCELLED_MESSAGE)) {
|
||||
code = OneDriveErrorCodes.AuthenticationCancelled;
|
||||
}
|
||||
|
||||
error.set(new ClientAuthenticatorException("Unable to login with MSA", e, code));
|
||||
mLogger.logError(error.get().getMessage(), error.get());
|
||||
waiter.signal();
|
||||
}
|
||||
};
|
||||
|
||||
mActivity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mAuthClient.login(mActivity, /* scopes */null, /* user object */ null, emailAddressHint, listener);
|
||||
}
|
||||
});
|
||||
|
||||
mLogger.logDebug("Waiting for MSA callback");
|
||||
waiter.waitForSignal();
|
||||
|
||||
final ClientException exception = error.get();
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
final String userId;
|
||||
if (emailAddressHint != null) {
|
||||
userId = emailAddressHint;
|
||||
} else {
|
||||
userId = DEFAULT_USER_ID;
|
||||
}
|
||||
|
||||
mUserId.set(userId);
|
||||
|
||||
final SharedPreferences prefs = getSharedPreferences();
|
||||
prefs.edit()
|
||||
.putString(USER_ID_KEY, mUserId.get())
|
||||
.putInt(VERSION_CODE_KEY, BuildConfig.VERSION_CODE)
|
||||
.apply();
|
||||
|
||||
return getAccountInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a silent login asynchronously.
|
||||
* @param loginCallback The callback to be called when the login is complete.
|
||||
*/
|
||||
@Override
|
||||
public void loginSilent(final ICallback<IAccountInfo> loginCallback) {
|
||||
if (!mInitialized) {
|
||||
throw new IllegalStateException("init must be called");
|
||||
}
|
||||
|
||||
if (loginCallback == null) {
|
||||
throw new InvalidParameterException("loginCallback");
|
||||
}
|
||||
|
||||
mLogger.logDebug("Starting login silent async");
|
||||
|
||||
mExecutors.performOnBackground(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
mExecutors.performOnForeground(loginSilent(), loginCallback);
|
||||
} catch (final ClientException e) {
|
||||
mExecutors.performOnForeground(e, loginCallback);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a silent login.
|
||||
* @return The account info.
|
||||
* @throws ClientException An exception occurs if the login was unable to complete for any reason.
|
||||
*/
|
||||
@Override
|
||||
public synchronized IAccountInfo loginSilent() throws ClientException {
|
||||
if (!mInitialized) {
|
||||
throw new IllegalStateException("init must be called");
|
||||
}
|
||||
|
||||
mLogger.logDebug("Starting login silent");
|
||||
|
||||
final int userIdStoredMinVersion = 10112;
|
||||
if (getSharedPreferences().getInt(VERSION_CODE_KEY, 0) >= userIdStoredMinVersion
|
||||
&& mUserId.get() == null) {
|
||||
mLogger.logDebug("No login information found for silent authentication");
|
||||
return null;
|
||||
}
|
||||
|
||||
final SimpleWaiter loginSilentWaiter = new SimpleWaiter();
|
||||
final AtomicReference<ClientException> error = new AtomicReference<>();
|
||||
|
||||
final boolean waitForCallback = mAuthClient.loginSilent(new LiveAuthListener() {
|
||||
@Override
|
||||
public void onAuthComplete(final LiveStatus liveStatus,
|
||||
final LiveConnectSession liveConnectSession,
|
||||
final Object o) {
|
||||
if (liveStatus == LiveStatus.NOT_CONNECTED) {
|
||||
error.set(new ClientAuthenticatorException("Failed silent login, interactive login required",
|
||||
OneDriveErrorCodes.AuthenticationFailure));
|
||||
mLogger.logError(error.get().getMessage(), error.get());
|
||||
} else {
|
||||
mLogger.logDebug("Successful silent login");
|
||||
}
|
||||
loginSilentWaiter.signal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthError(final LiveAuthException e,
|
||||
final Object o) {
|
||||
OneDriveErrorCodes code = OneDriveErrorCodes.AuthenticationFailure;
|
||||
if (e.getError().equals(SIGN_IN_CANCELLED_MESSAGE)) {
|
||||
code = OneDriveErrorCodes.AuthenticationCancelled;
|
||||
}
|
||||
|
||||
error.set(new ClientAuthenticatorException("Login silent authentication error", e, code));
|
||||
mLogger.logError(error.get().getMessage(), error.get());
|
||||
loginSilentWaiter.signal();
|
||||
}
|
||||
});
|
||||
|
||||
if (!waitForCallback) {
|
||||
mLogger.logDebug("MSA silent auth fast-failed");
|
||||
return null;
|
||||
}
|
||||
|
||||
mLogger.logDebug("Waiting for MSA callback");
|
||||
loginSilentWaiter.waitForSignal();
|
||||
final ClientException exception = error.get();
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
return getAccountInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the current user out.
|
||||
* @param logoutCallback The callback to be called when the logout is complete.
|
||||
*/
|
||||
@Override
|
||||
public void logout(final ICallback<Void> logoutCallback) {
|
||||
if (!mInitialized) {
|
||||
throw new IllegalStateException("init must be called");
|
||||
}
|
||||
|
||||
if (logoutCallback == null) {
|
||||
throw new InvalidParameterException("logoutCallback");
|
||||
}
|
||||
|
||||
mLogger.logDebug("Starting logout async");
|
||||
|
||||
mExecutors.performOnBackground(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
logout();
|
||||
mExecutors.performOnForeground((Void) null, logoutCallback);
|
||||
} catch (final ClientException e) {
|
||||
mExecutors.performOnForeground(e, logoutCallback);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the current user out.
|
||||
* @throws ClientException An exception occurs if the logout was unable to complete for any reason.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void logout() throws ClientException {
|
||||
if (!mInitialized) {
|
||||
throw new IllegalStateException("init must be called");
|
||||
}
|
||||
|
||||
mLogger.logDebug("Starting logout");
|
||||
|
||||
final SimpleWaiter logoutWaiter = new SimpleWaiter();
|
||||
final AtomicReference<ClientException> error = new AtomicReference<>();
|
||||
mAuthClient.logout(new LiveAuthListener() {
|
||||
@Override
|
||||
public void onAuthComplete(final LiveStatus liveStatus,
|
||||
final LiveConnectSession liveConnectSession,
|
||||
final Object o) {
|
||||
mLogger.logDebug("Logout completed");
|
||||
logoutWaiter.signal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthError(final LiveAuthException e, final Object o) {
|
||||
error.set(new ClientAuthenticatorException("MSA Logout failed",
|
||||
e,
|
||||
OneDriveErrorCodes.AuthenticationFailure));
|
||||
mLogger.logError(error.get().getMessage(), error.get());
|
||||
logoutWaiter.signal();
|
||||
}
|
||||
});
|
||||
|
||||
mLogger.logDebug("Waiting for logout to complete");
|
||||
logoutWaiter.waitForSignal();
|
||||
|
||||
mLogger.logDebug("Clearing all MSA Authenticator shared preferences");
|
||||
final SharedPreferences prefs = getSharedPreferences();
|
||||
prefs.edit()
|
||||
.clear()
|
||||
.putInt(VERSION_CODE_KEY, BuildConfig.VERSION_CODE)
|
||||
.apply();
|
||||
mUserId.set(null);
|
||||
|
||||
final ClientException exception = error.get();
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current account info for this authenticator.
|
||||
* @return NULL if no account is available.
|
||||
*/
|
||||
@Override
|
||||
public IAccountInfo getAccountInfo() {
|
||||
final LiveConnectSession session = mAuthClient.getSession();
|
||||
if (session == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new MyMSAAccountInfo(this, session, mLogger);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the shared preferences for this authenticator.
|
||||
* @return The shared preferences.
|
||||
*/
|
||||
private SharedPreferences getSharedPreferences() {
|
||||
return mContext.getSharedPreferences(MSA_AUTHENTICATOR_PREFS, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
}
|
@@ -1 +1,2 @@
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
android.useAndroidX=true
|
||||
|
Reference in New Issue
Block a user