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