Compare commits
4 Commits
v1.13-r1
...
feature/we
Author | SHA1 | Date | |
---|---|---|---|
![]() |
057a7e2f7a | ||
![]() |
cfb5098b38 | ||
![]() |
913222d7cb | ||
![]() |
3e6d86c206 |
@@ -140,6 +140,10 @@ namespace keepass2android
|
||||
|
||||
|
||||
#endif
|
||||
int WebDavChunkedUploadSize
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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<string> 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
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
package keepass2android.javafilestorage;
|
||||
|
||||
import android.content.Context;
|
||||
import java.math.BigInteger;
|
||||
import android.content.Intent;
|
||||
|
||||
import android.net.Uri;
|
||||
@@ -15,7 +16,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;
|
||||
@@ -24,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;
|
||||
@@ -44,23 +49,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);
|
||||
@@ -181,21 +196,119 @@ 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);
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
Response response = getClient(ci).newCall(request).execute();
|
||||
checkStatus(response);
|
||||
@@ -290,7 +403,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)
|
||||
@@ -519,3 +635,4 @@ public class WebDavStorage extends JavaFileStorageBase {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -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 <d:resourcetype> 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 <d:collection/>, so it's a folder
|
||||
isCollection = true;
|
||||
// Since <d:collection/> 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 <d:resourcetype>
|
||||
skip(parser);
|
||||
}
|
||||
}
|
||||
// After reading all children of <d:resourcetype>, 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());
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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<EditText>(Resource.Id.http_url).Text = connInfo.Url;
|
||||
dlgContents.FindViewById<EditText>(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);
|
||||
});
|
||||
@@ -352,8 +354,13 @@ namespace keepass2android
|
||||
dialog.Show();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void ShowFtpDialog(Activity activity, Util.FileSelectedHandler onStartBrowse, Action onCancel, string defaultPath)
|
||||
#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
|
||||
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);
|
||||
});
|
||||
|
@@ -209,6 +209,7 @@
|
||||
|
||||
<string name="ShowUnlockedNotification_key">ShowUnlockedNotification</string>
|
||||
<bool name="ShowUnlockedNotification_default">true</bool>
|
||||
<integer name="WebDavChunkedUploadSize_default">65536</integer>
|
||||
|
||||
<string name="PreloadDatabaseEnabled_key">PreloadDatabaseEnabled</string>
|
||||
<bool name="PreloadDatabaseEnabled_default">true</bool>
|
||||
|
@@ -729,6 +729,9 @@
|
||||
<string name="EntryChannel_desc">Notification to simplify access to the currently selected entry.</string>
|
||||
<string name="CloseDbAfterFailedAttempts">Close database after three failed biometric unlock attempts.</string>
|
||||
<string name="WarnFingerprintInvalidated">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!</string>
|
||||
<string name="webdav_chunked_upload_size_title">Chunk size for WebDav upload</string>
|
||||
<string name="webdav_chunked_upload_size_summary">Size of chunks when uploading to WebDav servers in bytes. Use 0 to disable chunked upload.</string>
|
||||
|
||||
|
||||
<string-array name="ChangeLog_1_13">
|
||||
<item>Improved password quality estimation by considering most popular passwords.</item>
|
||||
|
@@ -45,6 +45,14 @@
|
||||
android:title="@string/UseFileTransactions_title"
|
||||
android:key="@string/UseFileTransactions_key" />
|
||||
|
||||
<EditTextPreference
|
||||
android:key="WebDavChunkedUploadSize_str"
|
||||
android:title="@string/webdav_chunked_upload_size_title"
|
||||
android:summary="@string/webdav_chunked_upload_size_title"
|
||||
android:defaultValue="@integer/WebDavChunkedUploadSize_default"
|
||||
android:inputType="number"
|
||||
/>
|
||||
|
||||
<CheckBoxPreference
|
||||
android:enabled="true"
|
||||
android:persistent="true"
|
||||
@@ -80,5 +88,6 @@
|
||||
android:defaultValue="true"
|
||||
android:title="@string/CheckForDuplicateUuids_title"
|
||||
android:key="@string/CheckForDuplicateUuids_key" />
|
||||
|
||||
|
||||
</PreferenceScreen>
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user