diff --git a/library/build.gradle b/library/build.gradle index f232044c0dad6ca6995b131e7c724dc40bc27b17..28b35f367cf6a613da53bca737c671f6f965b106 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -47,7 +47,7 @@ configurations { def versionMajor = 2 def versionMinor = 0 -def versionPatch = 3 +def versionPatch = 4 def upstreamVersion = "2.17" def releasePatch = "release" def libName = "Nextcloud-Android-Library" diff --git a/library/src/main/java/com/owncloud/android/lib/common/OwnCloudClient.java b/library/src/main/java/com/owncloud/android/lib/common/OwnCloudClient.java index 02572cd58e332987cec935672e712a175e834623..57735285859fee78f2338f041d761e19726098f1 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/OwnCloudClient.java +++ b/library/src/main/java/com/owncloud/android/lib/common/OwnCloudClient.java @@ -27,6 +27,8 @@ package com.owncloud.android.lib.common; import android.net.Uri; +import androidx.annotation.IntDef; + import com.nextcloud.common.DNSCache; import com.nextcloud.common.NextcloudUriDelegate; import com.owncloud.android.lib.common.accounts.AccountUtils; @@ -47,7 +49,6 @@ import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.httpclient.params.HttpParams; -import androidx.annotation.IntDef; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Retention; @@ -68,16 +69,17 @@ public class OwnCloudClient extends HttpClient { private static final boolean PARAM_SINGLE_COOKIE_HEADER_VALUE = true; private static final String PARAM_PROTOCOL_VERSION = "http.protocol.version"; - private static byte[] sExhaustBuffer = new byte[1024]; + private static final byte[] sExhaustBuffer = new byte[1024]; + private static final String HEADER_NAME_COOKIE = "Cookie"; private static int sInstanceCounter = 0; private final NextcloudUriDelegate nextcloudUriDelegate; private boolean followRedirects = true; private OwnCloudCredentials credentials = null; - private int mInstanceNumber; + private final int mInstanceNumber; private boolean shouldResetCookie = false; - private @CookiesPolicy int cookiesPolicy; + private final @CookiesPolicy int cookiesPolicy; public static final int USE_COOKIES = 0; public static final int DONT_USE_COOKIES = 1; @@ -213,18 +215,32 @@ public class OwnCloudClient extends HttpClient { method.setFollowRedirects(false); /* - * We want to clear cookies here specifically for Notes API. - * Indeed, The Notes server APIs have the Cross-Origin Resource Sharing (CORS) flag, + * We want to ensure cookies are not sent with requests to APIs with CORS enabled. + * These server APIs have the Cross-Origin Resource Sharing (CORS) flag, * so are not able to deal with cookie sessions. + * + * Notes app uses [OwnCloudClient] to sync notes, using /e/OS's Account Manager's + * InputStreamBinder class via AIDL communication. + * + * For creating the OwnCloudClient for Notes, Account Manager supplies + * DONT_USE_COOKIES as cookiesPolicy to exclude cookies from the HTTP requests. */ - if (cookiesPolicy == DONT_USE_COOKIES && method.getURI().getEscapedURI().contains("/apps/notes/")) { - getState().clearCookies(); + CookiePolicySnapshot cookiePolicySnapshot = null; + + if (cookiesPolicy == DONT_USE_COOKIES) { + cookiePolicySnapshot = overrideCookiePolicy(method, CookiePolicy.IGNORE_COOKIES); + removeCookieHeader(method); } - boolean cookiePassedOnRequest = getState().getCookies().length > 0; + boolean cookiePassedOnRequest = cookiesPolicy == USE_COOKIES && + (hasCookieRequestHeader(method) || getState().getCookies().length > 0); int status = super.executeMethod(method); + if (cookiePolicySnapshot != null) { + cookiePolicySnapshot.restore(method); + } + if (status >= 500 && status < 600 && DNSCache.isIPV6First(hostname)) { return retryMethodWithIPv4(method, hostname); } @@ -276,6 +292,7 @@ public class OwnCloudClient extends HttpClient { shouldResetCookie = true; getState().clearCookies(); + removeCookieHeader(method); return executeMethod(method); } @@ -527,4 +544,33 @@ public class OwnCloudClient extends HttpClient { public @CookiesPolicy int getCookiesPolicy() { return cookiesPolicy; } + + private CookiePolicySnapshot overrideCookiePolicy(HttpMethod method, String newPolicy) { + HttpParams params = method.getParams(); + Object previousPolicy = params.getParameter(HttpMethodParams.COOKIE_POLICY); + CookiePolicySnapshot snapshot = new CookiePolicySnapshot(previousPolicy); + params.setParameter(HttpMethodParams.COOKIE_POLICY, newPolicy); + return snapshot; + } + + private boolean hasCookieRequestHeader(HttpMethod method) { + return method.getRequestHeader(HEADER_NAME_COOKIE) != null; + } + + private void removeCookieHeader(HttpMethod method) { + method.removeRequestHeader(HEADER_NAME_COOKIE); + } + + private static final class CookiePolicySnapshot { + private final Object previousPolicy; + + CookiePolicySnapshot(Object previousPolicy) { + this.previousPolicy = previousPolicy; + } + + void restore(HttpMethod method) { + HttpParams params = method.getParams(); + params.setParameter(HttpMethodParams.COOKIE_POLICY, previousPolicy); + } + } }