allow chunked uploads, closes https://github.com/PhilippC/keepass2android/issues/2777
This commit is contained in:
@@ -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
|
||||
}
|
@@ -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 {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
});
|
||||
@@ -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);
|
||||
});
|
||||
|
@@ -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