From 3e6d86c206e52bbae6b83d50d06fddc57ba6be46 Mon Sep 17 00:00:00 2001 From: Philipp Crocoll Date: Tue, 15 Jul 2025 09:10:41 +0200 Subject: [PATCH 1/4] correctly check if an item is a folder or file. closes https://github.com/PhilippC/keepass2android/issues/2589 --- .../javafilestorage/WebDavStorage.java | 5 ++- .../webdav/PropfindXmlParser.java | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/WebDavStorage.java b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/WebDavStorage.java index 26710fdf..fd3b6386 100644 --- a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/WebDavStorage.java +++ b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/WebDavStorage.java @@ -290,7 +290,10 @@ public class WebDavStorage extends JavaFileStorageBase { e.sizeInBytes = -1; } } - e.isDirectory = r.href.endsWith("/"); + + e.isDirectory = r.href.endsWith("/") || okprop.IsCollection; + + e.displayName = okprop.DisplayName; if (e.displayName == null) diff --git a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/webdav/PropfindXmlParser.java b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/webdav/PropfindXmlParser.java index 59ed2034..f424fb27 100644 --- a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/webdav/PropfindXmlParser.java +++ b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/webdav/PropfindXmlParser.java @@ -57,6 +57,8 @@ public class PropfindXmlParser public String DisplayName; public String LastModified; public String ContentLength; + + public boolean IsCollection; } public String status; public Prop prop; @@ -191,6 +193,8 @@ public class PropfindXmlParser continue; } String name = parser.getName(); + String namespace = parser.getNamespace(); + android.util.Log.d("PARSE", "4name = " + name); if (name.equals("getcontentlength")) @@ -200,6 +204,9 @@ public class PropfindXmlParser prop.LastModified = readText(parser); } else if (name.equals("displayname")) { prop.DisplayName = readText(parser); + } else if (name.equals("resourcetype") && namespace.equals(ns)) { + // We found the tag + prop.IsCollection = readResourceType(parser); } else { skip(parser); } @@ -208,6 +215,37 @@ public class PropfindXmlParser return prop; } + private boolean readResourceType(XmlPullParser parser) throws IOException, XmlPullParserException { + boolean isCollection = false; + parser.require(XmlPullParser.START_TAG, ns, "resourcetype"); + + while (parser.next() != XmlPullParser.END_TAG) { + + if (parser.getEventType() != XmlPullParser.START_TAG) { + continue; + } + String name = parser.getName(); + String namespace = parser.getNamespace(); + + if (name.equals("collection") && namespace.equals(ns)) { + // We found , so it's a folder + isCollection = true; + // Since is usually an empty tag, just consume it. + // It might contain text if there's whitespace, so consume text then end tag. + if (parser.next() == XmlPullParser.TEXT) { + parser.nextTag(); // Move to the end tag + } + parser.require(XmlPullParser.END_TAG, ns, "collection"); + } else { + // Skip any other unexpected tags within + skip(parser); + } + } + // After reading all children of , ensure we are at its END_TAG + parser.require(XmlPullParser.END_TAG, ns, "resourcetype"); + return isCollection; + } + private void skip(XmlPullParser parser) throws XmlPullParserException, IOException { android.util.Log.d("PARSE", "skipping " + parser.getName()); From 913222d7cb799274f3ddf9ef569f92aa3c01787b Mon Sep 17 00:00:00 2001 From: Philipp Crocoll Date: Tue, 15 Jul 2025 11:07:40 +0200 Subject: [PATCH 2/4] allow chunked uploads, closes https://github.com/PhilippC/keepass2android/issues/2777 --- src/Kp2aBusinessLogic/IKp2aApp.cs | 4 ++ .../Io/DropboxFileStorage.cs | 5 +- src/Kp2aBusinessLogic/Io/JavaFileStorage.cs | 2 +- src/Kp2aBusinessLogic/Io/WebDavFileStorage.cs | 25 +++++++-- .../javafilestorage/WebDavStorage.java | 56 ++++++++++++++++++- src/keepass2android-app/FileSelectHelper.cs | 15 +++-- .../Resources/values/config.xml | 1 + .../Resources/values/strings.xml | 3 + .../Resources/xml/pref_app_file_handling.xml | 9 +++ src/keepass2android-app/app/App.cs | 23 ++++++-- 10 files changed, 125 insertions(+), 18 deletions(-) diff --git a/src/Kp2aBusinessLogic/IKp2aApp.cs b/src/Kp2aBusinessLogic/IKp2aApp.cs index 9a8357f8..6e4e9c1f 100644 --- a/src/Kp2aBusinessLogic/IKp2aApp.cs +++ b/src/Kp2aBusinessLogic/IKp2aApp.cs @@ -140,6 +140,10 @@ namespace keepass2android #endif + int WebDavChunkedUploadSize + { + get; + } } } \ No newline at end of file diff --git a/src/Kp2aBusinessLogic/Io/DropboxFileStorage.cs b/src/Kp2aBusinessLogic/Io/DropboxFileStorage.cs index 4ad64472..0f354a5c 100644 --- a/src/Kp2aBusinessLogic/Io/DropboxFileStorage.cs +++ b/src/Kp2aBusinessLogic/Io/DropboxFileStorage.cs @@ -15,7 +15,9 @@ namespace keepass2android.Io { get { return false; } } - } + + static public bool IsConfigured => !string.IsNullOrEmpty(AppKey) && !string.IsNullOrEmpty(AppSecret); + } public partial class DropboxAppFolderFileStorage: JavaFileStorage { @@ -29,6 +31,7 @@ namespace keepass2android.Io get { return false; } } + static public bool IsConfigured => !string.IsNullOrEmpty(AppKey) && !string.IsNullOrEmpty(AppSecret); } } diff --git a/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs b/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs index e526928e..2c39e594 100644 --- a/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs +++ b/src/Kp2aBusinessLogic/Io/JavaFileStorage.cs @@ -123,7 +123,7 @@ namespace keepass2android.Io } - public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction) + public virtual IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction) { return new JavaFileStorageWriteTransaction(IocToPath(ioc), useFileTransaction, this); } diff --git a/src/Kp2aBusinessLogic/Io/WebDavFileStorage.cs b/src/Kp2aBusinessLogic/Io/WebDavFileStorage.cs index 6cce6119..2d80e18a 100644 --- a/src/Kp2aBusinessLogic/Io/WebDavFileStorage.cs +++ b/src/Kp2aBusinessLogic/Io/WebDavFileStorage.cs @@ -6,10 +6,12 @@ using System.Text; using Android.App; using Android.Content; using Android.OS; +using Android.Preferences; using Android.Runtime; using Android.Views; using Android.Widget; #if !NoNet && !EXCLUDE_JAVAFILESTORAGE + using Keepass2android.Javafilestorage; #endif using KeePassLib.Serialization; @@ -19,9 +21,15 @@ namespace keepass2android.Io #if !NoNet && !EXCLUDE_JAVAFILESTORAGE public class WebDavFileStorage: JavaFileStorage { - public WebDavFileStorage(IKp2aApp app) : base(new Keepass2android.Javafilestorage.WebDavStorage(app.CertificateErrorHandler), app) - { - } + private readonly IKp2aApp _app; + private readonly WebDavStorage baseWebdavStorage; + + public WebDavFileStorage(IKp2aApp app, int chunkSize) : base(new Keepass2android.Javafilestorage.WebDavStorage(app.CertificateErrorHandler, chunkSize), app) + { + _app = app; + baseWebdavStorage = (WebDavStorage)Jfs; + + } public override IEnumerable SupportedProtocols { @@ -75,6 +83,15 @@ namespace keepass2android.Io } return base.IocToPath(ioc); } - } + + + public override IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction) + { + baseWebdavStorage.SetUploadChunkSize(_app.WebDavChunkedUploadSize); + return base.OpenWriteTransaction(ioc, useFileTransaction); + } + } + + #endif } \ No newline at end of file diff --git a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/WebDavStorage.java b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/WebDavStorage.java index fd3b6386..37960f2d 100644 --- a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/WebDavStorage.java +++ b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/WebDavStorage.java @@ -15,7 +15,10 @@ import com.burgstaller.okhttp.basic.BasicAuthenticator; import com.burgstaller.okhttp.digest.CachingAuthenticator; import com.burgstaller.okhttp.digest.DigestAuthenticator; + +import java.io.ByteArrayInputStream; import java.io.FileNotFoundException; +import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.io.UnsupportedEncodingException; @@ -44,23 +47,33 @@ import keepass2android.javafilestorage.webdav.DecoratedTrustManager; import keepass2android.javafilestorage.webdav.PropfindXmlParser; import keepass2android.javafilestorage.webdav.WebDavUtil; import okhttp3.MediaType; +import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import okhttp3.internal.tls.OkHostnameVerifier; +import okio.BufferedSink; public class WebDavStorage extends JavaFileStorageBase { private final ICertificateErrorHandler mCertificateErrorHandler; private Context appContext; - public WebDavStorage(ICertificateErrorHandler certificateErrorHandler) + int chunkSize; + + public WebDavStorage(ICertificateErrorHandler certificateErrorHandler, int chunkSize) { + this.chunkSize = chunkSize; mCertificateErrorHandler = certificateErrorHandler; } + public void setUploadChunkSize(int chunkSize) + { + this.chunkSize = chunkSize; + } + public String buildFullPath(String url, String username, String password) throws UnsupportedEncodingException { String scheme = url.substring(0, url.indexOf("://")); url = url.substring(scheme.length() + 3); @@ -189,11 +202,49 @@ public class WebDavStorage extends JavaFileStorageBase { try { ConnectionInfo ci = splitStringToConnectionInfo(path); + + RequestBody requestBody; + if (chunkSize > 0) + { + // use chunked upload + requestBody = new RequestBody() { + @Override + public MediaType contentType() { + return MediaType.parse("application/binary"); + } + + @Override + public void writeTo(BufferedSink sink) throws IOException { + try (InputStream in = new ByteArrayInputStream(data)) { + byte[] buffer = new byte[chunkSize]; + int read; + while ((read = in.read(buffer)) != -1) { + sink.write(buffer, 0, read); + sink.flush(); + } + } + } + + @Override + public long contentLength() { + return -1; // use chunked upload + } + }; + } + else + { + requestBody = new MultipartBody.Builder() + .addPart(RequestBody.create(data, MediaType.parse("application/binary"))) + .build(); + } + + Request request = new Request.Builder() .url(new URL(ci.URL)) - .put(RequestBody.create(MediaType.parse("application/binary"), data)) + .put(requestBody) .build(); + //TODO consider writeTransactional //TODO check for error @@ -522,3 +573,4 @@ public class WebDavStorage extends JavaFileStorageBase { } } + diff --git a/src/keepass2android-app/FileSelectHelper.cs b/src/keepass2android-app/FileSelectHelper.cs index 911b5300..3b480b7a 100644 --- a/src/keepass2android-app/FileSelectHelper.cs +++ b/src/keepass2android-app/FileSelectHelper.cs @@ -9,7 +9,9 @@ using System.Text; using Android.App; using Android.Content; +using Android.Content.Res; using Android.OS; +using Android.Preferences; using Android.Runtime; using Android.Views; using Android.Widget; @@ -319,7 +321,7 @@ namespace keepass2android View dlgContents = activity.LayoutInflater.Inflate(Resource.Layout.httpcredentials, null); if (!defaultPath.EndsWith(_schemeSeparator)) { - var webdavStorage = new Keepass2android.Javafilestorage.WebDavStorage(App.Kp2a.CertificateErrorHandler); + var webdavStorage = CreateWebdavStorage(activity); var connInfo = webdavStorage.SplitStringToConnectionInfo(defaultPath); dlgContents.FindViewById(Resource.Id.http_url).Text = connInfo.Url; dlgContents.FindViewById(Resource.Id.http_user).Text = connInfo.Username; @@ -339,7 +341,7 @@ namespace keepass2android string scheme = defaultPath.Substring(0, defaultPath.IndexOf(_schemeSeparator, StringComparison.Ordinal)); if (host.Contains(_schemeSeparator) == false) host = scheme + _schemeSeparator + host; - string httpPath = new Keepass2android.Javafilestorage.WebDavStorage(null).BuildFullPath(host, user, + string httpPath = CreateWebdavStorage(activity).BuildFullPath(host, user, password); onStartBrowse(httpPath); }); @@ -353,7 +355,12 @@ namespace keepass2android #endif } - private void ShowFtpDialog(Activity activity, Util.FileSelectedHandler onStartBrowse, Action onCancel, string defaultPath) + private static WebDavStorage CreateWebdavStorage(Activity activity) + { + return new WebDavStorage(App.Kp2a.CertificateErrorHandler, App.Kp2a.WebDavChunkedUploadSize); + } + + private void ShowFtpDialog(Activity activity, Util.FileSelectedHandler onStartBrowse, Action onCancel, string defaultPath) { #if !NoNet MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(activity); @@ -518,7 +525,7 @@ namespace keepass2android string scheme = defaultPath.Substring(0,defaultPath.IndexOf(_schemeSeparator, StringComparison.Ordinal)); if (host.Contains(_schemeSeparator) == false) host = scheme + _schemeSeparator + host; - string httpPath = new Keepass2android.Javafilestorage.WebDavStorage(null).BuildFullPath(WebDavFileStorage.Owncloud2Webdav(host, subtype == "owncloud" ? WebDavFileStorage.owncloudPrefix : WebDavFileStorage.nextcloudPrefix), user, + string httpPath = CreateWebdavStorage(activity).BuildFullPath(WebDavFileStorage.Owncloud2Webdav(host, subtype == "owncloud" ? WebDavFileStorage.owncloudPrefix : WebDavFileStorage.nextcloudPrefix), user, password); onStartBrowse(httpPath); }); diff --git a/src/keepass2android-app/Resources/values/config.xml b/src/keepass2android-app/Resources/values/config.xml index e5c3a97c..db3582ec 100644 --- a/src/keepass2android-app/Resources/values/config.xml +++ b/src/keepass2android-app/Resources/values/config.xml @@ -209,6 +209,7 @@ ShowUnlockedNotification true + 65536 PreloadDatabaseEnabled true diff --git a/src/keepass2android-app/Resources/values/strings.xml b/src/keepass2android-app/Resources/values/strings.xml index 6c4f3c87..70a93d18 100644 --- a/src/keepass2android-app/Resources/values/strings.xml +++ b/src/keepass2android-app/Resources/values/strings.xml @@ -729,6 +729,9 @@ Notification to simplify access to the currently selected entry. Close database after three failed biometric unlock attempts. Warning! Biometric authentication can be invalidated by Android, e.g. after adding a new fingerprint in your device settings. Make sure you always know how to unlock with your master password! + Chunk size for WebDav upload + Size of chunks when uploading to WebDav servers in bytes. Use 0 to disable chunked upload. + Improved password quality estimation by considering most popular passwords. diff --git a/src/keepass2android-app/Resources/xml/pref_app_file_handling.xml b/src/keepass2android-app/Resources/xml/pref_app_file_handling.xml index 98b85e90..196ab621 100644 --- a/src/keepass2android-app/Resources/xml/pref_app_file_handling.xml +++ b/src/keepass2android-app/Resources/xml/pref_app_file_handling.xml @@ -45,6 +45,14 @@ android:title="@string/UseFileTransactions_title" android:key="@string/UseFileTransactions_key" /> + + + \ No newline at end of file diff --git a/src/keepass2android-app/app/App.cs b/src/keepass2android-app/app/App.cs index db78a794..77c4df72 100644 --- a/src/keepass2android-app/app/App.cs +++ b/src/keepass2android-app/app/App.cs @@ -836,8 +836,8 @@ namespace keepass2android new AndroidContentStorage(LocaleManager.LocalizedAppContext), #if !EXCLUDE_JAVAFILESTORAGE #if !NoNet - new DropboxFileStorage(LocaleManager.LocalizedAppContext, this), - new DropboxAppFolderFileStorage(LocaleManager.LocalizedAppContext, this), + DropboxFileStorage.IsConfigured ? new DropboxFileStorage(LocaleManager.LocalizedAppContext, this) : null, + DropboxAppFolderFileStorage.IsConfigured ? new DropboxAppFolderFileStorage(LocaleManager.LocalizedAppContext, this): null, GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(LocaleManager.LocalizedAppContext)==ConnectionResult.Success ? new GoogleDriveFileStorage(LocaleManager.LocalizedAppContext, this) : null, GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(LocaleManager.LocalizedAppContext)==ConnectionResult.Success ? new GoogleDriveAppDataFileStorage(LocaleManager.LocalizedAppContext, this) : null, new OneDriveFileStorage(this), @@ -846,8 +846,8 @@ namespace keepass2android new OneDrive2AppFolderFileStorage(), new SftpFileStorage(LocaleManager.LocalizedAppContext, this, IsFtpDebugEnabled()), new NetFtpFileStorage(LocaleManager.LocalizedAppContext, this, IsFtpDebugEnabled), - new WebDavFileStorage(this), - new PCloudFileStorage(LocaleManager.LocalizedAppContext, this), + new WebDavFileStorage(this, WebDavChunkedUploadSize), + new PCloudFileStorage(LocaleManager.LocalizedAppContext, this), new PCloudFileStorageAll(LocaleManager.LocalizedAppContext, this), new MegaFileStorage(App.Context), //new LegacyWebDavStorage(this), @@ -1333,6 +1333,18 @@ namespace keepass2android } } + + + public int WebDavChunkedUploadSize + { + get + { + return int.Parse(PreferenceManager.GetDefaultSharedPreferences(LocaleManager.LocalizedAppContext) + .GetString("WebDavChunkedUploadSize_str", + LocaleManager.LocalizedAppContext.Resources + .GetInteger(Resource.Integer.WebDavChunkedUploadSize_default).ToString())); + } + } } @@ -1458,8 +1470,7 @@ namespace keepass2android { Kp2aLog.LogUnexpectedError(e.Exception); } - - } + } } From cfb5098b38bda05c1110a91684d048ead8b9ba0a Mon Sep 17 00:00:00 2001 From: Philipp Crocoll Date: Tue, 15 Jul 2025 12:18:45 +0200 Subject: [PATCH 3/4] add support for transactional upload --- .../javafilestorage/WebDavStorage.java | 66 ++++++++++++++++++- .../javafilestoragetest2/MainActivity.java | 8 +-- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/WebDavStorage.java b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/WebDavStorage.java index 37960f2d..fb8ec597 100644 --- a/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/WebDavStorage.java +++ b/src/java/JavaFileStorage/app/src/main/java/keepass2android/javafilestorage/WebDavStorage.java @@ -1,6 +1,7 @@ package keepass2android.javafilestorage; import android.content.Context; +import java.math.BigInteger; import android.content.Intent; import android.net.Uri; @@ -27,6 +28,7 @@ import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; @@ -194,11 +196,73 @@ public class WebDavStorage extends JavaFileStorageBase { return client; } + public void renameOrMoveWebDavResource(String sourcePath, String destinationPath, boolean overwrite) throws Exception { + + ConnectionInfo sourceCi = splitStringToConnectionInfo(sourcePath); + ConnectionInfo destinationCi = splitStringToConnectionInfo(destinationPath); + + Request.Builder requestBuilder = new Request.Builder() + .url(new URL(sourceCi.URL)) + .method("MOVE", null) // "MOVE" is the HTTP method + .header("Destination", destinationCi.URL); // New URI for the resource + + // Add Overwrite header + if (overwrite) { + requestBuilder.header("Overwrite", "T"); // 'T' for true + } else { + requestBuilder.header("Overwrite", "F"); // 'F' for false + } + + Request request = requestBuilder.build(); + + Response response = getClient(sourceCi).newCall(request).execute(); + + // Check the status code + if (response.isSuccessful()) { + // WebDAV MOVE can return 201 (Created) if a new resource was created at dest, + // or 204 (No Content) if moved to a pre-existing destination (e.g., just renamed). + // A 200 OK might also be returned by some servers, though 201/204 are more common. + + } + else + { + throw new Exception("Rename/Move failed for " + sourceCi.URL + " to " + destinationCi.URL + ": " + response.code() + " " + response.message()); + } + } + + public static String generateRandomHexString(int length) { + SecureRandom secureRandom = new SecureRandom(); + // Generate enough bytes to ensure we can get the desired number of hex characters. + // Each byte converts to two hex characters. + // For 8 hex characters, we need 4 bytes. + int numBytes = (int) Math.ceil(length / 2.0); + byte[] randomBytes = new byte[numBytes]; + secureRandom.nextBytes(randomBytes); + + // Convert the byte array to a hexadecimal string + // BigInteger(1, randomBytes) treats the byte array as a positive number. + // toString(16) converts it to a hexadecimal string. + String hexString = new BigInteger(1, randomBytes).toString(16); + + // Pad with leading zeros if necessary (e.g., if the generated number is small) + // and then take the first 'length' characters. + // Using String.format to ensure leading zeros if the hexString is shorter. + return String.format("%0" + length + "d", new BigInteger(hexString, 16)).substring(0, length); + } @Override public void uploadFile(String path, byte[] data, boolean writeTransactional) throws Exception { + if (writeTransactional) + { + String randomSuffix = ".tmp." + generateRandomHexString(8); + uploadFile(path + randomSuffix, data, false); + renameOrMoveWebDavResource(path+randomSuffix, path, true); + return; + } + + try { ConnectionInfo ci = splitStringToConnectionInfo(path); @@ -245,8 +309,6 @@ public class WebDavStorage extends JavaFileStorageBase { .build(); - //TODO consider writeTransactional - //TODO check for error Response response = getClient(ci).newCall(request).execute(); checkStatus(response); diff --git a/src/java/JavaFileStorageTest-AS/app/src/main/java/com/crocoapps/javafilestoragetest2/MainActivity.java b/src/java/JavaFileStorageTest-AS/app/src/main/java/com/crocoapps/javafilestoragetest2/MainActivity.java index 1c81a604..5e8fcc35 100644 --- a/src/java/JavaFileStorageTest-AS/app/src/main/java/com/crocoapps/javafilestoragetest2/MainActivity.java +++ b/src/java/JavaFileStorageTest-AS/app/src/main/java/com/crocoapps/javafilestoragetest2/MainActivity.java @@ -548,7 +548,7 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag //storageToTest = new GoogleDriveAppDataFileStorage(); - /*storageToTest = new WebDavStorage(new ICertificateErrorHandler() { + storageToTest = new WebDavStorage(new ICertificateErrorHandler() { @Override public boolean onValidationError(String error) { return false; @@ -558,12 +558,12 @@ public class MainActivity extends Activity implements JavaFileStorage.FileStorag public boolean alwaysFailOnValidationError() { return false; } - }); -*/ + }, 64*1024); + //storageToTest = new DropboxV2Storage(ctx,"4ybka4p4a1027n6", "1z5lv528un9nre8", !simulateRestart); //storageToTest = new DropboxFileStorage(ctx,"4ybka4p4a1027n6", "1z5lv528un9nre8", !simulateRestart); //storageToTest = new DropboxAppFolderFileStorage(ctx,"ax0268uydp1ya57", "3s86datjhkihwyc", true); - storageToTest = new GoogleDriveFullFileStorage(); + // storageToTest = new GoogleDriveFullFileStorage(); return storageToTest; From 057a7e2f7afd4dfeae0108860683c12dd1839978 Mon Sep 17 00:00:00 2001 From: Philipp Crocoll Date: Tue, 15 Jul 2025 13:12:18 +0200 Subject: [PATCH 4/4] another nonet fix --- src/keepass2android-app/FileSelectHelper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/keepass2android-app/FileSelectHelper.cs b/src/keepass2android-app/FileSelectHelper.cs index 3b480b7a..176f780c 100644 --- a/src/keepass2android-app/FileSelectHelper.cs +++ b/src/keepass2android-app/FileSelectHelper.cs @@ -354,12 +354,12 @@ namespace keepass2android dialog.Show(); #endif } - +#if !NoNet private static WebDavStorage CreateWebdavStorage(Activity activity) { return new WebDavStorage(App.Kp2a.CertificateErrorHandler, App.Kp2a.WebDavChunkedUploadSize); } - +#endif private void ShowFtpDialog(Activity activity, Util.FileSelectedHandler onStartBrowse, Action onCancel, string defaultPath) { #if !NoNet