Browse Source

SSO: support of parameter v2, which allows to have multiple values for same key

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
tobiasKaminsky 4 years ago
parent
commit
561cff8157

+ 61 - 0
src/androidTest/java/com/nextcloud/sso/InputStreamBinderTest.kt

@@ -0,0 +1,61 @@
+/*
+ *
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2021 Tobias Kaminsky
+ * Copyright (C) 2021 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package com.nextcloud.sso
+
+import com.nextcloud.android.sso.InputStreamBinder
+import junit.framework.Assert.assertEquals
+import org.junit.Test
+
+class InputStreamBinderTest {
+    @Test
+    fun convertMapToNVP() {
+        val source = mutableMapOf<String, String>()
+        source["quality"] = "1024p"
+        source["someOtherParameter"] = "parameterValue"
+        source["duplicate"] = "1"
+        source["duplicate"] = "2" // this overwrites previous parameter
+
+        val output = InputStreamBinder.convertMapToNVP(source)
+
+        assertEquals(source.size, output.size)
+        assertEquals("1024p", output[0].value)
+        assertEquals("parameterValue", output[1].value)
+        assertEquals("2", output[2].value)
+    }
+
+    @Test
+    fun convertListToNVP() {
+        val source = mutableListOf<android.util.Pair<String, String>>()
+        source.add(android.util.Pair("quality", "1024p"))
+        source.add(android.util.Pair("someOtherParameter", "parameterValue"))
+        source.add(android.util.Pair("duplicate", "1"))
+        source.add(android.util.Pair("duplicate", "2")) // here we can have same parameter multiple times
+
+        val output = InputStreamBinder.convertListToNVP(source)
+
+        assertEquals(source.size, output.size)
+        assertEquals("1024p", output[0].value)
+        assertEquals("parameterValue", output[1].value)
+        assertEquals("1", output[2].value)
+        assertEquals("2", output[3].value)
+    }
+}

+ 28 - 3
src/main/java/com/nextcloud/android/sso/InputStreamBinder.java

@@ -32,6 +32,7 @@ import android.os.Binder;
 import android.os.ParcelFileDescriptor;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Pair;
 
 import com.nextcloud.android.sso.aidl.IInputStreamService;
 import com.nextcloud.android.sso.aidl.NextcloudRequest;
@@ -70,9 +71,12 @@ import java.io.InputStreamReader;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
+import androidx.annotation.VisibleForTesting;
+
 import static com.nextcloud.android.sso.Constants.DELIMITER;
 import static com.nextcloud.android.sso.Constants.EXCEPTION_ACCOUNT_NOT_FOUND;
 import static com.nextcloud.android.sso.Constants.EXCEPTION_HTTP_REQUEST_FAILED;
@@ -331,7 +335,11 @@ public class InputStreamBinder extends IInputStreamService.Stub {
 
         HttpMethodBase method = buildMethod(request, client.getBaseUri(), requestBodyInputStream);
 
-        method.setQueryString(convertMapToNVP(request.getParameter()));
+        if (!request.getParameterV2().isEmpty()) {
+            method.setQueryString(convertListToNVP(request.getParameterV2()));
+        } else {
+            method.setQueryString(convertMapToNVP(request.getParameter()));
+        }
         method.addRequestHeader("OCS-APIREQUEST", "true");
 
         for (Map.Entry<String, List<String>> header : request.getHeader().entrySet()) {
@@ -394,7 +402,12 @@ public class InputStreamBinder extends IInputStreamService.Stub {
 
         HttpMethodBase method = buildMethod(request, client.getBaseUri(), requestBodyInputStream);
 
-        method.setQueryString(convertMapToNVP(request.getParameter()));
+        if (!request.getParameterV2().isEmpty()) {
+            method.setQueryString(convertListToNVP(request.getParameterV2()));
+        } else {
+            method.setQueryString(convertMapToNVP(request.getParameter()));
+        }
+
         method.addRequestHeader("OCS-APIREQUEST", "true");
 
         for (Map.Entry<String, List<String>> header : request.getHeader().entrySet()) {
@@ -482,7 +495,8 @@ public class InputStreamBinder extends IInputStreamService.Stub {
         }
     }
 
-    private static NameValuePair[] convertMapToNVP(Map<String, String> map) {
+    @VisibleForTesting
+    public static NameValuePair[] convertMapToNVP(Map<String, String> map) {
         NameValuePair[] nvp = new NameValuePair[map.size()];
         int i = 0;
         for (String key : map.keySet()) {
@@ -491,4 +505,15 @@ public class InputStreamBinder extends IInputStreamService.Stub {
         }
         return nvp;
     }
+
+    @VisibleForTesting
+    public static NameValuePair[] convertListToNVP(Collection<Pair<String, String>> list) {
+        NameValuePair[] nvp = new NameValuePair[list.size()];
+        int i = 0;
+        for (Pair<String, String> pair : list) {
+            nvp[i] = new NameValuePair(pair.first, pair.second);
+            i++;
+        }
+        return nvp;
+    }
 }

+ 31 - 0
src/main/java/com/nextcloud/android/sso/aidl/NextcloudRequest.java

@@ -1,3 +1,25 @@
+/*
+ *
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2021 Tobias Kaminsky
+ * Copyright (C) 2021 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
 /*
  *  Nextcloud SingleSignOn
  *
@@ -19,8 +41,12 @@
 
 package com.nextcloud.android.sso.aidl;
 
+import android.util.Pair;
+
 import java.io.Serializable;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
@@ -31,6 +57,7 @@ public class NextcloudRequest implements Serializable {
     private String method;
     private Map<String, List<String>> header = new HashMap<>();
     private Map<String, String> parameter = new HashMap<>();
+    private final Collection<Pair<String, String>> parameterV2 = new LinkedList<>();
     private String requestBody;
     private String url;
     private String token;
@@ -144,4 +171,8 @@ public class NextcloudRequest implements Serializable {
     public boolean isFollowRedirects() {
         return this.followRedirects;
     }
+
+    public Collection<Pair<String, String>> getParameterV2() {
+        return parameterV2;
+    }
 }