IO_MAP = new ConcurrentHashMap<>();
+
+ private HttpIO(Account account) {
+ if (account == null) {
+ throw new IllegalArgumentException("IO constructor(): account is null.");
+ }
+
+ if (TextUtils.isEmpty(account.server)) {
+ throw new IllegalArgumentException("IO constructor(): account.server is null.");
+ }
+
+ if (TextUtils.isEmpty(account.email)) {
+ throw new IllegalArgumentException("IO constructor(): account.email is null.");
+ }
+
+ this.account = account;
+ }
+
+ /**
+ * Logged in
+ */
+ public static HttpIO getCurrentInstance() {
+ if (INSTANCE != null) {
+ return INSTANCE;
+ }
+
+ // singleton and map
+ synchronized (HttpIO.class) {
+ if (INSTANCE == null) {
+
+ Account curAccount = SupportAccountManager.getInstance().getCurrentAccount();
+ if (curAccount == null) {
+ throw new IllegalStateException("IO instance(): No current account");
+ }
+
+ //
+ INSTANCE = new HttpIO(curAccount);
+
+ //
+ TokenManager.getInstance().setToken(curAccount.token);
+ }
+ }
+
+ return INSTANCE;
+ }
+
+ /**
+ * Not logged in/Log in to another server
+ */
+ public static HttpIO getInstanceByAccount(Account account) {
+ if (account == null) {
+ return null;
+ }
+
+ if (IO_MAP.containsKey(account.getSignature())) {
+ HttpIO httpIo = IO_MAP.get(account.getSignature());
+ if (httpIo == null) {
+ return getAndRemoveIO(account);
+ }
+
+ if (!Objects.equals(httpIo.account, account)) {
+ return getAndRemoveIO(account);
+ }
+
+ return httpIo;
+ }
+
+ return getAndRemoveIO(account);
+ }
+
+ private static HttpIO getAndRemoveIO(Account account) {
+ Account newAccount = CloneUtils.deepClone(account, Account.class);
+ HttpIO httpIo = new HttpIO(newAccount);
+
+ IO_MAP.remove(newAccount.getSignature());
+ IO_MAP.put(newAccount.getSignature(), httpIo);
+
+ return httpIo;
+ }
+
+ public Account getAccount() {
+ return account;
+ }
+
+ /**
+ * get server url
+ */
+ public String getServerUrl() {
+ return account.getServer();
+ }
+
+ /**
+ * get client
+ */
+ public BaseOkHttpClient getOkHttpClient() {
+ if (okHttpClient == null) {
+ okHttpClient = new SafeOkHttpClient(account);
+ }
+ return okHttpClient;
+ }
+
+
+ /**
+ * When log in again or switch account, you should reset this IO Singleton.
+ * because it's a SINGLETON, unless kill the APP!
+ */
+ public static void resetLoggedInInstance() {
+ INSTANCE = null;
+ IO_MAP.clear();
+ }
+
+
+ public T execute(Class clazz) {
+ Retrofit retrofit = createRetrofit();
+ return retrofit.create(clazz);
+ }
+
+ private Retrofit createRetrofit() {
+ Retrofit.Builder rBuilder = new Retrofit.Builder();
+ rBuilder.baseUrl(getServerUrl());
+ rBuilder.addConverterFactory(ConverterFactory.create());
+ rBuilder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
+
+ rBuilder.client(getOkHttpClient().getOkClient());
+
+ return rBuilder.build();
+ }
+
+
+ public void downloadBinarySync(String url, File destinationFile, ProgressListener callback) throws IOException {
+ OkHttpClient client = getOkHttpClient().getOkClient();
+
+ try (OutputStream outputStream = Files.newOutputStream(destinationFile.toPath())) {
+ BinaryFileWriter fileWriter = new BinaryFileWriter(outputStream, new ProgressCallback() {
+ @Override
+ public void onProgress(long transferSize, long totalSize) {
+ if (callback != null) {
+ callback.onProgress(destinationFile.getName(), transferSize, totalSize);
+ }
+ }
+ });
+
+ try (BinaryFileDownloader fileDownloader = new BinaryFileDownloader(client, fileWriter)) {
+ fileDownloader.download(url);
+
+ } catch (Exception e) {
+ if (callback != null) {
+ callback.isCancelled();
+ }
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public Flowable downloadBinary(String url, File destinationFile) {
+
+ return Flowable.create(new FlowableOnSubscribe() {
+ @Override
+ public void subscribe(FlowableEmitter emitter) throws Exception {
+ OkHttpClient client = getOkHttpClient().getOkClient();
+
+ try (OutputStream outputStream = Files.newOutputStream(destinationFile.toPath())) {
+ BinaryFileWriter fileWriter = new BinaryFileWriter(outputStream, new ProgressCallback() {
+ @Override
+ public void onProgress(long transferSize, long totalSize) {
+ emitter.onNext(new Long[]{transferSize, totalSize});
+ }
+ });
+
+ try (BinaryFileDownloader fileDownloader = new BinaryFileDownloader(client, fileWriter)) {
+ fileDownloader.download(url);
+
+ emitter.onComplete();
+ } catch (Exception e) {
+ emitter.onError(e);
+ }
+ }
+ }
+ }, BackpressureStrategy.BUFFER);
+ }
+}
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/http/IO.java b/app/src/main/java/com/seafile/seadroid2/framework/http/IO.java
deleted file mode 100644
index 6c8bd0181..000000000
--- a/app/src/main/java/com/seafile/seadroid2/framework/http/IO.java
+++ /dev/null
@@ -1,264 +0,0 @@
-package com.seafile.seadroid2.framework.http;
-
-import com.seafile.seadroid2.BuildConfig;
-import com.seafile.seadroid2.account.Account;
-import com.seafile.seadroid2.account.SupportAccountManager;
-import com.seafile.seadroid2.config.Constants;
-import com.seafile.seadroid2.framework.http.callback.ProgressCallback;
-import com.seafile.seadroid2.framework.http.download.BinaryFileDownloader;
-import com.seafile.seadroid2.framework.http.download.BinaryFileWriter;
-import com.seafile.seadroid2.framework.util.SLogs;
-import com.seafile.seadroid2.framework.http.converter.ConverterFactory;
-import com.seafile.seadroid2.framework.http.interceptor.HeaderInterceptor;
-import com.seafile.seadroid2.listener.ProgressListener;
-
-import org.apache.commons.lang3.StringUtils;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import io.reactivex.BackpressureStrategy;
-import io.reactivex.Flowable;
-import io.reactivex.FlowableEmitter;
-import io.reactivex.FlowableOnSubscribe;
-import okhttp3.Interceptor;
-import okhttp3.OkHttpClient;
-import okhttp3.logging.HttpLoggingInterceptor;
-import retrofit2.Converter;
-
-
-public class IO extends BaseIO {
- private static volatile IO LOGGED_IN_INSTANCE;
- private String mServerUrl;
- private String mToken;
-
- private Account account;
-
- private static final ConcurrentMap IO_MAP = new ConcurrentHashMap<>();
-
- /**
- * Logged in
- */
- public static IO getInstanceWithLoggedIn() {
- if (LOGGED_IN_INSTANCE != null) {
- return LOGGED_IN_INSTANCE;
- }
-
- // singleton and map
- synchronized (IO.class) {
- if (LOGGED_IN_INSTANCE == null) {
- LOGGED_IN_INSTANCE = new IO();
-
- Account currentAccount = SupportAccountManager.getInstance().getCurrentAccount();
- if (currentAccount == null) {
- throw new IllegalStateException("IO: No current account");
- }
-
- SLogs.d(currentAccount.toString());
- LOGGED_IN_INSTANCE.setAccount(currentAccount);
- LOGGED_IN_INSTANCE.setToken(currentAccount.token);
- LOGGED_IN_INSTANCE.setServerUrl(currentAccount.server);
-
- //
- IO_MAP.put(currentAccount.getSignature(), LOGGED_IN_INSTANCE);
- }
- }
-
- return LOGGED_IN_INSTANCE;
- }
-
-
- /**
- * Not logged in/Log in to another server
- */
- public static IO getInstanceByAccount(Account account) {
- if (IO_MAP.containsKey(account.getSignature())) {
- return IO_MAP.get(account.getSignature());
- }
-
- IO io = new IO();
- io.setServerUrl(account.server);
- io.setToken(account.token);
- io.account = account;
-
- IO_MAP.put(account.getSignature(), io);
- return io;
- }
-
- public static void removeInstanceByAccount(Account account) {
- CLIENT_MAP.remove(account.getSignature());
- IO_MAP.remove(account.getSignature());
- }
-
- /**
- * Not logged in/Log in to another server
- */
- public static IO newInstanceByAccount(Account account) {
-
-
- IO io = new IO();
- io.setServerUrl(account.server);
- io.setToken(account.token);
- io.account = account;
- return io;
- }
-
- public static void updateInstanceByAccount(Account account) {
- IO_MAP.remove(account.getSignature());
-
- //reset okhttp client
- CLIENT_MAP.remove(account.getSignature());
-
- //
- IO io = new IO();
- io.setServerUrl(account.server);
- io.setToken(account.token);
- io.setAccount(account);
-
- IO_MAP.put(account.getSignature(), io);
- }
-
- @Override
- public Account getAccount() {
- return account;
- }
-
-// /**
-// * Not logged in/Log in to another server
-// */
-// public static IO getNewInstance(String hostUrl, String token) {
-// IO io = new IO();
-// io.setServerUrl(hostUrl);
-// io.setToken(token);
-//
-// //
-// resetSingleton();
-//
-// return io;
-// }
-
- /**
- * When you log in again or switch account, you should reset this IO Singleton.
- * because it's a SINGLETON, unless kill the APP!
- */
- public static void resetLoggedInInstance() {
- LOGGED_IN_INSTANCE = null;
- }
-
- private void setServerUrl(String mHostUrl) {
- this.mServerUrl = mHostUrl;
- }
-
- private void setToken(String mToken) {
- this.mToken = mToken;
- }
-
- public String getToken() {
- return mToken;
- }
-
- public void setAccount(Account account) {
- this.account = account;
- }
-
- /**
- * server url
- */
- @Override
- public String getServerUrl() {
- return mServerUrl;
- }
-
- /**
- * @return host.com
- */
- public String getHostDomain() {
- String host = mServerUrl;
- host = StringUtils.toRootLowerCase(host);
- host = StringUtils.removeStart(host, Constants.Protocol.HTTPS);
- host = StringUtils.removeStart(host, Constants.Protocol.HTTP);
- return StringUtils.removeEnd(host, "/");
- }
-
-
- @Override
- public List getInterceptors() {
-
- List interceptors = new ArrayList<>();
-
- //print log
- HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
- loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
-// loggingInterceptor.setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.BASIC);
- interceptors.add(loggingInterceptor);
-
- interceptors.add(new HeaderInterceptor(mToken));
-// interceptors.add(new AddCookiesInterceptor());
-// interceptors.add(new ReceivedCookiesInterceptor());
-
- return interceptors;
- }
-
- @Override
- public Converter.Factory getConverterFactory() {
- return ConverterFactory.create();
- }
-
- public void downloadBinarySync(String url, File destinationFile, ProgressListener callback) throws IOException {
- OkHttpClient client = getClient();
-
- try (OutputStream outputStream = Files.newOutputStream(destinationFile.toPath())) {
- BinaryFileWriter fileWriter = new BinaryFileWriter(outputStream, new ProgressCallback() {
- @Override
- public void onProgress(long transferSize, long totalSize) {
- if (callback != null) {
- callback.onProgress(destinationFile.getName(), transferSize, totalSize);
- }
- }
- });
-
- try (BinaryFileDownloader fileDownloader = new BinaryFileDownloader(client, fileWriter)) {
- fileDownloader.download(url);
-
- } catch (Exception e) {
- if (callback != null) {
- callback.isCancelled();
- }
- e.printStackTrace();
- }
- }
- }
-
- public Flowable downloadBinary(String url, File destinationFile) throws IOException {
-
- return Flowable.create(new FlowableOnSubscribe() {
- @Override
- public void subscribe(FlowableEmitter emitter) throws Exception {
- OkHttpClient client = getClient();
-
- try (OutputStream outputStream = Files.newOutputStream(destinationFile.toPath())) {
- BinaryFileWriter fileWriter = new BinaryFileWriter(outputStream, new ProgressCallback() {
- @Override
- public void onProgress(long transferSize, long totalSize) {
- emitter.onNext(new Long[]{transferSize, totalSize});
- }
- });
-
- try (BinaryFileDownloader fileDownloader = new BinaryFileDownloader(client, fileWriter)) {
- fileDownloader.download(url);
-
- emitter.onComplete();
- } catch (Exception e) {
- emitter.onError(e);
- }
- }
- }
- }, BackpressureStrategy.BUFFER);
- }
-}
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/http/SafeOkHttpClient.java b/app/src/main/java/com/seafile/seadroid2/framework/http/SafeOkHttpClient.java
new file mode 100644
index 000000000..f257a82b6
--- /dev/null
+++ b/app/src/main/java/com/seafile/seadroid2/framework/http/SafeOkHttpClient.java
@@ -0,0 +1,98 @@
+package com.seafile.seadroid2.framework.http;
+
+import com.blankj.utilcode.util.CollectionUtils;
+import com.seafile.seadroid2.account.Account;
+
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import okhttp3.ConnectionSpec;
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+
+public class SafeOkHttpClient extends BaseOkHttpClient {
+ public SafeOkHttpClient(Account account) {
+ super(account);
+ }
+
+ private TrustManager[] getTrustManagers() {
+ try {
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init((KeyStore) null);
+ TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
+ if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
+ throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
+ }
+ return trustManagers;
+ } catch (NoSuchAlgorithmException | KeyStoreException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public SSLSocketFactory getTLSSocketFactory(TrustManager[] trustManagers) {
+ try {
+ X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
+
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());
+ return sslContext.getSocketFactory();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ @Override
+ public OkHttpClient getOkClient() {
+ OkHttpClient.Builder builder = new OkHttpClient.Builder();
+
+ TrustManager[] trustManagers = getTrustManagers();
+ X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
+ SSLSocketFactory sslSocketFactory = getTLSSocketFactory(trustManagers);
+
+ // Add an interceptor to set SSL only for HTTPS
+ builder.addInterceptor(chain -> {
+ Request request = chain.request();
+ if (request.isHttps()) {
+ builder.sslSocketFactory(sslSocketFactory, trustManager);
+ }
+ return chain.proceed(request);
+ });
+
+ builder.connectionSpecs(Arrays.asList(
+ ConnectionSpec.MODERN_TLS,
+ ConnectionSpec.COMPATIBLE_TLS,
+ ConnectionSpec.CLEARTEXT));
+ builder.cache(cache);
+ //cache control
+ builder.interceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR);
+ builder.networkInterceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR);
+
+ //add interceptors
+ List interceptors = getInterceptors();
+ if (!CollectionUtils.isEmpty(interceptors)) {
+ for (Interceptor i : interceptors) {
+ builder.interceptors().add(i);
+ }
+ }
+
+ //timeout
+ builder.writeTimeout(DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS);
+ builder.readTimeout(DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS);
+ builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS);
+
+ return builder.build();
+ }
+}
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/http/UnsafeOkHttpClient.java b/app/src/main/java/com/seafile/seadroid2/framework/http/UnsafeOkHttpClient.java
new file mode 100644
index 000000000..82997a0a6
--- /dev/null
+++ b/app/src/main/java/com/seafile/seadroid2/framework/http/UnsafeOkHttpClient.java
@@ -0,0 +1,93 @@
+package com.seafile.seadroid2.framework.http;
+
+import com.blankj.utilcode.util.CollectionUtils;
+import com.seafile.seadroid2.account.Account;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import okhttp3.ConnectionSpec;
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+
+public class UnsafeOkHttpClient extends BaseOkHttpClient {
+ public UnsafeOkHttpClient(Account account) {
+ super(account);
+ }
+
+ private final TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[]{};
+ }
+ }
+ };
+
+ @Override
+ public OkHttpClient getOkClient() {
+ OkHttpClient.Builder builder = new OkHttpClient.Builder();
+
+
+ try {
+ // Install the all-trusting trust manager
+ final SSLContext sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
+ // Create an ssl socket factory with our all-trusting manager
+ final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+
+ builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ builder.connectionSpecs(Arrays.asList(
+ ConnectionSpec.MODERN_TLS,
+ ConnectionSpec.COMPATIBLE_TLS,
+ ConnectionSpec.CLEARTEXT));
+ builder.cache(cache);
+ builder.hostnameVerifier(new HostnameVerifier() {
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
+ });
+ //cache control
+ builder.interceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR);
+ builder.networkInterceptors().add(REWRITE_CACHE_CONTROL_INTERCEPTOR);
+
+ //add interceptors
+ List interceptors = getInterceptors();
+ if (!CollectionUtils.isEmpty(interceptors)) {
+ for (Interceptor i : interceptors) {
+ builder.interceptors().add(i);
+ }
+ }
+
+ //timeout
+ builder.writeTimeout(DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS);
+ builder.readTimeout(DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS);
+ builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS);
+
+ return builder.build();
+ }
+
+
+}
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/http/interceptor/CurrentTokenInterceptor.java b/app/src/main/java/com/seafile/seadroid2/framework/http/interceptor/CurrentTokenInterceptor.java
new file mode 100644
index 000000000..5745aabe5
--- /dev/null
+++ b/app/src/main/java/com/seafile/seadroid2/framework/http/interceptor/CurrentTokenInterceptor.java
@@ -0,0 +1,32 @@
+package com.seafile.seadroid2.framework.http.interceptor;
+
+import android.text.TextUtils;
+
+import com.seafile.seadroid2.framework.util.TokenManager;
+
+import java.io.IOException;
+
+import okhttp3.Interceptor;
+import okhttp3.Request;
+import okhttp3.Response;
+
+public class CurrentTokenInterceptor implements Interceptor {
+ @Override
+ public Response intercept(Chain chain) throws IOException {
+ return chain.proceed(initBuilder(chain.request().newBuilder()).build());
+ }
+
+ private Request.Builder initBuilder(Request.Builder builder) {
+ builder.addHeader("Content-Type", "application/json");
+ builder.addHeader("Accept", "application/json");
+ builder.addHeader("charset", "utf-8");
+ builder.addHeader("timestamp", String.valueOf(System.currentTimeMillis()));
+
+ String authToken = TokenManager.getInstance().getToken();
+ if (!TextUtils.isEmpty(authToken)) {
+ builder.addHeader("Authorization", "Token " + authToken);
+ }
+
+ return builder;
+ }
+}
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/util/AccountUtils.java b/app/src/main/java/com/seafile/seadroid2/framework/util/AccountUtils.java
index 71994d827..557b1f87e 100644
--- a/app/src/main/java/com/seafile/seadroid2/framework/util/AccountUtils.java
+++ b/app/src/main/java/com/seafile/seadroid2/framework/util/AccountUtils.java
@@ -9,7 +9,7 @@
import com.seafile.seadroid2.framework.datastore.sp.AlbumBackupManager;
import com.seafile.seadroid2.framework.datastore.sp.FolderBackupManager;
import com.seafile.seadroid2.framework.datastore.sp.GestureLockManager;
-import com.seafile.seadroid2.framework.http.IO;
+import com.seafile.seadroid2.framework.http.HttpIO;
import com.seafile.seadroid2.framework.worker.BackgroundJobManagerImpl;
import com.seafile.seadroid2.ui.camera_upload.CameraUploadManager;
@@ -30,7 +30,7 @@ public static void logout(Account account) {
BackgroundJobManagerImpl.getInstance().cancelAllJobs();
//reset IO instance for new account
- IO.resetLoggedInInstance();
+ HttpIO.resetLoggedInInstance();
//clear instance
DataStoreManager.resetUserInstance();
@@ -63,7 +63,7 @@ public static void switchAccount(Account account) {
BackgroundJobManagerImpl.getInstance().cancelAllJobs();
//reset IO instance for new account
- IO.resetLoggedInInstance();
+ HttpIO.resetLoggedInInstance();
//clear instance
DataStoreManager.resetUserInstance();
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/util/GlideCache.java b/app/src/main/java/com/seafile/seadroid2/framework/util/GlideCache.java
index bdba0002c..ac59f0f01 100644
--- a/app/src/main/java/com/seafile/seadroid2/framework/util/GlideCache.java
+++ b/app/src/main/java/com/seafile/seadroid2/framework/util/GlideCache.java
@@ -1,15 +1,30 @@
package com.seafile.seadroid2.framework.util;
import android.content.Context;
+
import androidx.annotation.NonNull;
+import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
+import com.bumptech.glide.Registry;
import com.bumptech.glide.annotation.GlideModule;
+import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
import com.bumptech.glide.load.engine.cache.DiskLruCacheFactory;
+import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.AppGlideModule;
import com.seafile.seadroid2.SeadroidApplication;
+import com.seafile.seadroid2.framework.http.HttpIO;
+import com.seafile.seadroid2.framework.http.interceptor.CurrentTokenInterceptor;
+import com.seafile.seadroid2.framework.http.interceptor.HeaderInterceptor;
import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
@GlideModule
public class GlideCache extends AppGlideModule {
@@ -21,5 +36,25 @@ public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder
String rootPath = externalMediaDirs[0].getAbsolutePath();
File dirPath = new File(rootPath + "/GlideCache/");
builder.setDiskCache(new DiskLruCacheFactory(dirPath.getAbsolutePath(), 1024 * 1024 * 100));
+ GlideApp.tearDown();
+ }
+
+ @Override
+ public boolean isManifestParsingEnabled() {
+ return false;
+ }
+
+ @Override
+ public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
+ try {
+ OkHttpClient client = getClient();
+ registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(client));
+ } catch (IllegalStateException e) {
+ SLogs.d("No current account?");
+ }
+ }
+
+ private OkHttpClient getClient() {
+ return new OkHttpClient.Builder().addInterceptor(new CurrentTokenInterceptor()).build();
}
}
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/util/Objs.java b/app/src/main/java/com/seafile/seadroid2/framework/util/Objs.java
index c4659c2e0..1d8f8f9e0 100644
--- a/app/src/main/java/com/seafile/seadroid2/framework/util/Objs.java
+++ b/app/src/main/java/com/seafile/seadroid2/framework/util/Objs.java
@@ -29,14 +29,13 @@
import com.seafile.seadroid2.framework.data.db.entities.StarredModel;
import com.seafile.seadroid2.framework.data.model.BaseModel;
import com.seafile.seadroid2.framework.data.model.GroupItemModel;
-import com.seafile.seadroid2.framework.data.model.enums.TransferAction;
import com.seafile.seadroid2.framework.data.model.enums.TransferStatus;
import com.seafile.seadroid2.framework.data.model.objs.DirentShareLinkModel;
import com.seafile.seadroid2.framework.data.model.repo.DirentWrapperModel;
import com.seafile.seadroid2.framework.data.model.repo.RepoWrapperModel;
import com.seafile.seadroid2.framework.data.model.star.StarredWrapperModel;
import com.seafile.seadroid2.framework.datastore.sp.Sorts;
-import com.seafile.seadroid2.framework.http.IO;
+import com.seafile.seadroid2.framework.http.HttpIO;
import com.seafile.seadroid2.listener.OnCreateDirentShareLinkListener;
import com.seafile.seadroid2.ui.dialog_fragment.AppChoiceDialogFragment;
import com.seafile.seadroid2.ui.dialog_fragment.GetShareLinkPasswordDialogFragment;
@@ -51,14 +50,11 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.TreeMap;
import java.util.stream.Collectors;
import io.reactivex.Completable;
import io.reactivex.Single;
-import io.reactivex.SingleEmitter;
-import io.reactivex.SingleOnSubscribe;
import io.reactivex.SingleSource;
import io.reactivex.functions.BiFunction;
import io.reactivex.functions.Function;
@@ -72,7 +68,7 @@ public class Objs {
////////////////////////////
public static Single> getStarredSingleFromServer(Account account) {
- Single netSingle = IO.getInstanceByAccount(account).execute(StarredService.class).getStarItems();
+ Single netSingle = HttpIO.getInstanceByAccount(account).execute(StarredService.class).getStarItems();
Completable completable = AppDatabase.getInstance().starredDirentDAO().deleteAllByAccount(account.getSignature());
Single deleteSingle = completable.toSingleDefault(0);
return Single.zip(netSingle, deleteSingle, new BiFunction>() {
@@ -102,7 +98,7 @@ public SingleSource> apply(List starredModels)
//////repo
////////////////////////////
public static Single> getReposSingleFromServer(Account account) {
- Single netSingle = IO.getInstanceByAccount(account).execute(RepoService.class).getRepos();
+ Single netSingle = HttpIO.getInstanceByAccount(account).execute(RepoService.class).getRepos();
Single> dbListSingle = AppDatabase.getInstance().repoDao().getListByAccount(account.getSignature());
//load net data and load local data
@@ -389,7 +385,7 @@ private static TreeMap> groupRepos(List repos
////////////////////////////
public static Single> getDirentsSingleFromServer(Account account, String repoId, String repoName, String parentDir) {
- Single netSingle = IO.getInstanceByAccount(account).execute(RepoService.class).getDirents(repoId, parentDir);
+ Single netSingle = HttpIO.getInstanceByAccount(account).execute(RepoService.class).getDirents(repoId, parentDir);
Single> dbSingle = AppDatabase.getInstance().direntDao().getListByParentPath(repoId, parentDir);
return Single.zip(netSingle, dbSingle, new BiFunction, List>() {
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/util/TokenManager.java b/app/src/main/java/com/seafile/seadroid2/framework/util/TokenManager.java
new file mode 100644
index 000000000..0629aefa0
--- /dev/null
+++ b/app/src/main/java/com/seafile/seadroid2/framework/util/TokenManager.java
@@ -0,0 +1,24 @@
+package com.seafile.seadroid2.framework.util;
+
+public class TokenManager {
+ private static TokenManager instance;
+ private String token;
+
+ private TokenManager() {
+ }
+
+ public static synchronized TokenManager getInstance() {
+ if (instance == null) {
+ instance = new TokenManager();
+ }
+ return instance;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+}
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/worker/TransferWorker.java b/app/src/main/java/com/seafile/seadroid2/framework/worker/TransferWorker.java
index 2bf0ac825..1689bcd58 100644
--- a/app/src/main/java/com/seafile/seadroid2/framework/worker/TransferWorker.java
+++ b/app/src/main/java/com/seafile/seadroid2/framework/worker/TransferWorker.java
@@ -10,7 +10,6 @@
import com.google.common.util.concurrent.ListenableFuture;
import com.seafile.seadroid2.SeafException;
import com.seafile.seadroid2.account.Account;
-import com.seafile.seadroid2.framework.data.BlockInfoBean;
import com.seafile.seadroid2.framework.data.db.AppDatabase;
import com.seafile.seadroid2.framework.data.db.entities.DirentModel;
import com.seafile.seadroid2.framework.data.db.entities.FileTransferEntity;
@@ -19,7 +18,7 @@
import com.seafile.seadroid2.framework.data.model.dirents.DirentFileModel;
import com.seafile.seadroid2.framework.data.model.enums.TransferDataSource;
import com.seafile.seadroid2.framework.data.model.repo.DirentWrapperModel;
-import com.seafile.seadroid2.framework.http.IO;
+import com.seafile.seadroid2.framework.http.HttpIO;
import com.seafile.seadroid2.framework.notification.GeneralNotificationHelper;
import com.seafile.seadroid2.framework.util.HttpUtils;
import com.seafile.seadroid2.framework.util.Objs;
@@ -27,12 +26,8 @@
import com.seafile.seadroid2.ui.file.FileService;
import com.seafile.seadroid2.ui.repo.RepoService;
-import org.apache.commons.lang3.StringUtils;
-import org.json.JSONException;
-
import java.io.IOException;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -78,7 +73,7 @@ public void showForegroundAsync(ForegroundInfo foregroundInfo) {
}
protected boolean checkRemoteDirExists(String repoId, String dirPath) throws IOException {
- retrofit2.Response response = IO.getInstanceWithLoggedIn()
+ retrofit2.Response response = HttpIO.getCurrentInstance()
.execute(FileService.class)
.getDirDetailCall(repoId, dirPath)
.execute();
@@ -93,7 +88,7 @@ protected void mkdirRemote(String repoId, String path) throws IOException {
Map requestBodyMap = HttpUtils.generateRequestBody(requestDataMap);
- retrofit2.Response response = IO.getInstanceWithLoggedIn()
+ retrofit2.Response response = HttpIO.getCurrentInstance()
.execute(FileService.class)
.mkDirCall(repoId, path, requestBodyMap)
.execute();
@@ -106,7 +101,7 @@ protected void mkdirRemote(String repoId, String path) throws IOException {
}
protected DirentFileModel getRemoteFile(String repoId, String remotePath) throws IOException, SeafException {
- retrofit2.Response fileDetailRes = IO.getInstanceWithLoggedIn()
+ retrofit2.Response fileDetailRes = HttpIO.getCurrentInstance()
.execute(FileService.class)
.getFileDetailCall(repoId, remotePath)
.execute();
@@ -125,7 +120,7 @@ protected DirentFileModel getRemoteFile(String repoId, String remotePath) throws
protected boolean getRemoteDirentList(Account account, RepoModel repoModel, String parentDir) throws IOException, SeafException {
- retrofit2.Response wrapperRes = IO.getInstanceWithLoggedIn()
+ retrofit2.Response wrapperRes = HttpIO.getCurrentInstance()
.execute(RepoService.class)
.getDirentsCall(repoModel.repo_id, parentDir)
.execute();
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/worker/download/DownloadFileScanWorker.java b/app/src/main/java/com/seafile/seadroid2/framework/worker/download/DownloadFileScanWorker.java
index 5775a7558..ef74f185e 100644
--- a/app/src/main/java/com/seafile/seadroid2/framework/worker/download/DownloadFileScanWorker.java
+++ b/app/src/main/java/com/seafile/seadroid2/framework/worker/download/DownloadFileScanWorker.java
@@ -24,7 +24,7 @@
import com.seafile.seadroid2.framework.data.model.enums.TransferAction;
import com.seafile.seadroid2.framework.data.model.enums.TransferResult;
import com.seafile.seadroid2.framework.data.model.enums.TransferStatus;
-import com.seafile.seadroid2.framework.http.IO;
+import com.seafile.seadroid2.framework.http.HttpIO;
import com.seafile.seadroid2.framework.notification.DownloadNotificationHelper;
import com.seafile.seadroid2.framework.util.SLogs;
import com.seafile.seadroid2.framework.worker.BackgroundJobManagerImpl;
@@ -263,7 +263,7 @@ private void insertIntoDbWhenDirentIsDir(Account account, DirentModel direntMode
* fetch file detail from server
*/
private DirentFileModel fetchFile(DirentModel direntModel) throws IOException {
- retrofit2.Response res = IO.getInstanceWithLoggedIn().execute(FileService.class).getFileDetailCall(direntModel.repo_id, direntModel.full_path).execute();
+ retrofit2.Response res = HttpIO.getCurrentInstance().execute(FileService.class).getFileDetailCall(direntModel.repo_id, direntModel.full_path).execute();
if (!res.isSuccessful()) {
return null;
}
@@ -275,7 +275,7 @@ private DirentFileModel fetchFile(DirentModel direntModel) throws IOException {
* get recursive files from server
*/
private List fetchRecursiveFiles(DirentModel direntModel) throws IOException {
- retrofit2.Response> res = IO.getInstanceWithLoggedIn().execute(FileService.class).getDirRecursiveFileCall(direntModel.repo_id, direntModel.full_path).execute();
+ retrofit2.Response> res = HttpIO.getCurrentInstance().execute(FileService.class).getDirRecursiveFileCall(direntModel.repo_id, direntModel.full_path).execute();
if (!res.isSuccessful()) {
return Collections.emptyList();
}
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/worker/download/DownloadWorker.java b/app/src/main/java/com/seafile/seadroid2/framework/worker/download/DownloadWorker.java
index 06c6e8dd3..381d5bee3 100644
--- a/app/src/main/java/com/seafile/seadroid2/framework/worker/download/DownloadWorker.java
+++ b/app/src/main/java/com/seafile/seadroid2/framework/worker/download/DownloadWorker.java
@@ -28,7 +28,7 @@
import com.seafile.seadroid2.framework.data.db.entities.FileTransferEntity;
import com.seafile.seadroid2.framework.data.model.enums.TransferResult;
import com.seafile.seadroid2.framework.data.model.enums.TransferStatus;
-import com.seafile.seadroid2.framework.http.IO;
+import com.seafile.seadroid2.framework.http.HttpIO;
import com.seafile.seadroid2.framework.notification.base.BaseNotification;
import com.seafile.seadroid2.framework.util.SLogs;
import com.seafile.seadroid2.framework.worker.BackgroundJobManagerImpl;
@@ -97,7 +97,7 @@ public Result doWork() {
//count
int pendingCount = AppDatabase.getInstance().fileTransferDAO().countPendingDownloadListSync(account.getSignature());
if (pendingCount <= 0) {
- return Result.success(getFinishData());
+ return Result.success(getFinishData(false));
}
ForegroundInfo foregroundInfo = notificationHelper.getForegroundNotification();
@@ -156,13 +156,14 @@ public Result doWork() {
ToastUtils.showLong(R.string.download_finished);
}
- return Result.success(getFinishData());
+ return Result.success(getFinishData(isDownloaded));
}
- private Data getFinishData() {
+ private Data getFinishData(boolean isDownloaded) {
return new Data.Builder()
.putString(TransferWorker.KEY_DATA_EVENT, TransferEvent.EVENT_FINISH)
- .putString(TransferWorker.KEY_DATA_TYPE, String.valueOf(TransferDataSource.FOLDER_BACKUP))
+ .putBoolean(TransferWorker.KEY_DATA_PARAM, isDownloaded)
+ .putString(TransferWorker.KEY_DATA_TYPE, String.valueOf(TransferDataSource.DOWNLOAD))
.build();
}
@@ -202,6 +203,10 @@ private void transferFile(Account account, FileTransferEntity transferEntity) th
return;
}
+ //update modified_at field
+ transferEntity.modified_at = System.currentTimeMillis();
+ AppDatabase.getInstance().fileTransferDAO().update(transferEntity);
+
if (repoModels.get(0).canLocalDecrypt()) {
downloadFileByBlock(account, transferEntity);
} else {
@@ -228,7 +233,7 @@ private void downloadFile(Account account, FileTransferEntity transferEntity) th
}
private Pair getDownloadLink(FileTransferEntity transferEntity, boolean isReUsed) throws SeafException, IOException {
- retrofit2.Response res = IO.getInstanceWithLoggedIn()
+ retrofit2.Response res = HttpIO.getCurrentInstance()
.execute(FileService.class)
.getFileDownloadLink(transferEntity.repo_id, transferEntity.full_path)
.execute();
@@ -273,7 +278,7 @@ private void download(FileTransferEntity fileTransferEntity, String dlink, File
.get()
.build();
- Call newCall = IO.getInstanceWithLoggedIn().getClient().newCall(request);
+ Call newCall = HttpIO.getCurrentInstance().getOkHttpClient().getOkClient().newCall(request);
try (Response response = newCall.execute()) {
if (!response.isSuccessful()) {
@@ -366,7 +371,7 @@ private void updateEntitySuccessState(FileTransferEntity fileTransferEntity, Fil
///////////////block///////////////
private FileBlocks getDownloadBlockList(FileTransferEntity transferEntity) throws Exception {
- retrofit2.Response res = IO.getInstanceWithLoggedIn()
+ retrofit2.Response res = HttpIO.getCurrentInstance()
.execute(FileService.class)
.getFileBlockDownloadLink(transferEntity.repo_id, transferEntity.full_path)
.execute();
@@ -423,7 +428,7 @@ private void downloadFileByBlock(Account account, FileTransferEntity transferEnt
for (Block blk : fileBlocks.getBlocks()) {
File tempBlock = new File(StorageManager.getInstance().getTempDir(), blk.blockId);
- retrofit2.Response blockRes = IO.getInstanceWithLoggedIn()
+ retrofit2.Response blockRes = HttpIO.getCurrentInstance()
.execute(FileService.class)
.getBlockDownloadLink(transferEntity.repo_id, fileBlocks.getFileId(), blk.blockId)
.execute();
@@ -461,7 +466,7 @@ private void downloadBlock(FileBlocks fileBlocks, String blockId, String dlink,
.url(dlink)
.get()
.build();
- Call newCall = IO.getInstanceWithLoggedIn().getClient().newCall(request);
+ Call newCall = HttpIO.getCurrentInstance().getOkHttpClient().getOkClient().newCall(request);
Response response = newCall.execute();
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/BaseUploadWorker.java b/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/BaseUploadWorker.java
index 3d2ae3afb..83fbe7803 100644
--- a/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/BaseUploadWorker.java
+++ b/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/BaseUploadWorker.java
@@ -27,11 +27,7 @@
import com.seafile.seadroid2.framework.data.model.enums.TransferResult;
import com.seafile.seadroid2.framework.data.model.enums.TransferStatus;
import com.seafile.seadroid2.framework.datastore.StorageManager;
-import com.seafile.seadroid2.framework.http.IO;
-import com.seafile.seadroid2.framework.notification.AlbumBackupNotificationHelper;
-import com.seafile.seadroid2.framework.notification.FileBackupNotificationHelper;
-import com.seafile.seadroid2.framework.notification.FolderBackupNotificationHelper;
-import com.seafile.seadroid2.framework.notification.base.BaseNotification;
+import com.seafile.seadroid2.framework.http.HttpIO;
import com.seafile.seadroid2.framework.notification.base.BaseTransferNotificationHelper;
import com.seafile.seadroid2.framework.util.HttpUtils;
import com.seafile.seadroid2.framework.util.SLogs;
@@ -163,8 +159,9 @@ public String isInterrupt(TransferResult result) {
protected boolean calcQuota(List list) throws SeafException, IOException {
+ //
Account account = SupportAccountManager.getInstance().getCurrentAccount();
- if (account != null && account.isQuotaNoLimit()) {
+ if (account != null && account.isQuotaUnlimited()) {
return true;
}
@@ -184,7 +181,7 @@ protected boolean calcQuota(List list) throws SeafException,
}
protected AccountInfo getAccountInfo() throws IOException, SeafException {
- retrofit2.Response response = IO.getInstanceWithLoggedIn()
+ retrofit2.Response response = HttpIO.getCurrentInstance()
.execute(AccountService.class)
.getAccountInfoCall()
.execute();
@@ -391,6 +388,10 @@ public void transferFile(Account account, FileTransferEntity transferEntity) thr
return;
}
+ //update modified_at field
+ transferEntity.modified_at = System.currentTimeMillis();
+ AppDatabase.getInstance().fileTransferDAO().update(transferEntity);
+
RepoModel repo = repoModels.get(0);
if (repo.canLocalDecrypt()) {
uploadBlockFile(account, repo, transferEntity);
@@ -477,7 +478,7 @@ private void uploadFile(Account account, RepoModel repoModel, FileTransferEntity
.url(uploadUrl)
.post(requestBody)
.build();
- newCall = IO.getInstanceWithLoggedIn().getClient().newCall(request);
+ newCall = HttpIO.getCurrentInstance().getOkHttpClient().getOkClient().newCall(request);
Response response = newCall.execute();
@@ -580,7 +581,7 @@ private void uploadBlockFile(Account account, RepoModel repoModel, FileTransferE
private String getFileUploadUrl(String repoId, String target_dir, boolean isUpdate) throws IOException, SeafException {
retrofit2.Response res;
if (isUpdate) {
- res = IO.getInstanceWithLoggedIn()
+ res = HttpIO.getCurrentInstance()
.execute(FileService.class)
.getFileUpdateLink(repoId)
.execute();
@@ -588,7 +589,7 @@ private String getFileUploadUrl(String repoId, String target_dir, boolean isUpda
// target_dir = StringUtils.removeEnd(target_dir, "/");
- res = IO.getInstanceWithLoggedIn()
+ res = HttpIO.getCurrentInstance()
.execute(FileService.class)
.getFileUploadLink(repoId, "/")
.execute();
@@ -613,7 +614,7 @@ private BlockInfoBean getFileBlockUploadUrl(Account account, String repoId, Link
Map requestBodyMap = HttpUtils.generateRequestBody(requestDataMap);
- retrofit2.Response res = IO.getInstanceWithLoggedIn()
+ retrofit2.Response res = HttpIO.getCurrentInstance()
.execute(FileService.class)
.getFileBlockUploadLink(repoId, requestBodyMap)
.execute();
@@ -660,7 +661,7 @@ private String uploadBlocksCommon(String link, List needUploadId, String
Request request = new Request.Builder().url(link)
.post(body)
.build();
- Response response = IO.getInstanceWithLoggedIn().getClient().newCall(request).execute();
+ Response response = HttpIO.getCurrentInstance().getOkHttpClient().getOkClient().newCall(request).execute();
if (!response.isSuccessful()) {
throw SeafException.networkException;
@@ -712,7 +713,7 @@ private void commitUpload(String link, List blkIds, FileTransferEntity t
SLogs.d("Folder upload block: newCall has executed()");
}
try {
- newCall = IO.getInstanceWithLoggedIn().getClient().newCall(request);
+ newCall = HttpIO.getCurrentInstance().getOkHttpClient().getOkClient().newCall(request);
Response response = newCall.execute();
if (!response.isSuccessful()) {
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/MediaBackupScannerWorker.java b/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/MediaBackupScannerWorker.java
index 985479ba2..67f761f9f 100644
--- a/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/MediaBackupScannerWorker.java
+++ b/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/MediaBackupScannerWorker.java
@@ -15,7 +15,6 @@
import androidx.work.WorkerParameters;
import com.blankj.utilcode.util.CollectionUtils;
-import com.blankj.utilcode.util.FileUtils;
import com.google.common.base.Joiner;
import com.seafile.seadroid2.R;
import com.seafile.seadroid2.SeadroidApplication;
@@ -23,7 +22,6 @@
import com.seafile.seadroid2.account.Account;
import com.seafile.seadroid2.account.SupportAccountManager;
import com.seafile.seadroid2.framework.data.model.enums.TransferDataSource;
-import com.seafile.seadroid2.framework.datastore.DataManager;
import com.seafile.seadroid2.framework.datastore.StorageManager;
import com.seafile.seadroid2.framework.data.db.AppDatabase;
import com.seafile.seadroid2.framework.data.db.entities.DirentModel;
@@ -31,10 +29,9 @@
import com.seafile.seadroid2.framework.data.model.enums.TransferAction;
import com.seafile.seadroid2.framework.data.model.repo.DirentWrapperModel;
import com.seafile.seadroid2.framework.datastore.sp.AlbumBackupManager;
-import com.seafile.seadroid2.framework.http.IO;
+import com.seafile.seadroid2.framework.http.HttpIO;
import com.seafile.seadroid2.framework.notification.AlbumBackupScanNotificationHelper;
import com.seafile.seadroid2.framework.util.SLogs;
-import com.seafile.seadroid2.framework.notification.AlbumBackupNotificationHelper;
import com.seafile.seadroid2.framework.worker.BackgroundJobManagerImpl;
import com.seafile.seadroid2.framework.worker.TransferEvent;
import com.seafile.seadroid2.framework.worker.TransferWorker;
@@ -443,7 +440,7 @@ private void forceCreateDirectory(String parent, String dirIsBucketName, List direntWrapperModelCall = IO.getInstanceWithLoggedIn().execute(RepoService.class).getDirentsSync(repoConfig.getRepoID(), parent);
+ Call direntWrapperModelCall = HttpIO.getCurrentInstance().execute(RepoService.class).getDirentsSync(repoConfig.getRepoID(), parent);
retrofit2.Response res = direntWrapperModelCall.execute();
if (!res.isSuccessful()) {
throw SeafException.networkException;
@@ -493,7 +490,7 @@ private void forceCreateDirectory(String parent, String dirIsBucketName, List> filePathList) throws SeafException, IOException {
- Call direntWrapperModelCall = IO.getInstanceWithLoggedIn().execute(RepoService.class).getDirentsSync(repoConfig.getRepoID(), parent);
+ Call direntWrapperModelCall = HttpIO.getCurrentInstance().execute(RepoService.class).getDirentsSync(repoConfig.getRepoID(), parent);
retrofit2.Response res = direntWrapperModelCall.execute();
if (!res.isSuccessful()) {
throw SeafException.networkException;
@@ -550,7 +547,7 @@ private void renameRemoteFile(String name, String fullPath) throws IOException {
renameMap.put("newname", newFilename);
Map requestBodyMap = HttpUtils.generateRequestBody(renameMap);
- retrofit2.Response renameRes = IO.getInstanceWithLoggedIn()
+ retrofit2.Response renameRes = HttpIO.getCurrentInstance()
.execute(FileService.class)
.renameFileCall(repoConfig.getRepoID(), fullPath, requestBodyMap)
.execute();
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/UploadFileManuallyWorker.java b/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/UploadFileManuallyWorker.java
index 6766df87e..46397e9cc 100644
--- a/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/UploadFileManuallyWorker.java
+++ b/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/UploadFileManuallyWorker.java
@@ -121,6 +121,10 @@ private ListenableWorker.Result start() {
throw SeafException.notLoggedInException;
}
+ //update modified_at field
+ transferEntity.modified_at = System.currentTimeMillis();
+ AppDatabase.getInstance().fileTransferDAO().update(transferEntity);
+
transferFile(account, transferEntity);
sendTransferEvent(transferEntity, true);
@@ -168,7 +172,7 @@ private ListenableWorker.Result start() {
Data data = new Data.Builder()
.putString(TransferWorker.KEY_DATA_EVENT, finishFlagEvent)
-// .putInt(TransferWorker.KEY_DATA_PARAM, pendingCount)
+ .putBoolean(TransferWorker.KEY_DATA_PARAM, isUploaded)
.putString(TransferWorker.KEY_DATA_TYPE, String.valueOf(TransferDataSource.FILE_BACKUP))
.build();
return ListenableWorker.Result.success(data);
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/UploadFolderFileAutomaticallyWorker.java b/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/UploadFolderFileAutomaticallyWorker.java
index ff8693d33..121ac1a8b 100644
--- a/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/UploadFolderFileAutomaticallyWorker.java
+++ b/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/UploadFolderFileAutomaticallyWorker.java
@@ -165,7 +165,7 @@ private Result start() {
Data data = new Data.Builder()
.putString(TransferWorker.KEY_DATA_EVENT, finishFlagEvent)
-// .putInt(TransferWorker.KEY_DATA_PARAM, pendingCount)
+ .putBoolean(TransferWorker.KEY_DATA_PARAM, isUploaded)
.putString(TransferWorker.KEY_DATA_TYPE, String.valueOf(TransferDataSource.FOLDER_BACKUP))
.build();
return Result.success(data);
diff --git a/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/UploadMediaFileAutomaticallyWorker.java b/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/UploadMediaFileAutomaticallyWorker.java
index 831585a0e..ebcd1c774 100644
--- a/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/UploadMediaFileAutomaticallyWorker.java
+++ b/app/src/main/java/com/seafile/seadroid2/framework/worker/upload/UploadMediaFileAutomaticallyWorker.java
@@ -152,7 +152,7 @@ public ListenableWorker.Result doWork() {
Data data = new Data.Builder()
.putString(TransferWorker.KEY_DATA_EVENT, finishFlagEvent)
-// .putInt(TransferWorker.KEY_DATA_PARAM, pendingCount)
+ .putBoolean(TransferWorker.KEY_DATA_PARAM, isUploaded)
.putString(TransferWorker.KEY_DATA_TYPE, String.valueOf(TransferDataSource.ALBUM_BACKUP))
.build();
return Result.success(data);
diff --git a/app/src/main/java/com/seafile/seadroid2/provider/SeafileProvider.java b/app/src/main/java/com/seafile/seadroid2/provider/SeafileProvider.java
index fb560918f..275cac4d9 100644
--- a/app/src/main/java/com/seafile/seadroid2/provider/SeafileProvider.java
+++ b/app/src/main/java/com/seafile/seadroid2/provider/SeafileProvider.java
@@ -40,24 +40,21 @@
import android.util.Log;
import com.blankj.utilcode.util.CollectionUtils;
-import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
-import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.request.RequestOptions;
import com.seafile.seadroid2.R;
import com.seafile.seadroid2.SeadroidApplication;
import com.seafile.seadroid2.account.Account;
import com.seafile.seadroid2.account.SupportAccountManager;
-import com.seafile.seadroid2.config.GlideLoadConfig;
-import com.seafile.seadroid2.config.RepoType;
import com.seafile.seadroid2.framework.data.db.AppDatabase;
import com.seafile.seadroid2.framework.data.db.entities.DirentModel;
import com.seafile.seadroid2.framework.data.db.entities.RepoModel;
import com.seafile.seadroid2.framework.data.db.entities.StarredModel;
import com.seafile.seadroid2.framework.data.model.BaseModel;
import com.seafile.seadroid2.framework.datastore.DataManager;
-import com.seafile.seadroid2.framework.http.IO;
+import com.seafile.seadroid2.framework.http.HttpIO;
import com.seafile.seadroid2.framework.util.ConcurrentAsyncTask;
+import com.seafile.seadroid2.framework.util.GlideApp;
import com.seafile.seadroid2.framework.util.Objs;
import com.seafile.seadroid2.framework.util.SLogs;
import com.seafile.seadroid2.framework.util.Utils;
@@ -507,7 +504,12 @@ private File getFile(final CancellationSignal signal, Account account, RepoModel
try {
//get download url
- Call urlCall = IO.getInstanceByAccount(account).execute(FileService.class).getFileDownloadLinkSync(repo.repo_id, path);
+ HttpIO httpIo = HttpIO.getInstanceByAccount(account);
+ if (httpIo == null) {
+ throw new FileNotFoundException();
+ }
+ Call urlCall = httpIo.execute(FileService.class).getFileDownloadLinkSync(repo.repo_id, path);
+
Response res = urlCall.execute();
if (!res.isSuccessful()) {
throw new FileNotFoundException();
@@ -520,7 +522,7 @@ private File getFile(final CancellationSignal signal, Account account, RepoModel
SLogs.d("SeafileProvider: start download");
SLogs.d("targetFile = " + targetFile);
- IO.getInstanceByAccount(account).downloadBinarySync(url, targetFile, new ProgressListener() {
+ httpIo.downloadBinarySync(url, targetFile, new ProgressListener() {
@Override
public void onProgress(String fileName, long cur, long total) {
SLogs.d("fileName = " + fileName + ", cur = " + ", total = " + total);
@@ -590,25 +592,23 @@ public Bitmap call() throws Exception {
try (FileOutputStream fileStream = new FileOutputStream(pair[1].getFileDescriptor())) {
File localFile = DataManager.getLocalRepoFile(account, repoId, repoModel.repo_name, path);
- GlideUrl glideUrl;
+ String urlPath;
if (localFile.exists()) {
- String urlPath = "file://" + localFile.getAbsolutePath();
+ urlPath = "file://" + localFile.getAbsolutePath();
SLogs.d("urlPath = " + urlPath);
- glideUrl = new GlideUrl(urlPath);
} else {
String pathEnc = URLEncoder.encode(path, "UTF-8");
- String urlPath = account.getServer() + String.format("api2/repos/%s/thumbnail/?p=%s&size=%s", repoId, pathEnc, sizeHint.x);
+ urlPath = account.getServer() + String.format("api2/repos/%s/thumbnail/?p=%s&size=%s", repoId, pathEnc, sizeHint.x);
SLogs.d("urlPath = " + urlPath);
- glideUrl = GlideLoadConfig.getGlideUrl(urlPath, account.token);
}
RequestOptions requestOptions = new RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.ALL);
- bitmap = Glide.with(getContext())
+ bitmap = GlideApp.with(getContext())
.asBitmap()
.apply(requestOptions)
- .load(glideUrl)
+ .load(urlPath)
.centerCrop()
.submit(sizeHint.x, sizeHint.y)
.get();
diff --git a/app/src/main/java/com/seafile/seadroid2/ssl/CertsDBHelper.java b/app/src/main/java/com/seafile/seadroid2/ssl/CertsDBHelper.java
index 581a168c2..3ffceb286 100644
--- a/app/src/main/java/com/seafile/seadroid2/ssl/CertsDBHelper.java
+++ b/app/src/main/java/com/seafile/seadroid2/ssl/CertsDBHelper.java
@@ -6,15 +6,18 @@
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.cert.X509Certificate;
+import java.util.List;
-import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Base64;
+import com.blankj.utilcode.util.CollectionUtils;
import com.seafile.seadroid2.SeadroidApplication;
+import com.seafile.seadroid2.framework.data.db.AppDatabase;
+import com.seafile.seadroid2.framework.data.db.entities.CertEntity;
public class CertsDBHelper extends SQLiteOpenHelper {
// If you change the database schema, you must increment the database version.
@@ -50,99 +53,10 @@ public void onCreate(SQLiteDatabase db) {
}
@Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
-
- @Override
- public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
-
- public X509Certificate getCertificate(String url) {
- String[] projection = {COLUMN_CERT};
-
- Cursor c = database.query(TABLE_NAME,
- projection,
- "url=?",
- new String[] {url},
- null, // don't group the rows
- null, // don't filter by row groups
- null); // The sort order
-
- if (!c.moveToFirst()) {
- c.close();
- return null;
- }
-
- X509Certificate cert = cursorToCert(c);
-
- c.close();
- return cert;
- }
-
- private X509Certificate cursorToCert(Cursor cursor) {
- X509Certificate cert = null;
- String text = cursor.getString(0);
-
- ByteArrayInputStream bis = null;
- ObjectInputStream ois = null;
- byte[] data = null;
-
- data = Base64.decode(text, Base64.DEFAULT);
-
- try {
- bis = new ByteArrayInputStream(data);
- ois = new ObjectInputStream(bis);
- cert = (X509Certificate) ois.readObject();
- return cert;
- } catch (ClassNotFoundException e) {
- return null;
- } catch (IOException e) {
- return null;
- } finally {
- if (bis != null) {
- try {
- bis.close();
- } catch (IOException e) {
- }
- }
-
- if (ois != null) {
- try {
- ois.close();
- } catch (IOException e) {
- }
- }
- }
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
- public void saveCertificate(String url, X509Certificate cert) {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- ObjectOutputStream out = null;
- String text = null;
- try {
- out = new ObjectOutputStream(bos);
- out.writeObject(cert);
- byte[] data = bos.toByteArray();
- text = Base64.encodeToString(data, Base64.DEFAULT);
- } catch (IOException e) {
- return;
- } finally {
- try {
- if (out != null) {
- out.close();
- }
- } catch (IOException ex) {
- // ignore close exception
- }
- try {
- bos.close();
- } catch (IOException ex) {
- // ignore close exception
- }
- }
-
- ContentValues values = new ContentValues();
- values.put(COLUMN_URL, url);
- values.put(COLUMN_CERT, text);
-
- database.replace(TABLE_NAME, null, values);
+ @Override
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
diff --git a/app/src/main/java/com/seafile/seadroid2/ssl/CertsHelper.java b/app/src/main/java/com/seafile/seadroid2/ssl/CertsHelper.java
new file mode 100644
index 000000000..2991825a2
--- /dev/null
+++ b/app/src/main/java/com/seafile/seadroid2/ssl/CertsHelper.java
@@ -0,0 +1,129 @@
+package com.seafile.seadroid2.ssl;
+
+import android.database.Cursor;
+import android.util.Base64;
+
+import com.blankj.utilcode.util.CollectionUtils;
+import com.seafile.seadroid2.framework.data.db.AppDatabase;
+import com.seafile.seadroid2.framework.data.db.entities.CertEntity;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+public class CertsHelper {
+
+ public static X509Certificate getCertificate(String url) {
+ List list = AppDatabase.getInstance().certDAO().getListByUrl(url);
+ if (CollectionUtils.isEmpty(list)) {
+ return null;
+ }
+
+ return convertToCert(list.get(0).cert);
+
+// String[] projection = {COLUMN_CERT};
+//
+// Cursor c = database.query(TABLE_NAME,
+// projection,
+// "url=?",
+// new String[]{url},
+// null, // don't group the rows
+// null, // don't filter by row groups
+// null); // The sort order
+//
+// if (!c.moveToFirst()) {
+// c.close();
+// return null;
+// }
+//
+// X509Certificate cert = cursorToCert(c);
+//
+// c.close();
+// return cert;
+ }
+
+ private static X509Certificate convertToCert(String text) {
+ X509Certificate cert = null;
+
+ ByteArrayInputStream bis = null;
+ ObjectInputStream ois = null;
+ byte[] data = null;
+
+ data = Base64.decode(text, Base64.DEFAULT);
+
+ try {
+ bis = new ByteArrayInputStream(data);
+ ois = new ObjectInputStream(bis);
+ cert = (X509Certificate) ois.readObject();
+ return cert;
+ } catch (ClassNotFoundException e) {
+ return null;
+ } catch (IOException e) {
+ return null;
+ } finally {
+ if (bis != null) {
+ try {
+ bis.close();
+ } catch (IOException e) {
+ }
+ }
+
+ if (ois != null) {
+ try {
+ ois.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ private static X509Certificate cursorToCert(Cursor cursor) {
+ X509Certificate cert = null;
+ String text = cursor.getString(0);
+ return convertToCert(text);
+ }
+
+ public static void saveCertificate(String url, X509Certificate cert) {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream out = null;
+ String text = null;
+ try {
+ out = new ObjectOutputStream(bos);
+ out.writeObject(cert);
+ byte[] data = bos.toByteArray();
+ text = Base64.encodeToString(data, Base64.DEFAULT);
+ } catch (IOException e) {
+ return;
+ } finally {
+ try {
+ if (out != null) {
+ out.close();
+ }
+ } catch (IOException ex) {
+ // ignore close exception
+ }
+ try {
+ bos.close();
+ } catch (IOException ex) {
+ // ignore close exception
+ }
+ }
+
+// ContentValues values = new ContentValues();
+// values.put(COLUMN_URL, url);
+// values.put(COLUMN_CERT, text);
+// database.replace(TABLE_NAME, null, values);
+
+ CertEntity certEntity = new CertEntity();
+ certEntity.cert = text;
+ certEntity.url = url;
+
+ AppDatabase.getInstance().certDAO().deleteByUrl(url);
+ AppDatabase.getInstance().certDAO().insert(certEntity);
+
+ }
+}
diff --git a/app/src/main/java/com/seafile/seadroid2/ssl/CertsManager.java b/app/src/main/java/com/seafile/seadroid2/ssl/CertsManager.java
index badc238c3..458724162 100644
--- a/app/src/main/java/com/seafile/seadroid2/ssl/CertsManager.java
+++ b/app/src/main/java/com/seafile/seadroid2/ssl/CertsManager.java
@@ -7,6 +7,8 @@
import android.util.Log;
import com.google.common.collect.Maps;
+import com.seafile.seadroid2.framework.data.db.AppDatabase;
+import com.seafile.seadroid2.framework.data.db.entities.CertEntity;
import com.seafile.seadroid2.framework.util.ConcurrentAsyncTask;
import com.seafile.seadroid2.account.Account;
@@ -32,7 +34,7 @@ public static synchronized CertsManager instance() {
public void saveCertForAccount(final Account account, boolean rememberChoice) {
List certs = SSLTrustManager.instance().getCertsChainForAccount(account);
- if (certs == null || certs.size() == 0) {
+ if (certs == null || certs.isEmpty()) {
return;
}
@@ -43,7 +45,8 @@ public void saveCertForAccount(final Account account, boolean rememberChoice) {
ConcurrentAsyncTask.submit(new Runnable() {
@Override
public void run() {
- db.saveCertificate(account.server, cert);
+ CertsHelper.saveCertificate(account.server,cert);
+// db.saveCertificate(account.server, cert);
}
});
}
@@ -57,7 +60,8 @@ public X509Certificate getCertificate(Account account) {
return cert;
}
- cert = db.getCertificate(account.server);
+// cert = db.getCertificate(account.server);
+ cert = CertsHelper.getCertificate(account.server);
if (cert != null) {
cachedCerts.put(account, cert);
}
diff --git a/app/src/main/java/com/seafile/seadroid2/ssl/SSLTrustManager.java b/app/src/main/java/com/seafile/seadroid2/ssl/SSLTrustManager.java
index 29ea2dbf5..697cff9ca 100644
--- a/app/src/main/java/com/seafile/seadroid2/ssl/SSLTrustManager.java
+++ b/app/src/main/java/com/seafile/seadroid2/ssl/SSLTrustManager.java
@@ -7,6 +7,7 @@
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.seafile.seadroid2.account.Account;
+import com.seafile.seadroid2.framework.util.ConcurrentAsyncTask;
import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
import org.apache.http.conn.ssl.X509HostnameVerifier;
@@ -29,8 +30,9 @@
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
-@Deprecated
+
public final class SSLTrustManager {
+
public enum SslFailureReason {
CERT_NOT_TRUSTED,
CERT_CHANGED,
@@ -60,11 +62,9 @@ public static synchronized SSLTrustManager instance() {
private void init() {
try {
- javax.net.ssl.TrustManagerFactory tmf;
- TrustManager[] tms;
- tmf = javax.net.ssl.TrustManagerFactory.getInstance("X509");
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init((KeyStore) null);
- tms = tmf.getTrustManagers();
+ TrustManager[] tms = tmf.getTrustManagers();
if (tms != null) {
for (TrustManager tm : tms) {
if (tm instanceof X509TrustManager) {
@@ -231,13 +231,13 @@ public void checkServerTrusted(X509Certificate[] chain, String authType)
}
}
- public String getCeritificateInfo() throws CertificateParsingException {
- X509Certificate cert = CertsManager.instance().getCertificate(account);
- return "sigalgName:" + cert.getSigAlgName() + " Type: "
- + cert.getType() + " Version: " + cert.getVersion()
- + " IssuerAlternative: " + cert.getIssuerAlternativeNames()
- + " NotAfter: " + cert.getNotAfter();
- }
+// public String getCeritificateInfo() throws CertificateParsingException {
+// X509Certificate cert = CertsManager.instance().getCertificate(account);
+// return "sigalgName:" + cert.getSigAlgName() + " Type: "
+// + cert.getType() + " Version: " + cert.getVersion()
+// + " IssuerAlternative: " + cert.getIssuerAlternativeNames()
+// + " NotAfter: " + cert.getNotAfter();
+// }
/**
* Interface for checking if a hostname matches the names stored inside the server's X.509 certificate
@@ -259,26 +259,38 @@ private void customCheck(List chain, String authType)
certsChain = ImmutableList.copyOf(chain);
- X509Certificate cert = chain.get(0);
- X509Certificate savedCert = CertsManager.instance().getCertificate(account);
- if (savedCert == null) {
- Log.d(DEBUG_TAG, "no saved cert for " + account.server);
- reason = SslFailureReason.CERT_NOT_TRUSTED;
- throw new CertificateException();
- } else if (savedCert.equals(cert)) {
- // The user has confirmed to trust this certificate
- Log.d(DEBUG_TAG, "the cert of " + account.server + " is trusted");
- return;
- } else {
- // The certificate is different from the one user confirmed to trust,
- // This may be either:
- // 1. The server admin has changed its cert
- // 2. The user is under security attack
- Log.d(DEBUG_TAG, "the cert of " + account.server + " has changed");
- reason = SslFailureReason.CERT_CHANGED;
- throw new CertificateException();
- }
+ ConcurrentAsyncTask.submit(new Runnable() {
+ @Override
+ public void run() {
+
+ try {
+ X509Certificate cert = chain.get(0);
+
+ X509Certificate savedCert = CertsManager.instance().getCertificate(account);
+ if (savedCert == null) {
+ Log.d(DEBUG_TAG, "no saved cert for " + account.server);
+ reason = SslFailureReason.CERT_NOT_TRUSTED;
+ throw new CertificateException();
+ } else if (savedCert.equals(cert)) {
+ // The user has confirmed to trust this certificate
+ Log.d(DEBUG_TAG, "the cert of " + account.server + " is trusted");
+ return;
+ } else {
+ // The certificate is different from the one user confirmed to trust,
+ // This may be either:
+ // 1. The server admin has changed its cert
+ // 2. The user is under security attack
+ Log.d(DEBUG_TAG, "the cert of " + account.server + " has changed");
+ reason = SslFailureReason.CERT_CHANGED;
+ throw new CertificateException();
+ }
+ } catch (CertificateException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+
}
public X509Certificate[] getAcceptedIssuers() {
diff --git a/app/src/main/java/com/seafile/seadroid2/ui/account/AccountDetailActivity.java b/app/src/main/java/com/seafile/seadroid2/ui/account/AccountDetailActivity.java
index 32a896408..8ec108b8e 100644
--- a/app/src/main/java/com/seafile/seadroid2/ui/account/AccountDetailActivity.java
+++ b/app/src/main/java/com/seafile/seadroid2/ui/account/AccountDetailActivity.java
@@ -2,6 +2,7 @@
import android.app.Dialog;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
@@ -20,6 +21,7 @@
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.NavUtils;
import androidx.core.app.TaskStackBuilder;
@@ -229,21 +231,33 @@ private void onLoginException(Account account, SeafException err) {
if (err == SeafException.sslException) {
mAuthTokenInputLayout.setVisibility(View.GONE);
mRemDeviceCheckBox.setVisibility(View.GONE);
- SslConfirmDialog sslConfirmDialog = new SslConfirmDialog(account,
- new SslConfirmDialog.Listener() {
- @Override
- public void onAccepted(boolean rememberChoice) {
- CertsManager.instance().saveCertForAccount(account, rememberChoice);
- login();
- }
-
- @Override
- public void onRejected() {
- mStatusTv.setText(R.string.ssl_error);
- mLoginBtn.setEnabled(true);
- }
- });
- sslConfirmDialog.show(getSupportFragmentManager(), SslConfirmDialog.FRAGMENT_TAG);
+
+ MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
+ builder.setTitle(R.string.ssl_confirm_title);
+ builder.setMessage(getString(R.string.ssl_not_trusted,account.getServerHost()));
+ builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ }
+ });
+ builder.create().show();
+
+// SslConfirmDialog sslConfirmDialog = new SslConfirmDialog(account,
+// new SslConfirmDialog.Listener() {
+// @Override
+// public void onAccepted(boolean rememberChoice) {
+// CertsManager.instance().saveCertForAccount(account, rememberChoice);
+// login();
+// }
+//
+// @Override
+// public void onRejected() {
+// mStatusTv.setText(R.string.ssl_error);
+// mLoginBtn.setEnabled(true);
+// }
+// });
+// sslConfirmDialog.show(getSupportFragmentManager(), SslConfirmDialog.FRAGMENT_TAG);
} else if (err == SeafException.twoFactorAuthTokenMissing) {
// show auth token input box
mAuthTokenInputLayout.setVisibility(View.VISIBLE);
diff --git a/app/src/main/java/com/seafile/seadroid2/ui/account/AccountViewModel.java b/app/src/main/java/com/seafile/seadroid2/ui/account/AccountViewModel.java
index 8185c7b6f..0a0aa3b02 100644
--- a/app/src/main/java/com/seafile/seadroid2/ui/account/AccountViewModel.java
+++ b/app/src/main/java/com/seafile/seadroid2/ui/account/AccountViewModel.java
@@ -14,7 +14,7 @@
import com.seafile.seadroid2.framework.data.ServerInfo;
import com.seafile.seadroid2.framework.data.model.TokenModel;
import com.seafile.seadroid2.framework.data.model.server.ServerInfoModel;
-import com.seafile.seadroid2.framework.http.IO;
+import com.seafile.seadroid2.framework.http.HttpIO;
import com.seafile.seadroid2.framework.util.AccountUtils;
import com.seafile.seadroid2.framework.util.DeviceIdManager;
import com.seafile.seadroid2.ui.base.viewmodel.BaseViewModel;
@@ -59,7 +59,7 @@ public void loadAccountInfo(Account loginAccount, String authToken) {
getRefreshLiveData().setValue(true);
loginAccount.token = authToken;
- Single single = IO.getInstanceByAccount(loginAccount).execute(AccountService.class).getAccountInfo();
+ Single single = HttpIO.getInstanceByAccount(loginAccount).execute(AccountService.class).getAccountInfo();
addSingleDisposable(single, new Consumer() {
@Override
public void accept(AccountInfo accountInfo) throws Exception {
@@ -108,14 +108,8 @@ public void subscribe(SingleEmitter emitter) throws Exception {
tempAccount.token = tokenModel.token;
}
- //note this:
- //the token to be updated here, because the user is logged in successfully
- //but don't use "IO.getLoggedInAccountInstance();"
- //because not set up an Android Account yet.
- IO.updateInstanceByAccount(tempAccount);
-
//
- retrofit2.Response accountInfoResponse = IO
+ retrofit2.Response accountInfoResponse = HttpIO
.getInstanceByAccount(tempAccount) //Still use it that way
.execute(AccountService.class)
.getAccountInfoCall()
@@ -189,19 +183,16 @@ private Call getLoginCall(Account tempAccount, String pwd, String to
Map requestBody = generateRequestBody(body);
- //
- IO.removeInstanceByAccount(tempAccount);
-
- return IO.newInstanceByAccount(tempAccount).execute(AccountService.class).login(headers, requestBody);
+ return HttpIO.getInstanceByAccount(tempAccount).execute(AccountService.class).login(headers, requestBody);
}
public void getServerInfo() {
getRefreshLiveData().setValue(true);
- Single serverSingle = IO.getInstanceWithLoggedIn().execute(MainService.class).getServerInfo();
+ Single serverSingle = HttpIO.getCurrentInstance().execute(MainService.class).getServerInfo();
addSingleDisposable(serverSingle, new Consumer() {
@Override
- public void accept(ServerInfoModel serverInfoModel) throws Exception {
+ public void accept(ServerInfoModel serverInfoModel) {
Account account = SupportAccountManager.getInstance().getCurrentAccount();
if (account == null) {
diff --git a/app/src/main/java/com/seafile/seadroid2/ui/account/SeafileAuthenticatorActivity.java b/app/src/main/java/com/seafile/seadroid2/ui/account/SeafileAuthenticatorActivity.java
index 543c8fd59..9c5c25152 100644
--- a/app/src/main/java/com/seafile/seadroid2/ui/account/SeafileAuthenticatorActivity.java
+++ b/app/src/main/java/com/seafile/seadroid2/ui/account/SeafileAuthenticatorActivity.java
@@ -18,25 +18,31 @@
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ComponentActivity;
import androidx.core.app.NavUtils;
import androidx.core.app.TaskStackBuilder;
+import androidx.preference.Preference;
import com.blankj.utilcode.util.ToastUtils;
import com.google.firebase.analytics.FirebaseAnalytics;
import com.seafile.seadroid2.R;
import com.seafile.seadroid2.account.Authenticator;
import com.seafile.seadroid2.account.SupportAccountManager;
+import com.seafile.seadroid2.framework.datastore.sp.SettingsManager;
import com.seafile.seadroid2.framework.util.Objs;
+import com.seafile.seadroid2.framework.util.SLogs;
import com.seafile.seadroid2.ui.WidgetUtils;
import com.seafile.seadroid2.ui.camera_upload.CameraUploadManager;
import com.seafile.seadroid2.config.Constants;
import com.seafile.seadroid2.ui.markdown.MarkdownActivity;
import com.seafile.seadroid2.ui.repo.RepoQuickFragment;
+import com.seafile.seadroid2.ui.webview.SeaWebViewActivity;
import java.io.File;
+import java.util.Locale;
/**
* The Authenticator activity.
@@ -78,12 +84,22 @@ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.account_create_type_select);
+
+ String country = Locale.getDefault().getCountry();
+ String language = Locale.getDefault().getLanguage();
+ boolean isZH = TextUtils.equals("CN", country) || TextUtils.equals("zh", language);
+
String[] array = getResources().getStringArray(R.array.choose_server_array);
- String[] strArray = new String[1 + array.length];
- strArray[0] = getString(R.string.server_name_top);
- for (int i = 0; i < array.length; i++) {
- strArray[i + 1] = array[i];
+ String[] strArray;
+ if (isZH) {
+ strArray = new String[1 + array.length];
+ strArray[0] = getString(R.string.server_name_top);
+ System.arraycopy(array, 0, strArray, 1, array.length);
+ } else {
+ strArray = new String[array.length];
+ System.arraycopy(array, 0, strArray, 0, array.length);
}
+
ArrayAdapter listAdapter = new ArrayAdapter<>(this, R.layout.list_item_authenticator, strArray);
ListView listView = (ListView) findViewById(R.id.account_create_list);
listView.setAdapter(listAdapter);
@@ -91,11 +107,15 @@ public void onCreate(Bundle savedInstanceState) {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
Intent intent = null;
+
+ if (!isZH) {
+ id++;
+ }
+
if (id == SEACLOUD_CC) {
intent = new Intent(SeafileAuthenticatorActivity.this, AccountDetailActivity.class);
intent.putExtras(getIntent());
intent.putExtra(SeafileAuthenticatorActivity.ARG_SERVER_URI, getString(R.string.server_url_seacloud));
-
} else if (id == SINGLE_SIGN_ON_LOGIN) {
intent = new Intent(SeafileAuthenticatorActivity.this, SingleSignOnActivity.class);
intent.putExtras(getIntent());
@@ -104,6 +124,7 @@ public void onItemClick(AdapterView> parent, View view, int position, long id)
intent.putExtras(getIntent());
}
+
if (intent != null) {
activityLauncher.launch(intent);
}
@@ -212,7 +233,7 @@ public void onActivityResult(ActivityResult o) {
});
private void finishLogin(Intent intent) {
- Log.d(DEBUG_TAG, "finishLogin");
+ SLogs.d(DEBUG_TAG, "finishLogin");
//firebase - event -login
Bundle eventBundle = new Bundle();
diff --git a/app/src/main/java/com/seafile/seadroid2/ui/account/SingleSignOnAuthorizeActivity.java b/app/src/main/java/com/seafile/seadroid2/ui/account/SingleSignOnAuthorizeActivity.java
index cad07407f..a4e616ed8 100644
--- a/app/src/main/java/com/seafile/seadroid2/ui/account/SingleSignOnAuthorizeActivity.java
+++ b/app/src/main/java/com/seafile/seadroid2/ui/account/SingleSignOnAuthorizeActivity.java
@@ -2,6 +2,7 @@
import android.annotation.SuppressLint;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -26,6 +27,7 @@
import android.widget.LinearLayout;
import com.blankj.utilcode.util.ToastUtils;
+import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.seafile.seadroid2.R;
import com.seafile.seadroid2.SeadroidApplication;
import com.seafile.seadroid2.SeafException;
@@ -235,33 +237,49 @@ public void onReceivedError(WebView view, int errorCode, String description, Str
@Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
Log.d(DEBUG_TAG, "onReceivedSslError " + error.getCertificate().toString());
- final Account account = new Account(serverUrl, null, null, null, null, false);
- SslCertificate sslCert = error.getCertificate();
- X509Certificate savedCert = CertsManager.instance().getCertificate(account);
-
- if (Utils.isSameCert(sslCert, savedCert)) {
- Log.d(DEBUG_TAG, "trust this cert");
- handler.proceed();
- } else {
- Log.d(DEBUG_TAG, "cert is not trusted");
- SslConfirmDialog dialog = new SslConfirmDialog(account,
- Utils.getX509CertFromSslCertHack(sslCert),
- new SslConfirmDialog.Listener() {
- @Override
- public void onAccepted(boolean rememberChoice) {
- CertsManager.instance().saveCertForAccount(account, rememberChoice);
- // Ignore SSL certificate validate
- handler.proceed();
- }
-
- @Override
- public void onRejected() {
- displaySSLError();
- handler.cancel();
- }
- });
- dialog.show(getSupportFragmentManager(), SslConfirmDialog.FRAGMENT_TAG);
- }
+
+ MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(SingleSignOnAuthorizeActivity.this);
+ builder.setTitle(R.string.ssl_confirm_title);
+ builder.setMessage(getString(R.string.ssl_not_trusted, serverUrl));
+ builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ handler.cancel();
+ displaySSLError();
+ dialog.dismiss();
+ }
+ });
+ builder.create().show();
+
+// final Account account = new Account(serverUrl, null, null, null, null, false);
+// SslCertificate sslCert = error.getCertificate();
+//
+// //todo notice main thread
+// X509Certificate savedCert = CertsManager.instance().getCertificate(account);
+//
+// if (Utils.isSameCert(sslCert, savedCert)) {
+// Log.d(DEBUG_TAG, "trust this cert");
+// handler.proceed();
+// } else {
+// Log.d(DEBUG_TAG, "cert is not trusted");
+// SslConfirmDialog dialog = new SslConfirmDialog(account,
+// Utils.getX509CertFromSslCertHack(sslCert),
+// new SslConfirmDialog.Listener() {
+// @Override
+// public void onAccepted(boolean rememberChoice) {
+// CertsManager.instance().saveCertForAccount(account, rememberChoice);
+// // Ignore SSL certificate validate
+// handler.proceed();
+// }
+//
+// @Override
+// public void onRejected() {
+// displaySSLError();
+// handler.cancel();
+// }
+// });
+// dialog.show(getSupportFragmentManager(), SslConfirmDialog.FRAGMENT_TAG);
+// }
}
@Override
diff --git a/app/src/main/java/com/seafile/seadroid2/ui/account/adapter/AccountAdapter.java b/app/src/main/java/com/seafile/seadroid2/ui/account/adapter/AccountAdapter.java
index d3ba3826c..b1bdf89d0 100644
--- a/app/src/main/java/com/seafile/seadroid2/ui/account/adapter/AccountAdapter.java
+++ b/app/src/main/java/com/seafile/seadroid2/ui/account/adapter/AccountAdapter.java
@@ -9,11 +9,11 @@
import android.widget.ImageView;
import android.widget.TextView;
-import com.bumptech.glide.Glide;
import com.google.common.collect.Lists;
import com.seafile.seadroid2.R;
import com.seafile.seadroid2.account.Account;
import com.seafile.seadroid2.config.GlideLoadConfig;
+import com.seafile.seadroid2.framework.util.GlideApp;
import java.util.ArrayList;
import java.util.List;
@@ -95,9 +95,9 @@ public View getView(int position, View convertView, ViewGroup parent) {
if (TextUtils.isEmpty(account.avatar_url)) {
viewHolder.icon.setImageResource(com.seafile.seadroid2.R.drawable.default_avatar);
} else {
- Glide.with(context)
- .load(GlideLoadConfig.getGlideUrl(account.avatar_url))
- .apply(GlideLoadConfig.getDefaultAvatarOptions())
+ GlideApp.with(context)
+ .load(account.avatar_url)
+ .apply(GlideLoadConfig.getAvatarOptions())
.into(viewHolder.icon);
}
diff --git a/app/src/main/java/com/seafile/seadroid2/ui/activities/ActivityAdapter.java b/app/src/main/java/com/seafile/seadroid2/ui/activities/ActivityAdapter.java
index fe0a7572b..e40fcaabe 100644
--- a/app/src/main/java/com/seafile/seadroid2/ui/activities/ActivityAdapter.java
+++ b/app/src/main/java/com/seafile/seadroid2/ui/activities/ActivityAdapter.java
@@ -10,7 +10,6 @@
import androidx.recyclerview.widget.RecyclerView;
import com.blankj.utilcode.util.SpanUtils;
-import com.bumptech.glide.Glide;
import com.seafile.seadroid2.R;
import com.seafile.seadroid2.config.AbsLayoutItemType;
import com.seafile.seadroid2.config.GlideLoadConfig;
@@ -19,6 +18,7 @@
import com.seafile.seadroid2.framework.data.model.BaseModel;
import com.seafile.seadroid2.framework.data.model.GroupItemModel;
import com.seafile.seadroid2.framework.data.model.activities.ActivityModel;
+import com.seafile.seadroid2.framework.util.GlideApp;
import com.seafile.seadroid2.framework.util.SystemSwitchUtils;
import com.seafile.seadroid2.ui.base.adapter.BaseMultiAdapter;
import com.seafile.seadroid2.ui.viewholder.GroupItemViewHolder;
@@ -95,9 +95,9 @@ private void onBindActivity(ActivityViewHolder holder, ActivityModel model) {
}
}
- Glide.with(getContext())
- .load(GlideLoadConfig.getGlideUrl(model.avatar_url))
- .apply(GlideLoadConfig.getOptions())
+ GlideApp.with(getContext())
+ .load(model.avatar_url)
+ .apply(GlideLoadConfig.getAvatarOptions())
.into(holder.binding.itemAvatar);
}
}
diff --git a/app/src/main/java/com/seafile/seadroid2/ui/activities/ActivityViewModel.java b/app/src/main/java/com/seafile/seadroid2/ui/activities/ActivityViewModel.java
index 8e85f1021..c657b7e08 100644
--- a/app/src/main/java/com/seafile/seadroid2/ui/activities/ActivityViewModel.java
+++ b/app/src/main/java/com/seafile/seadroid2/ui/activities/ActivityViewModel.java
@@ -3,15 +3,12 @@
import androidx.lifecycle.MutableLiveData;
import com.blankj.utilcode.util.CollectionUtils;
-import com.blankj.utilcode.util.NetworkUtils;
-import com.blankj.utilcode.util.ToastUtils;
-import com.seafile.seadroid2.R;
import com.seafile.seadroid2.SeafException;
import com.seafile.seadroid2.framework.data.db.AppDatabase;
import com.seafile.seadroid2.framework.data.db.entities.RepoModel;
import com.seafile.seadroid2.ui.base.viewmodel.BaseViewModel;
import com.seafile.seadroid2.enums.OpType;
-import com.seafile.seadroid2.framework.http.IO;
+import com.seafile.seadroid2.framework.http.HttpIO;
import com.seafile.seadroid2.framework.data.model.activities.ActivityModel;
import com.seafile.seadroid2.framework.data.model.activities.ActivityWrapperModel;
import com.seafile.seadroid2.framework.util.SLogs;
@@ -20,7 +17,6 @@
import io.reactivex.Single;
import io.reactivex.functions.Consumer;
-import kotlin.Pair;
public class ActivityViewModel extends BaseViewModel {
private final MutableLiveData> listLiveData = new MutableLiveData<>();
@@ -52,7 +48,7 @@ public void accept(Throwable throwable) throws Exception {
public void loadAllData(int page) {
getRefreshLiveData().setValue(true);
- Single flowable = IO.getInstanceWithLoggedIn().execute(ActivityService.class).getActivities(page);
+ Single flowable = HttpIO.getCurrentInstance().execute(ActivityService.class).getActivities(page);
addSingleDisposable(flowable, new Consumer() {
@Override
public void accept(ActivityWrapperModel wrapperModel) throws Exception {
diff --git a/app/src/main/java/com/seafile/seadroid2/ui/base/fragment/BaseFragment.java b/app/src/main/java/com/seafile/seadroid2/ui/base/fragment/BaseFragment.java
index fc1de61a4..3de25e4de 100644
--- a/app/src/main/java/com/seafile/seadroid2/ui/base/fragment/BaseFragment.java
+++ b/app/src/main/java/com/seafile/seadroid2/ui/base/fragment/BaseFragment.java
@@ -18,7 +18,7 @@ public void onResume() {
isFirstLoadData = false;
onFirstResume();
} else {
- onNonFirstResume();
+ onOtherResume();
}
}
@@ -26,7 +26,7 @@ public void onFirstResume() {
}
- public void onNonFirstResume() {
+ public void onOtherResume() {
}
}
diff --git a/app/src/main/java/com/seafile/seadroid2/ui/base/viewmodel/BaseViewModel.java b/app/src/main/java/com/seafile/seadroid2/ui/base/viewmodel/BaseViewModel.java
index ce5dee2b2..c9e086bac 100644
--- a/app/src/main/java/com/seafile/seadroid2/ui/base/viewmodel/BaseViewModel.java
+++ b/app/src/main/java/com/seafile/seadroid2/ui/base/viewmodel/BaseViewModel.java
@@ -14,7 +14,7 @@
import com.seafile.seadroid2.SeadroidApplication;
import com.seafile.seadroid2.SeafException;
import com.seafile.seadroid2.framework.data.model.ResultModel;
-import com.seafile.seadroid2.framework.http.IO;
+import com.seafile.seadroid2.framework.http.HttpIO;
import com.seafile.seadroid2.framework.util.SLogs;
import com.seafile.seadroid2.framework.util.Utils;
import com.seafile.seadroid2.ui.account.AccountService;
@@ -23,13 +23,14 @@
import java.io.IOException;
import java.io.UnsupportedEncodingException;
-import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Map;
+import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLPeerUnverifiedException;
import io.reactivex.Completable;
import io.reactivex.Flowable;
@@ -41,7 +42,6 @@
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import kotlin.Pair;
-import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
@@ -77,7 +77,7 @@ public void closeRefresh() {
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
public void completeRemoteWipe() {
- Single