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,6 +15,8 @@ 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,8 +21,14 @@ 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,7 +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 | ||||
| @@ -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" | ||||
| @@ -81,4 +89,5 @@ | ||||
| 		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,7 +846,7 @@ namespace keepass2android | ||||
| 						    new OneDrive2AppFolderFileStorage(), | ||||
|                             new SftpFileStorage(LocaleManager.LocalizedAppContext, this, IsFtpDebugEnabled()), | ||||
| 							new NetFtpFileStorage(LocaleManager.LocalizedAppContext, this, IsFtpDebugEnabled), | ||||
| 							new WebDavFileStorage(this), | ||||
|                             new WebDavFileStorage(this, WebDavChunkedUploadSize), | ||||
|                             new PCloudFileStorage(LocaleManager.LocalizedAppContext, this), | ||||
|                             new PCloudFileStorageAll(LocaleManager.LocalizedAppContext, this), | ||||
|                             new MegaFileStorage(App.Context), | ||||
| @@ -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,7 +1470,6 @@ namespace keepass2android | ||||
| 		{ | ||||
| 			Kp2aLog.LogUnexpectedError(e.Exception); | ||||
| 		} | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user