From c3f24e817e5f94b08b7e416ef99ef03ed3b61d3a Mon Sep 17 00:00:00 2001 From: masensio Date: Mon, 5 Oct 2015 11:23:39 +0200 Subject: [PATCH 01/21] Add method to know if server supports search users function --- .../android/lib/resources/status/OwnCloudVersion.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/com/owncloud/android/lib/resources/status/OwnCloudVersion.java b/src/com/owncloud/android/lib/resources/status/OwnCloudVersion.java index f3da9f47..8c30c7ab 100644 --- a/src/com/owncloud/android/lib/resources/status/OwnCloudVersion.java +++ b/src/com/owncloud/android/lib/resources/status/OwnCloudVersion.java @@ -43,6 +43,8 @@ public class OwnCloudVersion implements Comparable { public static final int MINIMUM_SERVER_VERSION_FOR_REMOTE_THUMBNAILS = 0x07080000; // 7.8.0 + public static final int MINIMUM_VERSION_FOR_SEARCHING_USERS = 0x08020000; //8.2 + public static final int VERSION_8 = 0x08000000; // 8.0 private static final int MAX_DOTS = 3; @@ -138,6 +140,10 @@ public class OwnCloudVersion implements Comparable { public boolean isAfter8Version(){ return (mVersion >= VERSION_8); } + + public boolean isSearchUsersSupported() { + return (mVersion >= MINIMUM_VERSION_FOR_SEARCHING_USERS); + } } From 0c6dfef90830476573ff84e8a58517288fc393dc Mon Sep 17 00:00:00 2001 From: masensio Date: Thu, 8 Oct 2015 18:32:50 +0200 Subject: [PATCH 02/21] Add operation to get users from the server --- .../users/GetRemoteUsersOperation.java | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 src/com/owncloud/android/lib/resources/users/GetRemoteUsersOperation.java diff --git a/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOperation.java b/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOperation.java new file mode 100644 index 00000000..d590089f --- /dev/null +++ b/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOperation.java @@ -0,0 +1,166 @@ +/* ownCloud Android Library is available under MIT license + * Copyright (C) 2015 ownCloud Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.owncloud.android.lib.resources.users; + +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.operations.RemoteOperation; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.common.utils.Log_OC; + +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.http.HttpStatus; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.ArrayList; + +/** + * Created by masensio on 08/10/2015. + * + * Retrieves a list of users from the ownCloud server. Authentication is done by sending a Basic HTTP Authorization header. + * Syntax: ocs/v1.php/cloud/users + * HTTP method: GET + * url arguments: search - string, optional search string + * url arguments: limit - int, optional limit value + * url arguments: offset - int, optional offset value + * + * Status codes: + * 100 - successful + */ +public class GetRemoteUsersOperation extends RemoteOperation{ + + private static final String TAG = GetRemoteUserNameOperation.class.getSimpleName(); + + // OCS Route + private static final String OCS_ROUTE ="/ocs/v1.php/cloud/users?format=json"; + + // Arguments + private static final String PARAM_SEARCH = "search"; + private static final String PARAM_LIMIT = "limit"; + private static final String PARAM_OFFSET = "offset"; + + // JSON Node names + private static final String NODE_OCS = "ocs"; + private static final String NODE_META = "meta"; + private static final String NODE_STATUS = "status"; + private static final String NODE_STATUSCODE = "statuscode"; + private static final String NODE_MESSAGE = "message"; + private static final String NODE_DATA = "data"; + private static final String NODE_USERS = "users"; + + private ArrayList mUsers; // List of users + + private String mSearchString; + private int mLimit; + private int mOffset; + + /** + * Constructor + * + * @param searchString string for searching users, optional + * @param limit limit, optional + * @param offset offset, optional + */ + public GetRemoteUsersOperation(String searchString, int limit, int offset) { + mSearchString = searchString; + mLimit = limit; + mOffset = offset; + } + + @Override + protected RemoteOperationResult run(OwnCloudClient client) { + RemoteOperationResult result = null; + int status = -1; + GetMethod get = null; + + try{ + // Get Method + get = new GetMethod(client.getBaseUri() + OCS_ROUTE); + + // Add Parameters to Get Method + get.setQueryString(new NameValuePair[]{ + new NameValuePair(PARAM_SEARCH, mSearchString), + new NameValuePair(PARAM_LIMIT, String.valueOf(mLimit)), + new NameValuePair(PARAM_OFFSET, String.valueOf(mOffset)) + }); + + //¿? + get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE); + + status = client.executeMethod(get); + + if(isSuccess(status)) { + String response = get.getResponseBodyAsString(); + Log_OC.d(TAG, "Successful response: " + response); + + // Parse the response + JSONObject respJSON = new JSONObject(response); + JSONObject respOCS = respJSON.getJSONObject(NODE_OCS); + JSONObject respData = respOCS.getJSONObject(NODE_DATA); + JSONArray respUsers = respData.getJSONArray(NODE_USERS); + mUsers = new ArrayList(); + ArrayList data = new ArrayList(); // For result data + for(int i=0; i<= respUsers.length(); i++){ + JSONObject jsonUser = respUsers.getJSONObject(i); + String user = jsonUser.toString(); + mUsers.add(user); + data.add(user); + Log_OC.d(TAG, "*** USER : " + user); + } + + // Result + result = new RemoteOperationResult(true, status, get.getResponseHeaders()); + result.setData(data); + + Log_OC.d(TAG, "*** Get Users completed " ); + + } else { + result = new RemoteOperationResult(false, status, get.getResponseHeaders()); + String response = get.getResponseBodyAsString(); + Log_OC.e(TAG, "Failed response while getting users from the server "); + if (response != null) { + Log_OC.e(TAG, "*** status code: " + status + "; response message: " + response); + } else { + Log_OC.e(TAG, "*** status code: " + status); + } + } + + } catch (Exception e) { + result = new RemoteOperationResult(e); + Log_OC.e(TAG, "Exception while getting users", e); + + } finally { + if (get != null) { + get.releaseConnection(); + } + } + return result; + } + + private boolean isSuccess(int status) { + return (status == HttpStatus.SC_OK); + } +} From fa17c6947e03e09b0c675b260d6b7fb21d0e0c1a Mon Sep 17 00:00:00 2001 From: masensio Date: Fri, 9 Oct 2015 10:02:03 +0200 Subject: [PATCH 03/21] Remove unused constants --- .../android/lib/resources/users/GetRemoteUsersOperation.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOperation.java b/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOperation.java index d590089f..c7f708ea 100644 --- a/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOperation.java +++ b/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOperation.java @@ -64,10 +64,6 @@ public class GetRemoteUsersOperation extends RemoteOperation{ // JSON Node names private static final String NODE_OCS = "ocs"; - private static final String NODE_META = "meta"; - private static final String NODE_STATUS = "status"; - private static final String NODE_STATUSCODE = "statuscode"; - private static final String NODE_MESSAGE = "message"; private static final String NODE_DATA = "data"; private static final String NODE_USERS = "users"; From cea7054a3d94b484691c6b06fe1a1536b8a17911 Mon Sep 17 00:00:00 2001 From: masensio Date: Fri, 9 Oct 2015 12:29:23 +0200 Subject: [PATCH 04/21] Add Get Groups Operation to the library --- ...a => GetRemoteUsersOrGroupsOperation.java} | 55 ++++++++++++------- 1 file changed, 35 insertions(+), 20 deletions(-) rename src/com/owncloud/android/lib/resources/users/{GetRemoteUsersOperation.java => GetRemoteUsersOrGroupsOperation.java} (71%) diff --git a/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOperation.java b/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOrGroupsOperation.java similarity index 71% rename from src/com/owncloud/android/lib/resources/users/GetRemoteUsersOperation.java rename to src/com/owncloud/android/lib/resources/users/GetRemoteUsersOrGroupsOperation.java index c7f708ea..404e88a2 100644 --- a/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOperation.java +++ b/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOrGroupsOperation.java @@ -40,8 +40,10 @@ import java.util.ArrayList; /** * Created by masensio on 08/10/2015. * - * Retrieves a list of users from the ownCloud server. Authentication is done by sending a Basic HTTP Authorization header. - * Syntax: ocs/v1.php/cloud/users + * Retrieves a list of users or groups from the ownCloud server. + * Authentication is done by sending a Basic HTTP Authorization header. + * Syntax: ocs/v1.php/cloud/users (Users) + * ocs/v1.php/cloud/groups (Groups) * HTTP method: GET * url arguments: search - string, optional search string * url arguments: limit - int, optional limit value @@ -50,12 +52,13 @@ import java.util.ArrayList; * Status codes: * 100 - successful */ -public class GetRemoteUsersOperation extends RemoteOperation{ +public class GetRemoteUsersOrGroupsOperation extends RemoteOperation{ - private static final String TAG = GetRemoteUserNameOperation.class.getSimpleName(); + private static final String TAG = GetRemoteUsersOrGroupsOperation.class.getSimpleName(); - // OCS Route - private static final String OCS_ROUTE ="/ocs/v1.php/cloud/users?format=json"; + // OCS Routes + private static final String OCS_ROUTE_USERS ="/ocs/v1.php/cloud/users?format=json"; + private static final String OCS_ROUTE_GROUPS ="/ocs/v1.php/cloud/groups?format=json"; // Arguments private static final String PARAM_SEARCH = "search"; @@ -66,12 +69,14 @@ public class GetRemoteUsersOperation extends RemoteOperation{ private static final String NODE_OCS = "ocs"; private static final String NODE_DATA = "data"; private static final String NODE_USERS = "users"; + private static final String NODE_GROUPS = "groups"; - private ArrayList mUsers; // List of users + private ArrayList mNames; // List of users or groups private String mSearchString; private int mLimit; private int mOffset; + private boolean mGetGroup = false; /** * Constructor @@ -79,11 +84,14 @@ public class GetRemoteUsersOperation extends RemoteOperation{ * @param searchString string for searching users, optional * @param limit limit, optional * @param offset offset, optional + * @param getGroups true: for searching groups, false: for searching users */ - public GetRemoteUsersOperation(String searchString, int limit, int offset) { + public GetRemoteUsersOrGroupsOperation(String searchString, int limit, int offset, + boolean getGroups) { mSearchString = searchString; mLimit = limit; mOffset = offset; + mGetGroup = getGroups; } @Override @@ -92,9 +100,16 @@ public class GetRemoteUsersOperation extends RemoteOperation{ int status = -1; GetMethod get = null; + String ocs_route = OCS_ROUTE_USERS; + String nodeUsersOrGroups = NODE_USERS; + if(mGetGroup){ + ocs_route = OCS_ROUTE_GROUPS; + nodeUsersOrGroups = NODE_GROUPS; + } + try{ // Get Method - get = new GetMethod(client.getBaseUri() + OCS_ROUTE); + get = new GetMethod(client.getBaseUri() + ocs_route); // Add Parameters to Get Method get.setQueryString(new NameValuePair[]{ @@ -116,27 +131,27 @@ public class GetRemoteUsersOperation extends RemoteOperation{ JSONObject respJSON = new JSONObject(response); JSONObject respOCS = respJSON.getJSONObject(NODE_OCS); JSONObject respData = respOCS.getJSONObject(NODE_DATA); - JSONArray respUsers = respData.getJSONArray(NODE_USERS); - mUsers = new ArrayList(); + JSONArray respUsersOrGroups = respData.getJSONArray(nodeUsersOrGroups); + mNames = new ArrayList(); ArrayList data = new ArrayList(); // For result data - for(int i=0; i<= respUsers.length(); i++){ - JSONObject jsonUser = respUsers.getJSONObject(i); - String user = jsonUser.toString(); - mUsers.add(user); - data.add(user); - Log_OC.d(TAG, "*** USER : " + user); + for(int i=0; i<= respUsersOrGroups.length(); i++){ + JSONObject jsonUser = respUsersOrGroups.getJSONObject(i); + String name = jsonUser.toString(); + mNames.add(name); + data.add(name); + Log_OC.d(TAG, "*** "+ nodeUsersOrGroups + " : " + name); } // Result result = new RemoteOperationResult(true, status, get.getResponseHeaders()); result.setData(data); - Log_OC.d(TAG, "*** Get Users completed " ); + Log_OC.d(TAG, "*** Get Users or groups completed " ); } else { result = new RemoteOperationResult(false, status, get.getResponseHeaders()); String response = get.getResponseBodyAsString(); - Log_OC.e(TAG, "Failed response while getting users from the server "); + Log_OC.e(TAG, "Failed response while getting users/groups from the server "); if (response != null) { Log_OC.e(TAG, "*** status code: " + status + "; response message: " + response); } else { @@ -146,7 +161,7 @@ public class GetRemoteUsersOperation extends RemoteOperation{ } catch (Exception e) { result = new RemoteOperationResult(e); - Log_OC.e(TAG, "Exception while getting users", e); + Log_OC.e(TAG, "Exception while getting users/groups", e); } finally { if (get != null) { From d9eb3655fd27462fe879979289e26bf2e0e0f4ad Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Thu, 15 Oct 2015 09:24:06 +0200 Subject: [PATCH 05/21] Removed constrain to parse only public shares --- .../resources/shares/GetRemoteSharesForFileOperation.java | 6 ++++-- .../android/lib/resources/shares/ShareXMLParser.java | 4 +--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesForFileOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesForFileOperation.java index 37241844..1518b516 100644 --- a/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesForFileOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesForFileOperation.java @@ -117,8 +117,10 @@ public class GetRemoteSharesForFileOperation extends RemoteOperation { ArrayList sharesObjects = new ArrayList(); for (OCShare share: mShares) { // Build the link - if (( share.getShareLink() == null) && - (share.getToken().length() > 0)) { + if ( share.getShareType() == ShareType.PUBLIC_LINK && + share.getShareLink() == null && + share.getToken().length() > 0 + ) { String linkToken = ShareUtils.getSharingToken( client.getOwnCloudVersion()); share.setShareLink(client.getBaseUri() + linkToken + diff --git a/src/com/owncloud/android/lib/resources/shares/ShareXMLParser.java b/src/com/owncloud/android/lib/resources/shares/ShareXMLParser.java index b19d5772..cb984fd4 100644 --- a/src/com/owncloud/android/lib/resources/shares/ShareXMLParser.java +++ b/src/com/owncloud/android/lib/resources/shares/ShareXMLParser.java @@ -348,9 +348,7 @@ public class ShareXMLParser { } private boolean isValidShare(OCShare share) { - return ((share.getIdRemoteShared() > -1) && - (share.getShareType() == ShareType.PUBLIC_LINK) // at this moment we only care about public shares - ); + return (share.getIdRemoteShared() > -1); } private void fixPathForFolder(OCShare share) { From 0793d3fca79e45683c457a20c99d056bef8951ed Mon Sep 17 00:00:00 2001 From: masensio Date: Fri, 16 Oct 2015 11:00:41 +0200 Subject: [PATCH 06/21] Fix NODE_SHARE_WITH_DISPLAY_NAME tag in ShareXMLParser --- .../owncloud/android/lib/resources/shares/ShareXMLParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/owncloud/android/lib/resources/shares/ShareXMLParser.java b/src/com/owncloud/android/lib/resources/shares/ShareXMLParser.java index cb984fd4..8189eac0 100644 --- a/src/com/owncloud/android/lib/resources/shares/ShareXMLParser.java +++ b/src/com/owncloud/android/lib/resources/shares/ShareXMLParser.java @@ -75,7 +75,7 @@ public class ShareXMLParser { private static final String NODE_TOKEN = "token"; private static final String NODE_STORAGE = "storage"; private static final String NODE_MAIL_SEND = "mail_send"; - private static final String NODE_SHARE_WITH_DISPLAY_NAME = "share_with_display_name"; + private static final String NODE_SHARE_WITH_DISPLAY_NAME = "share_with_displayname"; private static final String NODE_URL = "url"; From 3b3b992a79f529c4aadf23800452038b28207578 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Mon, 19 Oct 2015 15:06:52 +0200 Subject: [PATCH 07/21] Get users or groups available to share with via SHAREE API --- .../users/GetRemoteUserNameOperation.java | 2 +- .../GetRemoteUsersOrGroupsOperation.java | 110 +++++++++++------- 2 files changed, 66 insertions(+), 46 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/users/GetRemoteUserNameOperation.java b/src/com/owncloud/android/lib/resources/users/GetRemoteUserNameOperation.java index cecd639f..d6b85a7a 100644 --- a/src/com/owncloud/android/lib/resources/users/GetRemoteUserNameOperation.java +++ b/src/com/owncloud/android/lib/resources/users/GetRemoteUserNameOperation.java @@ -50,7 +50,7 @@ public class GetRemoteUserNameOperation extends RemoteOperation { private static final String TAG = GetRemoteUserNameOperation.class.getSimpleName(); // OCS Route - private static final String OCS_ROUTE ="/index.php/ocs/cloud/user?format=json"; + private static final String OCS_ROUTE ="/index.php/ocs/cloud/user?format=json"; // JSON Node names private static final String NODE_OCS = "ocs"; diff --git a/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOrGroupsOperation.java b/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOrGroupsOperation.java index 404e88a2..122b488a 100644 --- a/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOrGroupsOperation.java +++ b/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOrGroupsOperation.java @@ -1,4 +1,7 @@ /* ownCloud Android Library is available under MIT license + * + * @author masensio + * @author David A. Velasco * Copyright (C) 2015 ownCloud Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -24,12 +27,14 @@ package com.owncloud.android.lib.resources.users; +import android.net.Uri; +import android.util.Pair; + import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.utils.Log_OC; -import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.http.HttpStatus; import org.json.JSONArray; @@ -57,69 +62,69 @@ public class GetRemoteUsersOrGroupsOperation extends RemoteOperation{ private static final String TAG = GetRemoteUsersOrGroupsOperation.class.getSimpleName(); // OCS Routes - private static final String OCS_ROUTE_USERS ="/ocs/v1.php/cloud/users?format=json"; - private static final String OCS_ROUTE_GROUPS ="/ocs/v1.php/cloud/groups?format=json"; + private static final String OCS_ROUTE = "ocs/v2.php/apps/files_sharing/api/v1/sharees"; // from OC 8.2 - // Arguments + // Arguments - names + private static final String PARAM_FORMAT = "format"; + private static final String PARAM_ITEM_TYPE = "itemType"; private static final String PARAM_SEARCH = "search"; - private static final String PARAM_LIMIT = "limit"; - private static final String PARAM_OFFSET = "offset"; + private static final String PARAM_PAGE = "page"; // default = 1 + private static final String PARAM_PER_PAGE = "perPage"; // default = 200 + + // Arguments - constant values + private static final String VALUE_FORMAT = "json"; + private static final String VALUE_ITEM_TYPE = "search"; // to get the server search for users / groups + // JSON Node names private static final String NODE_OCS = "ocs"; private static final String NODE_DATA = "data"; + private static final String NODE_EXACT = "exact"; private static final String NODE_USERS = "users"; private static final String NODE_GROUPS = "groups"; + private static final String NODE_VALUE = "value"; + private static final String PROPERTY_LABEL = "label"; + private static final String PROPERTY_SHARE_TYPE = "shareType"; - private ArrayList mNames; // List of users or groups + // Result types + public static final Byte USER_TYPE = 0; + public static final Byte GROUP_TYPE = 1; private String mSearchString; - private int mLimit; - private int mOffset; - private boolean mGetGroup = false; + private int mPage; + private int mPerPage; /** * Constructor * * @param searchString string for searching users, optional - * @param limit limit, optional - * @param offset offset, optional - * @param getGroups true: for searching groups, false: for searching users + * @param page page index in the list of results; beginning in 1 + * @param perPage maximum number of results in a single page */ - public GetRemoteUsersOrGroupsOperation(String searchString, int limit, int offset, - boolean getGroups) { + public GetRemoteUsersOrGroupsOperation(String searchString, int page, int perPage) { mSearchString = searchString; - mLimit = limit; - mOffset = offset; - mGetGroup = getGroups; + mPage = page; + mPerPage = perPage; } @Override protected RemoteOperationResult run(OwnCloudClient client) { RemoteOperationResult result = null; - int status = -1; + int status; GetMethod get = null; - String ocs_route = OCS_ROUTE_USERS; - String nodeUsersOrGroups = NODE_USERS; - if(mGetGroup){ - ocs_route = OCS_ROUTE_GROUPS; - nodeUsersOrGroups = NODE_GROUPS; - } - try{ + Uri requestUri = client.getBaseUri(); + Uri.Builder uriBuilder = requestUri.buildUpon(); + uriBuilder.appendEncodedPath(OCS_ROUTE); + uriBuilder.appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT); + uriBuilder.appendQueryParameter(PARAM_ITEM_TYPE, VALUE_ITEM_TYPE); + uriBuilder.appendQueryParameter(PARAM_SEARCH, Uri.encode(mSearchString)); + uriBuilder.appendQueryParameter(PARAM_PAGE, String.valueOf(mPage)); + uriBuilder.appendQueryParameter(PARAM_PER_PAGE, String.valueOf(mPerPage)); + // Get Method - get = new GetMethod(client.getBaseUri() + ocs_route); - - // Add Parameters to Get Method - get.setQueryString(new NameValuePair[]{ - new NameValuePair(PARAM_SEARCH, mSearchString), - new NameValuePair(PARAM_LIMIT, String.valueOf(mLimit)), - new NameValuePair(PARAM_OFFSET, String.valueOf(mOffset)) - }); - - //¿? - get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE); + get = new GetMethod(uriBuilder.build().toString()); status = client.executeMethod(get); @@ -131,15 +136,30 @@ public class GetRemoteUsersOrGroupsOperation extends RemoteOperation{ JSONObject respJSON = new JSONObject(response); JSONObject respOCS = respJSON.getJSONObject(NODE_OCS); JSONObject respData = respOCS.getJSONObject(NODE_DATA); - JSONArray respUsersOrGroups = respData.getJSONArray(nodeUsersOrGroups); - mNames = new ArrayList(); + JSONObject respExact = respData.getJSONObject(NODE_EXACT); + JSONArray respExactUsers = respExact.getJSONArray(NODE_USERS); + JSONArray respExactGroups = respExact.getJSONArray(NODE_GROUPS); + JSONArray respPartialUsers = respData.getJSONArray(NODE_USERS); + JSONArray respPartialGroups = respData.getJSONArray(NODE_GROUPS); + JSONArray[] jsonResults = { + respExactUsers, + respExactGroups, + respPartialUsers, + respPartialGroups + }; + ArrayList data = new ArrayList(); // For result data - for(int i=0; i<= respUsersOrGroups.length(); i++){ - JSONObject jsonUser = respUsersOrGroups.getJSONObject(i); - String name = jsonUser.toString(); - mNames.add(name); - data.add(name); - Log_OC.d(TAG, "*** "+ nodeUsersOrGroups + " : " + name); + Pair match; + for (int i=0; i<4; i++) { + for(int j=0; j< jsonResults[i].length(); j++){ + JSONObject jsonResult = jsonResults[i].getJSONObject(j); + match = new Pair( + jsonResult.getString(PROPERTY_LABEL), + (byte)jsonResult.getJSONObject(NODE_VALUE).getInt(PROPERTY_SHARE_TYPE) + ); + data.add(match); + Log_OC.d(TAG, "*** Added item: " + match.first); + } } // Result From 68e0633b74debd1d3c80875a7f68cb0b6c83534c Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Wed, 21 Oct 2015 14:44:04 +0200 Subject: [PATCH 08/21] Add option to retrieve share details in CreateRemoteShareOperation; by default the server only returns the share id --- .../shares/CreateRemoteShareOperation.java | 34 +++++- .../shares/GetRemoteShareOperation.java | 110 ++++++++++++++++++ .../shares/GetRemoteSharesOperation.java | 2 +- 3 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 src/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java diff --git a/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java b/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java index f3d38779..6aaa7d1f 100644 --- a/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java @@ -62,6 +62,7 @@ public class CreateRemoteShareOperation extends RemoteOperation { private boolean mPublicUpload; private String mPassword; private int mPermissions; + private boolean mGetShareDetails; /** * Constructor @@ -81,8 +82,14 @@ public class CreateRemoteShareOperation extends RemoteOperation { * To obtain combinations, add the desired values together. * For instance, for Re-Share, delete, read, update, add 16+8+2+1 = 27. */ - public CreateRemoteShareOperation(String remoteFilePath, ShareType shareType, String shareWith, boolean publicUpload, - String password, int permissions) { + public CreateRemoteShareOperation( + String remoteFilePath, + ShareType shareType, + String shareWith, + boolean publicUpload, + String password, + int permissions + ) { mRemoteFilePath = remoteFilePath; mShareType = shareType; @@ -90,6 +97,15 @@ public class CreateRemoteShareOperation extends RemoteOperation { mPublicUpload = publicUpload; mPassword = password; mPermissions = permissions; + mGetShareDetails = false; // defaults to false for backwards compatibility + } + + public boolean isGettingShareDetails () { + return mGetShareDetails; + } + + public void setGetShareDetails(boolean set) { + mGetShareDetails = set; } @Override @@ -141,11 +157,25 @@ public class CreateRemoteShareOperation extends RemoteOperation { sharesObjects.add(share); } result.setData(sharesObjects); + + if (mGetShareDetails) { + // retrieve more info + OCShare emptyShare = (OCShare) sharesObjects.get(0); + + GetRemoteShareOperation getInfo = new GetRemoteShareOperation(emptyShare.getIdRemoteShared()); + result = getInfo.execute(client); + } + + } else { + result = new RemoteOperationResult(ResultCode.UNKNOWN_ERROR); + Log_OC.e(TAG, "Successful response with no share in it"); } + } else if (xmlParser.isFileNotFound()){ result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND); } else if (xmlParser.isFailure()) { + // TODO need deeper processing result = new RemoteOperationResult(ResultCode.SHARE_FORBIDDEN); } else { diff --git a/src/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java new file mode 100644 index 00000000..6dcb28a2 --- /dev/null +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java @@ -0,0 +1,110 @@ +/* ownCloud Android Library is available under MIT license + * @author David A. Velasco + * Copyright (C) 2015 ownCloud Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.owncloud.android.lib.resources.shares; + +import android.net.Uri; + +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.operations.RemoteOperation; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.lib.common.utils.Log_OC; + +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.http.HttpStatus; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + + +/** + * Get the data about a Share resource, known its remote ID. + */ + +public class GetRemoteShareOperation extends RemoteOperation { + + private static final String TAG = GetRemoteShareOperation.class.getSimpleName(); + + private long mRemoteId; + + + public GetRemoteShareOperation(long remoteId) { + mRemoteId = remoteId; + } + + + @Override + protected RemoteOperationResult run(OwnCloudClient client) { + RemoteOperationResult result = null; + int status = -1; + + // Get Method + GetMethod get = null; + + // Get the response + try{ + get = new GetMethod(client.getBaseUri() + ShareUtils.SHARING_API_PATH + "/" + Long.toString(mRemoteId)); + //get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE); + status = client.executeMethod(get); + if(isSuccess(status)) { + String response = get.getResponseBodyAsString(); + + // Parse xml response --> obtain the response in ShareFiles ArrayList + // convert String into InputStream + InputStream is = new ByteArrayInputStream(response.getBytes()); + ShareXMLParser xmlParser = new ShareXMLParser(); + List shares = xmlParser.parseXMLResponse(is); + if (shares != null && shares.size() > 0) { + Log_OC.d(TAG, "Got " + shares.size() + " shares"); + result = new RemoteOperationResult(ResultCode.OK); + ArrayList sharesObjects = new ArrayList(); + sharesObjects.add(shares.get(0)); + result.setData(sharesObjects); + } + } else { + result = new RemoteOperationResult(false, status, get.getResponseHeaders()); + } + + } catch (Exception e) { + result = new RemoteOperationResult(e); + Log_OC.e(TAG, "Exception while getting remote shares ", e); + + } finally { + if (get != null) { + get.releaseConnection(); + } + } + return result; + } + + private boolean isSuccess(int status) { + return (status == HttpStatus.SC_OK); + } + + +} diff --git a/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesOperation.java index 38b75194..18326549 100644 --- a/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesOperation.java @@ -39,7 +39,7 @@ import com.owncloud.android.lib.common.utils.Log_OC; /** - * Get the data from the server to know shares + * Get the data from the server about ALL the known shares owned by the requester. * * @author masensio * From 3d34e504ffd5a2116acb255511f162b846396143 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Fri, 23 Oct 2015 11:33:22 +0200 Subject: [PATCH 09/21] Refactored resources.users.GetRemoteUsersAndGroupsOperation to resources.shares.GetRemoteShareesOperation --- .../GetRemoteShareesOperation.java} | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) rename src/com/owncloud/android/lib/resources/{users/GetRemoteUsersOrGroupsOperation.java => shares/GetRemoteShareesOperation.java} (88%) diff --git a/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOrGroupsOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java similarity index 88% rename from src/com/owncloud/android/lib/resources/users/GetRemoteUsersOrGroupsOperation.java rename to src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java index 122b488a..b54f8430 100644 --- a/src/com/owncloud/android/lib/resources/users/GetRemoteUsersOrGroupsOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java @@ -25,7 +25,7 @@ * */ -package com.owncloud.android.lib.resources.users; +package com.owncloud.android.lib.resources.shares; import android.net.Uri; import android.util.Pair; @@ -45,21 +45,27 @@ import java.util.ArrayList; /** * Created by masensio on 08/10/2015. * - * Retrieves a list of users or groups from the ownCloud server. - * Authentication is done by sending a Basic HTTP Authorization header. - * Syntax: ocs/v1.php/cloud/users (Users) - * ocs/v1.php/cloud/groups (Groups) + * Retrieves a list of sharees (possible targets of a share) from the ownCloud server. + * + * Currently only handles users and groups. Users in other OC servers (federation) should be added later. + * + * Depends on SHAREE API. {@See https://github.com/owncloud/documentation/issues/1626} + * + * Syntax: + * Entry point: ocs/v2.php/apps/files_sharing/api/v1/sharees * HTTP method: GET - * url arguments: search - string, optional search string - * url arguments: limit - int, optional limit value - * url arguments: offset - int, optional offset value + * url argument: itemType - string, required + * url argument: format - string, optional + * url argument: search - string, optional + * url arguments: perPage - int, optional + * url arguments: page - int, optional * * Status codes: * 100 - successful */ -public class GetRemoteUsersOrGroupsOperation extends RemoteOperation{ +public class GetRemoteShareesOperation extends RemoteOperation{ - private static final String TAG = GetRemoteUsersOrGroupsOperation.class.getSimpleName(); + private static final String TAG = GetRemoteShareesOperation.class.getSimpleName(); // OCS Routes private static final String OCS_ROUTE = "ocs/v2.php/apps/files_sharing/api/v1/sharees"; // from OC 8.2 @@ -73,7 +79,7 @@ public class GetRemoteUsersOrGroupsOperation extends RemoteOperation{ // Arguments - constant values private static final String VALUE_FORMAT = "json"; - private static final String VALUE_ITEM_TYPE = "search"; // to get the server search for users / groups + private static final String VALUE_ITEM_TYPE = "search"; // to get the server search for users / groups // JSON Node names @@ -101,7 +107,7 @@ public class GetRemoteUsersOrGroupsOperation extends RemoteOperation{ * @param page page index in the list of results; beginning in 1 * @param perPage maximum number of results in a single page */ - public GetRemoteUsersOrGroupsOperation(String searchString, int page, int perPage) { + public GetRemoteShareesOperation(String searchString, int page, int perPage) { mSearchString = searchString; mPage = page; mPerPage = perPage; From ad60bc9e8e0328e0f6c382890536ded8f7b139a8 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Fri, 23 Oct 2015 15:27:37 +0200 Subject: [PATCH 10/21] Complete error handling and add error message from server to response --- .../operations/RemoteOperationResult.java | 3 +- .../shares/CreateRemoteShareOperation.java | 34 ++++++----- .../shares/GetRemoteShareOperation.java | 39 ++++++++++--- .../GetRemoteSharesForFileOperation.java | 58 +++++++++++++------ .../shares/GetRemoteSharesOperation.java | 36 +++++++++--- .../shares/RemoveRemoteShareOperation.java | 21 +++++-- .../lib/resources/shares/ShareXMLParser.java | 38 +++++++++--- 7 files changed, 167 insertions(+), 62 deletions(-) diff --git a/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java b/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java index ceb3f25f..28709905 100644 --- a/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java +++ b/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java @@ -107,7 +107,8 @@ public class RemoteOperationResult implements Serializable { INVALID_COPY_INTO_DESCENDANT, PARTIAL_MOVE_DONE, PARTIAL_COPY_DONE, - INVALID_CHARACTER_DETECT_IN_SERVER + SHARE_WRONG_PARAMETER, + WRONG_SERVER_RESPONSE, INVALID_CHARACTER_DETECT_IN_SERVER } private boolean mSuccess = false; diff --git a/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java b/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java index 6aaa7d1f..10b447a9 100644 --- a/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java @@ -140,46 +140,52 @@ public class CreateRemoteShareOperation extends RemoteOperation { if(isSuccess(status)) { String response = post.getResponseBodyAsString(); + ArrayList resultData = new ArrayList(); - result = new RemoteOperationResult(ResultCode.OK); - // Parse xml response --> obtain the response in ShareFiles ArrayList // convert String into InputStream InputStream is = new ByteArrayInputStream(response.getBytes()); ShareXMLParser xmlParser = new ShareXMLParser(); mShares = xmlParser.parseXMLResponse(is); if (xmlParser.isSuccess()) { - if (mShares != null) { + if (mShares != null && mShares.size() > 0) { Log_OC.d(TAG, "Created " + mShares.size() + " share(s)"); result = new RemoteOperationResult(ResultCode.OK); - ArrayList sharesObjects = new ArrayList(); for (OCShare share: mShares) { - sharesObjects.add(share); + resultData.add(share); } - result.setData(sharesObjects); + result.setData(resultData); if (mGetShareDetails) { // retrieve more info - OCShare emptyShare = (OCShare) sharesObjects.get(0); + OCShare emptyShare = (OCShare) resultData.get(0); GetRemoteShareOperation getInfo = new GetRemoteShareOperation(emptyShare.getIdRemoteShared()); result = getInfo.execute(client); } } else { - result = new RemoteOperationResult(ResultCode.UNKNOWN_ERROR); - Log_OC.e(TAG, "Successful response with no share in it"); + result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); + Log_OC.e(TAG, "Successful status with no share in it"); } - } else if (xmlParser.isFileNotFound()){ + } else if (xmlParser.isWrongParameter()){ + result = new RemoteOperationResult(ResultCode.SHARE_WRONG_PARAMETER); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + + } else if (xmlParser.isNotFound()){ result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND); - - } else if (xmlParser.isFailure()) { - // TODO need deeper processing + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + + } else if (xmlParser.isForbidden()) { result = new RemoteOperationResult(ResultCode.SHARE_FORBIDDEN); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); } else { - result = new RemoteOperationResult(false, status, post.getResponseHeaders()); + result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); } } else { diff --git a/src/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java index 6dcb28a2..f7ab0b29 100644 --- a/src/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java @@ -25,8 +25,6 @@ package com.owncloud.android.lib.resources.shares; -import android.net.Uri; - import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -71,21 +69,46 @@ public class GetRemoteShareOperation extends RemoteOperation { get = new GetMethod(client.getBaseUri() + ShareUtils.SHARING_API_PATH + "/" + Long.toString(mRemoteId)); //get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE); status = client.executeMethod(get); + if(isSuccess(status)) { String response = get.getResponseBodyAsString(); + ArrayList resultData = new ArrayList(); // Parse xml response --> obtain the response in ShareFiles ArrayList // convert String into InputStream InputStream is = new ByteArrayInputStream(response.getBytes()); ShareXMLParser xmlParser = new ShareXMLParser(); List shares = xmlParser.parseXMLResponse(is); - if (shares != null && shares.size() > 0) { - Log_OC.d(TAG, "Got " + shares.size() + " shares"); - result = new RemoteOperationResult(ResultCode.OK); - ArrayList sharesObjects = new ArrayList(); - sharesObjects.add(shares.get(0)); - result.setData(sharesObjects); + if (xmlParser.isSuccess()) { + if (shares != null && shares.size() > 0) { + Log_OC.d(TAG, "Got " + shares.size() + " shares"); + result = new RemoteOperationResult(ResultCode.OK); + resultData.add(shares.get(0)); + result.setData(resultData); + } else { + result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); + Log_OC.e(TAG, "Successful status with no share in it"); + } + + } else if (xmlParser.isWrongParameter()){ + result = new RemoteOperationResult(ResultCode.SHARE_WRONG_PARAMETER); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + + } else if (xmlParser.isNotFound()){ + result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + + } else if (xmlParser.isForbidden()) { + result = new RemoteOperationResult(ResultCode.SHARE_FORBIDDEN); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + + } else { + result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); } + } else { result = new RemoteOperationResult(false, status, get.getResponseHeaders()); } diff --git a/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesForFileOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesForFileOperation.java index 1518b516..98c8c9d8 100644 --- a/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesForFileOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesForFileOperation.java @@ -37,7 +37,6 @@ import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.lib.resources.status.OwnCloudVersion; /** * Provide a list shares for a specific file. @@ -103,32 +102,53 @@ public class GetRemoteSharesForFileOperation extends RemoteOperation { if(isSuccess(status)) { String response = get.getResponseBodyAsString(); + ArrayList resultData = new ArrayList(); - result = new RemoteOperationResult(ResultCode.OK); - // Parse xml response --> obtain the response in ShareFiles ArrayList // convert String into InputStream InputStream is = new ByteArrayInputStream(response.getBytes()); ShareXMLParser xmlParser = new ShareXMLParser(); mShares = xmlParser.parseXMLResponse(is); - if (mShares != null) { - Log_OC.d(TAG, "Got " + mShares.size() + " shares"); - result = new RemoteOperationResult(ResultCode.OK); - ArrayList sharesObjects = new ArrayList(); - for (OCShare share: mShares) { - // Build the link - if ( share.getShareType() == ShareType.PUBLIC_LINK && - share.getShareLink() == null && - share.getToken().length() > 0 - ) { - String linkToken = ShareUtils.getSharingToken( - client.getOwnCloudVersion()); - share.setShareLink(client.getBaseUri() + linkToken + - share.getToken()); + if (xmlParser.isSuccess()) { + if (mShares != null) { // 0 shares is a right response + Log_OC.d(TAG, "Got " + mShares.size() + " shares"); + result = new RemoteOperationResult(ResultCode.OK); + for (OCShare share: mShares) { + // Build the link + if ( share.getShareType() == ShareType.PUBLIC_LINK && + share.getShareLink() == null && + share.getToken().length() > 0 + ) { + String linkToken = ShareUtils.getSharingToken( + client.getOwnCloudVersion()); + share.setShareLink(client.getBaseUri() + linkToken + + share.getToken()); + } + resultData.add(share); } - sharesObjects.add(share); + result.setData(resultData); + } else { + result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); + Log_OC.e(TAG, "Successful status with no share in it"); } - result.setData(sharesObjects); + + } else if (xmlParser.isWrongParameter()){ + result = new RemoteOperationResult(ResultCode.SHARE_WRONG_PARAMETER); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + + } else if (xmlParser.isNotFound()){ + result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + + } else if (xmlParser.isForbidden()) { + result = new RemoteOperationResult(ResultCode.SHARE_FORBIDDEN); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + + } else { + result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); } } else { diff --git a/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesOperation.java index 18326549..295eaba4 100644 --- a/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesOperation.java @@ -68,23 +68,45 @@ public class GetRemoteSharesOperation extends RemoteOperation { get = new GetMethod(client.getBaseUri() + ShareUtils.SHARING_API_PATH); get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE); status = client.executeMethod(get); + if(isSuccess(status)) { String response = get.getResponseBodyAsString(); + ArrayList resultData = new ArrayList(); // Parse xml response --> obtain the response in ShareFiles ArrayList // convert String into InputStream InputStream is = new ByteArrayInputStream(response.getBytes()); ShareXMLParser xmlParser = new ShareXMLParser(); mShares = xmlParser.parseXMLResponse(is); - if (mShares != null) { - Log_OC.d(TAG, "Got " + mShares.size() + " shares"); - result = new RemoteOperationResult(ResultCode.OK); - ArrayList sharesObjects = new ArrayList(); - for (OCShare share: mShares) { - sharesObjects.add(share); + if (xmlParser.isSuccess()) { + if (mShares != null) { // 0 shares is a right response + Log_OC.d(TAG, "Got " + mShares.size() + " shares"); + result = new RemoteOperationResult(ResultCode.OK); + for (OCShare share : mShares) { + resultData.add(share); + } + result.setData(resultData); } - result.setData(sharesObjects); + + } else if (xmlParser.isWrongParameter()){ + result = new RemoteOperationResult(ResultCode.SHARE_WRONG_PARAMETER); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + + } else if (xmlParser.isNotFound()){ + result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + + } else if (xmlParser.isForbidden()) { + result = new RemoteOperationResult(ResultCode.SHARE_FORBIDDEN); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + + } else { + result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); } + } else { result = new RemoteOperationResult(false, status, get.getResponseHeaders()); } diff --git a/src/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.java b/src/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.java index 4db29051..c4245718 100644 --- a/src/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.java @@ -26,6 +26,7 @@ package com.owncloud.android.lib.resources.shares; import java.io.ByteArrayInputStream; import java.io.InputStream; +import java.util.ArrayList; import org.apache.commons.httpclient.HttpStatus; import org.apache.jackrabbit.webdav.client.methods.DeleteMethod; @@ -77,9 +78,8 @@ public class RemoveRemoteShareOperation extends RemoteOperation { if(isSuccess(status)) { String response = delete.getResponseBodyAsString(); + ArrayList resultData = new ArrayList(); - result = new RemoteOperationResult(ResultCode.OK); - // Parse xml response // convert String into InputStream InputStream is = new ByteArrayInputStream(response.getBytes()); @@ -87,10 +87,23 @@ public class RemoveRemoteShareOperation extends RemoteOperation { xmlParser.parseXMLResponse(is); if (xmlParser.isSuccess()) { result = new RemoteOperationResult(ResultCode.OK); - } else if (xmlParser.isFileNotFound()){ + } else if (xmlParser.isWrongParameter()){ + result = new RemoteOperationResult(ResultCode.SHARE_WRONG_PARAMETER); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + + } else if (xmlParser.isNotFound()){ result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + + } else if (xmlParser.isForbidden()) { + result = new RemoteOperationResult(ResultCode.SHARE_FORBIDDEN); + resultData.add(xmlParser.getMessage()); + result.setData(resultData); + } else { - result = new RemoteOperationResult(false, status, delete.getResponseHeaders()); + result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); } Log_OC.d(TAG, "Unshare " + id + ": " + result.getLogMessage()); diff --git a/src/com/owncloud/android/lib/resources/shares/ShareXMLParser.java b/src/com/owncloud/android/lib/resources/shares/ShareXMLParser.java index 8189eac0..e672deeb 100644 --- a/src/com/owncloud/android/lib/resources/shares/ShareXMLParser.java +++ b/src/com/owncloud/android/lib/resources/shares/ShareXMLParser.java @@ -57,7 +57,7 @@ public class ShareXMLParser { private static final String NODE_META = "meta"; private static final String NODE_STATUS = "status"; private static final String NODE_STATUS_CODE = "statuscode"; - //private static final String NODE_MESSAGE = "message"; + private static final String NODE_MESSAGE = "message"; private static final String NODE_DATA = "data"; private static final String NODE_ELEMENT = "element"; @@ -82,11 +82,13 @@ public class ShareXMLParser { private static final String TYPE_FOLDER = "folder"; private static final int SUCCESS = 100; - private static final int FAILURE = 403; - private static final int FILE_NOT_FOUND = 404; + private static final int ERROR_WRONG_PARAMETER = 403; + private static final int ERROR_FORBIDDEN = 403; + private static final int ERROR_NOT_FOUND = 404; private String mStatus; private int mStatusCode; + private String mMessage; // Getters and Setters public String getStatus() { @@ -104,21 +106,36 @@ public class ShareXMLParser { public void setStatusCode(int statusCode) { this.mStatusCode = statusCode; } + + public String getMessage() { + return mMessage; + } + + public void setMessage(String message) { + this.mMessage = message; + } + // Constructor public ShareXMLParser() { - mStatusCode = 100; + mStatusCode = -1; } public boolean isSuccess() { return mStatusCode == SUCCESS; } - public boolean isFailure() { - return mStatusCode == FAILURE; + + public boolean isForbidden() { + return mStatusCode == ERROR_FORBIDDEN; } - public boolean isFileNotFound() { - return mStatusCode == FILE_NOT_FOUND; + + public boolean isNotFound() { + return mStatusCode == ERROR_NOT_FOUND; } - + + public boolean isWrongParameter() { + return mStatusCode == ERROR_WRONG_PARAMETER; + } + /** * Parse is as response of Share API * @param is @@ -197,6 +214,9 @@ public class ShareXMLParser { } else if (name.equalsIgnoreCase(NODE_STATUS_CODE)) { setStatusCode(Integer.parseInt(readNode(parser, NODE_STATUS_CODE))); + } else if (name.equalsIgnoreCase(NODE_MESSAGE)) { + setMessage(readNode(parser, NODE_MESSAGE)); + } else { skip(parser); } From 4d9ff3e02275f03642fb4b5ed16f3164a0412e21 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Mon, 26 Oct 2015 11:22:22 +0100 Subject: [PATCH 11/21] Refactoed operations on Shares --- .../shares/CreateRemoteShareOperation.java | 72 +++------ .../shares/GetRemoteShareOperation.java | 52 ++----- .../GetRemoteSharesForFileOperation.java | 68 ++------- .../shares/GetRemoteSharesOperation.java | 52 ++----- .../shares/RemoveRemoteShareOperation.java | 42 +---- .../ShareToRemoteOperationResultParser.java | 144 ++++++++++++++++++ .../lib/resources/shares/ShareUtils.java | 14 +- 7 files changed, 206 insertions(+), 238 deletions(-) create mode 100644 src/com/owncloud/android/lib/resources/shares/ShareToRemoteOperationResultParser.java diff --git a/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java b/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java index 10b447a9..403c62c7 100644 --- a/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java @@ -1,4 +1,6 @@ /* ownCloud Android Library is available under MIT license + * @author masensio + * @author David A. Velasco * Copyright (C) 2015 ownCloud Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -24,24 +26,16 @@ package com.owncloud.android.lib.resources.shares; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.ArrayList; - import org.apache.commons.httpclient.methods.PostMethod; import org.apache.http.HttpStatus; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.utils.Log_OC; /** * Creates a new share. This allows sharing with a user or group or as a link. - * - * @author masensio - * */ public class CreateRemoteShareOperation extends RemoteOperation { @@ -54,8 +48,6 @@ public class CreateRemoteShareOperation extends RemoteOperation { private static final String PARAM_PASSWORD = "password"; private static final String PARAM_PERMISSIONS = "permissions"; - private ArrayList mShares; // List of shares for result, one share in this case - private String mRemoteFilePath; private ShareType mShareType; private String mShareWith; @@ -118,7 +110,6 @@ public class CreateRemoteShareOperation extends RemoteOperation { try { // Post Method post = new PostMethod(client.getBaseUri() + ShareUtils.SHARING_API_PATH); - //Log_OC.d(TAG, "URL ------> " + client.getBaseUri() + ShareUtils.SHARING_API_PATH); post.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); // necessary for special characters @@ -127,7 +118,7 @@ public class CreateRemoteShareOperation extends RemoteOperation { post.addParameter(PARAM_SHARE_TYPE, Integer.toString(mShareType.getValue())); post.addParameter(PARAM_SHARE_WITH, mShareWith); if (mPublicUpload) { - post.addParameter(PARAM_PUBLIC_UPLOAD, Boolean.toString(mPublicUpload)); + post.addParameter(PARAM_PUBLIC_UPLOAD, Boolean.toString(true)); } if (mPassword != null && mPassword.length() > 0) { post.addParameter(PARAM_PASSWORD, mPassword); @@ -140,52 +131,23 @@ public class CreateRemoteShareOperation extends RemoteOperation { if(isSuccess(status)) { String response = post.getResponseBodyAsString(); - ArrayList resultData = new ArrayList(); - // Parse xml response --> obtain the response in ShareFiles ArrayList - // convert String into InputStream - InputStream is = new ByteArrayInputStream(response.getBytes()); - ShareXMLParser xmlParser = new ShareXMLParser(); - mShares = xmlParser.parseXMLResponse(is); - if (xmlParser.isSuccess()) { - if (mShares != null && mShares.size() > 0) { - Log_OC.d(TAG, "Created " + mShares.size() + " share(s)"); - result = new RemoteOperationResult(ResultCode.OK); - for (OCShare share: mShares) { - resultData.add(share); - } - result.setData(resultData); + ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser( + new ShareXMLParser() + ); + parser.setOneOrMoreSharesRequired(true); + parser.setOwnCloudVersion(client.getOwnCloudVersion()); + parser.setServerBaseUri(client.getBaseUri()); + result = parser.parse(response); - if (mGetShareDetails) { - // retrieve more info - OCShare emptyShare = (OCShare) resultData.get(0); - - GetRemoteShareOperation getInfo = new GetRemoteShareOperation(emptyShare.getIdRemoteShared()); - result = getInfo.execute(client); - } - - } else { - result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); - Log_OC.e(TAG, "Successful status with no share in it"); + if (result.isSuccess()) { + Log_OC.d(TAG, "Created " + result.getData().size() + " share(s)"); // should be one + if (mGetShareDetails) { + // retrieve more info - POST operation only returns the index of the new share + OCShare emptyShare = (OCShare) result.getData().get(0); + GetRemoteShareOperation getInfo = new GetRemoteShareOperation(emptyShare.getIdRemoteShared()); + result = getInfo.execute(client); } - - } else if (xmlParser.isWrongParameter()){ - result = new RemoteOperationResult(ResultCode.SHARE_WRONG_PARAMETER); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else if (xmlParser.isNotFound()){ - result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else if (xmlParser.isForbidden()) { - result = new RemoteOperationResult(ResultCode.SHARE_FORBIDDEN); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else { - result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); } } else { diff --git a/src/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java index f7ab0b29..9189b9f0 100644 --- a/src/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareOperation.java @@ -28,17 +28,11 @@ package com.owncloud.android.lib.resources.shares; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.utils.Log_OC; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.http.HttpStatus; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; - /** * Get the data about a Share resource, known its remote ID. @@ -67,47 +61,21 @@ public class GetRemoteShareOperation extends RemoteOperation { // Get the response try{ get = new GetMethod(client.getBaseUri() + ShareUtils.SHARING_API_PATH + "/" + Long.toString(mRemoteId)); - //get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE); + get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE); + status = client.executeMethod(get); if(isSuccess(status)) { String response = get.getResponseBodyAsString(); - ArrayList resultData = new ArrayList(); - // Parse xml response --> obtain the response in ShareFiles ArrayList - // convert String into InputStream - InputStream is = new ByteArrayInputStream(response.getBytes()); - ShareXMLParser xmlParser = new ShareXMLParser(); - List shares = xmlParser.parseXMLResponse(is); - if (xmlParser.isSuccess()) { - if (shares != null && shares.size() > 0) { - Log_OC.d(TAG, "Got " + shares.size() + " shares"); - result = new RemoteOperationResult(ResultCode.OK); - resultData.add(shares.get(0)); - result.setData(resultData); - } else { - result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); - Log_OC.e(TAG, "Successful status with no share in it"); - } - - } else if (xmlParser.isWrongParameter()){ - result = new RemoteOperationResult(ResultCode.SHARE_WRONG_PARAMETER); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else if (xmlParser.isNotFound()){ - result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else if (xmlParser.isForbidden()) { - result = new RemoteOperationResult(ResultCode.SHARE_FORBIDDEN); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else { - result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); - } + // Parse xml response and obtain the list of shares + ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser( + new ShareXMLParser() + ); + parser.setOneOrMoreSharesRequired(true); + parser.setOwnCloudVersion(client.getOwnCloudVersion()); + parser.setServerBaseUri(client.getBaseUri()); + result = parser.parse(response); } else { result = new RemoteOperationResult(false, status, get.getResponseHeaders()); diff --git a/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesForFileOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesForFileOperation.java index 98c8c9d8..1381d272 100644 --- a/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesForFileOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesForFileOperation.java @@ -1,4 +1,6 @@ /* ownCloud Android Library is available under MIT license + * @author masensio + * @author David A. Velasco * Copyright (C) 2015 ownCloud Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -24,10 +26,6 @@ package com.owncloud.android.lib.resources.shares; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.ArrayList; - import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.http.HttpStatus; @@ -35,18 +33,14 @@ import org.apache.http.HttpStatus; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.utils.Log_OC; + /** * Provide a list shares for a specific file. * The input is the full path of the desired file. * The output is a list of everyone who has the file shared with them. - * - * @author masensio - * */ - public class GetRemoteSharesForFileOperation extends RemoteOperation { private static final String TAG = GetRemoteSharesForFileOperation.class.getSimpleName(); @@ -55,8 +49,6 @@ public class GetRemoteSharesForFileOperation extends RemoteOperation { private static final String PARAM_RESHARES = "reshares"; private static final String PARAM_SUBFILES = "subfiles"; - private ArrayList mShares; // List of shares for result, one share in this case - private String mRemoteFilePath; private boolean mReshares; private boolean mSubfiles; @@ -102,53 +94,17 @@ public class GetRemoteSharesForFileOperation extends RemoteOperation { if(isSuccess(status)) { String response = get.getResponseBodyAsString(); - ArrayList resultData = new ArrayList(); - // Parse xml response --> obtain the response in ShareFiles ArrayList - // convert String into InputStream - InputStream is = new ByteArrayInputStream(response.getBytes()); - ShareXMLParser xmlParser = new ShareXMLParser(); - mShares = xmlParser.parseXMLResponse(is); - if (xmlParser.isSuccess()) { - if (mShares != null) { // 0 shares is a right response - Log_OC.d(TAG, "Got " + mShares.size() + " shares"); - result = new RemoteOperationResult(ResultCode.OK); - for (OCShare share: mShares) { - // Build the link - if ( share.getShareType() == ShareType.PUBLIC_LINK && - share.getShareLink() == null && - share.getToken().length() > 0 - ) { - String linkToken = ShareUtils.getSharingToken( - client.getOwnCloudVersion()); - share.setShareLink(client.getBaseUri() + linkToken + - share.getToken()); - } - resultData.add(share); - } - result.setData(resultData); - } else { - result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); - Log_OC.e(TAG, "Successful status with no share in it"); - } + // Parse xml response and obtain the list of shares + ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser( + new ShareXMLParser() + ); + parser.setOwnCloudVersion(client.getOwnCloudVersion()); + parser.setServerBaseUri(client.getBaseUri()); + result = parser.parse(response); - } else if (xmlParser.isWrongParameter()){ - result = new RemoteOperationResult(ResultCode.SHARE_WRONG_PARAMETER); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else if (xmlParser.isNotFound()){ - result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else if (xmlParser.isForbidden()) { - result = new RemoteOperationResult(ResultCode.SHARE_FORBIDDEN); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else { - result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); + if (result.isSuccess()) { + Log_OC.d(TAG, "Got " + result.getData().size() + " shares"); } } else { diff --git a/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesOperation.java index 295eaba4..acd8ca23 100644 --- a/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteSharesOperation.java @@ -1,4 +1,6 @@ /* ownCloud Android Library is available under MIT license + * @author masensio + * @author David A. Velasco * Copyright (C) 2015 ownCloud Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -24,34 +26,25 @@ package com.owncloud.android.lib.resources.shares; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.ArrayList; - import org.apache.commons.httpclient.methods.GetMethod; import org.apache.http.HttpStatus; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.utils.Log_OC; /** * Get the data from the server about ALL the known shares owned by the requester. * - * @author masensio - * */ public class GetRemoteSharesOperation extends RemoteOperation { private static final String TAG = GetRemoteSharesOperation.class.getSimpleName(); - private ArrayList mShares; // List of shares for result - public GetRemoteSharesOperation() { } @@ -71,41 +64,14 @@ public class GetRemoteSharesOperation extends RemoteOperation { if(isSuccess(status)) { String response = get.getResponseBodyAsString(); - ArrayList resultData = new ArrayList(); - // Parse xml response --> obtain the response in ShareFiles ArrayList - // convert String into InputStream - InputStream is = new ByteArrayInputStream(response.getBytes()); - ShareXMLParser xmlParser = new ShareXMLParser(); - mShares = xmlParser.parseXMLResponse(is); - if (xmlParser.isSuccess()) { - if (mShares != null) { // 0 shares is a right response - Log_OC.d(TAG, "Got " + mShares.size() + " shares"); - result = new RemoteOperationResult(ResultCode.OK); - for (OCShare share : mShares) { - resultData.add(share); - } - result.setData(resultData); - } - - } else if (xmlParser.isWrongParameter()){ - result = new RemoteOperationResult(ResultCode.SHARE_WRONG_PARAMETER); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else if (xmlParser.isNotFound()){ - result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else if (xmlParser.isForbidden()) { - result = new RemoteOperationResult(ResultCode.SHARE_FORBIDDEN); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else { - result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); - } + // Parse xml response and obtain the list of shares + ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser( + new ShareXMLParser() + ); + parser.setOwnCloudVersion(client.getOwnCloudVersion()); + parser.setServerBaseUri(client.getBaseUri()); + result = parser.parse(response); } else { result = new RemoteOperationResult(false, status, get.getResponseHeaders()); diff --git a/src/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.java b/src/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.java index c4245718..68a94db4 100644 --- a/src/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/RemoveRemoteShareOperation.java @@ -1,4 +1,6 @@ /* ownCloud Android Library is available under MIT license + * @author masensio + * @author David A. Velasco * Copyright (C) 2015 ownCloud Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -24,24 +26,16 @@ package com.owncloud.android.lib.resources.shares; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.ArrayList; - import org.apache.commons.httpclient.HttpStatus; import org.apache.jackrabbit.webdav.client.methods.DeleteMethod; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.common.utils.Log_OC; /** * Remove a share - * - * @author masensio - * */ public class RemoveRemoteShareOperation extends RemoteOperation { @@ -78,35 +72,15 @@ public class RemoveRemoteShareOperation extends RemoteOperation { if(isSuccess(status)) { String response = delete.getResponseBodyAsString(); - ArrayList resultData = new ArrayList(); - // Parse xml response - // convert String into InputStream - InputStream is = new ByteArrayInputStream(response.getBytes()); - ShareXMLParser xmlParser = new ShareXMLParser(); - xmlParser.parseXMLResponse(is); - if (xmlParser.isSuccess()) { - result = new RemoteOperationResult(ResultCode.OK); - } else if (xmlParser.isWrongParameter()){ - result = new RemoteOperationResult(ResultCode.SHARE_WRONG_PARAMETER); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); + // Parse xml response and obtain the list of shares + ShareToRemoteOperationResultParser parser = new ShareToRemoteOperationResultParser( + new ShareXMLParser() + ); + result = parser.parse(response); - } else if (xmlParser.isNotFound()){ - result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else if (xmlParser.isForbidden()) { - result = new RemoteOperationResult(ResultCode.SHARE_FORBIDDEN); - resultData.add(xmlParser.getMessage()); - result.setData(resultData); - - } else { - result = new RemoteOperationResult(ResultCode.WRONG_SERVER_RESPONSE); - } - Log_OC.d(TAG, "Unshare " + id + ": " + result.getLogMessage()); + } else { result = new RemoteOperationResult(false, status, delete.getResponseHeaders()); } diff --git a/src/com/owncloud/android/lib/resources/shares/ShareToRemoteOperationResultParser.java b/src/com/owncloud/android/lib/resources/shares/ShareToRemoteOperationResultParser.java new file mode 100644 index 00000000..c59ba8ed --- /dev/null +++ b/src/com/owncloud/android/lib/resources/shares/ShareToRemoteOperationResultParser.java @@ -0,0 +1,144 @@ +/* ownCloud Android Library is available under MIT license + * @author David A. Velasco + * Copyright (C) 2015 ownCloud Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.owncloud.android.lib.resources.shares; + +import android.net.Uri; + +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.lib.resources.status.OwnCloudVersion; + +import org.xmlpull.v1.XmlPullParserException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +public class ShareToRemoteOperationResultParser { + + private static final String TAG = ShareToRemoteOperationResultParser.class.getSimpleName(); + + private ShareXMLParser mShareXmlParser = null; + private boolean mOneOrMoreSharesRequired = false; + private OwnCloudVersion mOwnCloudVersion = null; + private Uri mServerBaseUri = null; + + + public ShareToRemoteOperationResultParser(ShareXMLParser shareXmlParser) { + mShareXmlParser = shareXmlParser; + } + + public void setOneOrMoreSharesRequired(boolean oneOrMoreSharesRequired) { + mOneOrMoreSharesRequired = oneOrMoreSharesRequired; + } + + public void setOwnCloudVersion(OwnCloudVersion ownCloudVersion) { + mOwnCloudVersion = ownCloudVersion; + } + + public void setServerBaseUri(Uri serverBaseURi) { + mServerBaseUri = serverBaseURi; + } + + public RemoteOperationResult parse(String serverResponse) { + if (serverResponse == null || serverResponse.length() == 0) { + return new RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE); + } + + RemoteOperationResult result = null; + ArrayList resultData = new ArrayList(); + + try { + // Parse xml response and obtain the list of shares + InputStream is = new ByteArrayInputStream(serverResponse.getBytes()); + if (mShareXmlParser == null) { + Log_OC.w(TAG, "No ShareXmlParser provided, creating new instance "); + mShareXmlParser = new ShareXMLParser(); + } + List shares = mShareXmlParser.parseXMLResponse(is); + + if (mShareXmlParser.isSuccess()) { + if ((shares != null && shares.size() > 0) || !mOneOrMoreSharesRequired) { + result = new RemoteOperationResult(RemoteOperationResult.ResultCode.OK); + if (shares != null) { + for (OCShare share : shares) { + resultData.add(share); + // build the share link if not in the response (only received when the share is created) + if (share.getShareType() == ShareType.PUBLIC_LINK && + share.getShareLink() == null && + share.getToken().length() > 0 + ) { + if (mServerBaseUri != null) { + String sharingLinkPath = ShareUtils.getSharingLinkPath(mOwnCloudVersion); + share.setShareLink(mServerBaseUri + sharingLinkPath + share.getToken()); + } else { + Log_OC.e(TAG, "Couldn't build link for public share"); + } + } + } + } + result.setData(resultData); + + } else { + result = new RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE); + Log_OC.e(TAG, "Successful status with no share in the response"); + } + + } else if (mShareXmlParser.isWrongParameter()){ + result = new RemoteOperationResult(RemoteOperationResult.ResultCode.SHARE_WRONG_PARAMETER); + resultData.add(mShareXmlParser.getMessage()); + result.setData(resultData); + + } else if (mShareXmlParser.isNotFound()){ + result = new RemoteOperationResult(RemoteOperationResult.ResultCode.SHARE_NOT_FOUND); + resultData.add(mShareXmlParser.getMessage()); + result.setData(resultData); + + } else if (mShareXmlParser.isForbidden()) { + result = new RemoteOperationResult(RemoteOperationResult.ResultCode.SHARE_FORBIDDEN); + resultData.add(mShareXmlParser.getMessage()); + result.setData(resultData); + + } else { + result = new RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE); + + } + + } catch (XmlPullParserException e) { + Log_OC.e(TAG, "Error parsing response from server ", e); + result = new RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE); + + } catch (IOException e) { + Log_OC.e(TAG, "Error reading response from server ", e); + result = new RemoteOperationResult(RemoteOperationResult.ResultCode.WRONG_SERVER_RESPONSE); + } + + return result; + } + +} diff --git a/src/com/owncloud/android/lib/resources/shares/ShareUtils.java b/src/com/owncloud/android/lib/resources/shares/ShareUtils.java index 8ab9b118..ae4bc8b8 100644 --- a/src/com/owncloud/android/lib/resources/shares/ShareUtils.java +++ b/src/com/owncloud/android/lib/resources/shares/ShareUtils.java @@ -39,17 +39,15 @@ public class ShareUtils { public static final String SHARING_API_PATH ="/ocs/v1.php/apps/files_sharing/api/v1/shares"; // String to build the link with the token of a share: - // server address + "/public.php?service=files&t=" + token - public static final String SHARING_LINK_TOKEN_BEFORE_VERSION_8 = "/public.php?service=files&t="; - public static final String SHARING_LINK_TOKEN_AFTER_VERSION_8= "/index.php/s/"; + public static final String SHARING_LINK_PATH_BEFORE_VERSION_8 = "/public.php?service=files&t="; + public static final String SHARING_LINK_PATH_AFTER_VERSION_8 = "/index.php/s/"; - public static String getSharingToken(OwnCloudVersion version){ + public static String getSharingLinkPath(OwnCloudVersion version){ if (version!= null && version.isAfter8Version()){ - return SHARING_LINK_TOKEN_AFTER_VERSION_8; + return SHARING_LINK_PATH_AFTER_VERSION_8; } else { - return SHARING_LINK_TOKEN_BEFORE_VERSION_8; + return SHARING_LINK_PATH_BEFORE_VERSION_8; } - } - + } From bfe4fcd977de4d91b68cf0e439872fb95570572a Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Tue, 27 Oct 2015 09:23:36 +0100 Subject: [PATCH 12/21] Changes after cr --- .../shares/CreateRemoteShareOperation.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java b/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java index 403c62c7..65bbb0c4 100644 --- a/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java @@ -60,7 +60,8 @@ public class CreateRemoteShareOperation extends RemoteOperation { * Constructor * @param remoteFilePath Full path of the file/folder being shared. Mandatory argument * @param shareType 0 = user, 1 = group, 3 = Public link. Mandatory argument - * @param shareWith User/group ID with who the file should be shared. This is mandatory for shareType of 0 or 1 + * @param shareWith User/group ID with who the file should be shared. This is mandatory for shareType + * of 0 or 1 * @param publicUpload If false (default) public cannot upload to a public shared folder. * If true public can upload to a shared folder. Only available for public link shares * @param password Password to protect a public link share. Only available for public link shares @@ -140,14 +141,13 @@ public class CreateRemoteShareOperation extends RemoteOperation { parser.setServerBaseUri(client.getBaseUri()); result = parser.parse(response); - if (result.isSuccess()) { - Log_OC.d(TAG, "Created " + result.getData().size() + " share(s)"); // should be one - if (mGetShareDetails) { - // retrieve more info - POST operation only returns the index of the new share - OCShare emptyShare = (OCShare) result.getData().get(0); - GetRemoteShareOperation getInfo = new GetRemoteShareOperation(emptyShare.getIdRemoteShared()); - result = getInfo.execute(client); - } + if (result.isSuccess() && mGetShareDetails) { + // retrieve more info - POST only returns the index of the new share + OCShare emptyShare = (OCShare) result.getData().get(0); + GetRemoteShareOperation getInfo = new GetRemoteShareOperation( + emptyShare.getIdRemoteShared() + ); + result = getInfo.execute(client); } } else { From 0acd17d8ac5900251e31ddefa370f9bf19eca604 Mon Sep 17 00:00:00 2001 From: masensio Date: Wed, 28 Oct 2015 10:47:22 +0100 Subject: [PATCH 13/21] Fix: user whose name includes @ are not found --- .../android/lib/resources/shares/GetRemoteShareesOperation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java index b54f8430..bfe5195d 100644 --- a/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java @@ -125,7 +125,7 @@ public class GetRemoteShareesOperation extends RemoteOperation{ uriBuilder.appendEncodedPath(OCS_ROUTE); uriBuilder.appendQueryParameter(PARAM_FORMAT, VALUE_FORMAT); uriBuilder.appendQueryParameter(PARAM_ITEM_TYPE, VALUE_ITEM_TYPE); - uriBuilder.appendQueryParameter(PARAM_SEARCH, Uri.encode(mSearchString)); + uriBuilder.appendQueryParameter(PARAM_SEARCH, Uri.encode(mSearchString, "@")); uriBuilder.appendQueryParameter(PARAM_PAGE, String.valueOf(mPage)); uriBuilder.appendQueryParameter(PARAM_PER_PAGE, String.valueOf(mPerPage)); From a9ada0b508343948431998170189a1267708dfec Mon Sep 17 00:00:00 2001 From: masensio Date: Wed, 28 Oct 2015 18:38:53 +0100 Subject: [PATCH 14/21] Fix problem searching users on Shibboleth Server. Add OC_API_HEADER to GetRemoteShareesOperation --- .../android/lib/resources/shares/GetRemoteShareesOperation.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java index bfe5195d..9045fc88 100644 --- a/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java @@ -131,6 +131,7 @@ public class GetRemoteShareesOperation extends RemoteOperation{ // Get Method get = new GetMethod(uriBuilder.build().toString()); + get.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE); status = client.executeMethod(get); From ea26e43c0d173aef2346301cb1e9398ec4bd9da7 Mon Sep 17 00:00:00 2001 From: masensio Date: Thu, 29 Oct 2015 10:42:57 +0100 Subject: [PATCH 15/21] GetRemoteShareeOperation returns ArrayList with Users and Groups --- .../shares/GetRemoteShareesOperation.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java index 9045fc88..6809fac6 100644 --- a/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java @@ -88,9 +88,10 @@ public class GetRemoteShareesOperation extends RemoteOperation{ private static final String NODE_EXACT = "exact"; private static final String NODE_USERS = "users"; private static final String NODE_GROUPS = "groups"; - private static final String NODE_VALUE = "value"; - private static final String PROPERTY_LABEL = "label"; - private static final String PROPERTY_SHARE_TYPE = "shareType"; + public static final String NODE_VALUE = "value"; + public static final String PROPERTY_LABEL = "label"; + public static final String PROPERTY_SHARE_TYPE = "shareType"; + public static final String PROPERTY_SHARE_WITH = "shareWith"; // Result types public static final Byte USER_TYPE = 0; @@ -156,16 +157,16 @@ public class GetRemoteShareesOperation extends RemoteOperation{ }; ArrayList data = new ArrayList(); // For result data - Pair match; +// Pair match; for (int i=0; i<4; i++) { for(int j=0; j< jsonResults[i].length(); j++){ JSONObject jsonResult = jsonResults[i].getJSONObject(j); - match = new Pair( - jsonResult.getString(PROPERTY_LABEL), - (byte)jsonResult.getJSONObject(NODE_VALUE).getInt(PROPERTY_SHARE_TYPE) - ); - data.add(match); - Log_OC.d(TAG, "*** Added item: " + match.first); +// match = new Pair( +// jsonResult.getString(PROPERTY_LABEL), +// (byte)jsonResult.getJSONObject(NODE_VALUE).getInt(PROPERTY_SHARE_TYPE) +// ); + data.add(jsonResult); + Log_OC.d(TAG, "*** Added item: " + jsonResult.getString(PROPERTY_LABEL)); } } From 642051cf450ee70c10235041029361f12a0a9717 Mon Sep 17 00:00:00 2001 From: masensio Date: Thu, 29 Oct 2015 10:49:19 +0100 Subject: [PATCH 16/21] Remove commented code --- .../lib/resources/shares/GetRemoteShareesOperation.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java index 6809fac6..132b017f 100644 --- a/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/GetRemoteShareesOperation.java @@ -28,7 +28,6 @@ package com.owncloud.android.lib.resources.shares; import android.net.Uri; -import android.util.Pair; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; @@ -157,14 +156,9 @@ public class GetRemoteShareesOperation extends RemoteOperation{ }; ArrayList data = new ArrayList(); // For result data -// Pair match; for (int i=0; i<4; i++) { for(int j=0; j< jsonResults[i].length(); j++){ JSONObject jsonResult = jsonResults[i].getJSONObject(j); -// match = new Pair( -// jsonResult.getString(PROPERTY_LABEL), -// (byte)jsonResult.getJSONObject(NODE_VALUE).getInt(PROPERTY_SHARE_TYPE) -// ); data.add(jsonResult); Log_OC.d(TAG, "*** Added item: " + jsonResult.getString(PROPERTY_LABEL)); } From 875fce9f9c19190ba976cfc3634c63029362eda5 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Thu, 29 Oct 2015 16:32:57 +0100 Subject: [PATCH 17/21] Added constant to let server decide share permissions --- .../lib/resources/shares/CreateRemoteShareOperation.java | 4 +++- src/com/owncloud/android/lib/resources/shares/OCShare.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java b/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java index 65bbb0c4..21545222 100644 --- a/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java +++ b/src/com/owncloud/android/lib/resources/shares/CreateRemoteShareOperation.java @@ -124,7 +124,9 @@ public class CreateRemoteShareOperation extends RemoteOperation { if (mPassword != null && mPassword.length() > 0) { post.addParameter(PARAM_PASSWORD, mPassword); } - post.addParameter(PARAM_PERMISSIONS, Integer.toString(mPermissions)); + if (OCShare.DEFAULT_PERMISSION != mPermissions) { + post.addParameter(PARAM_PERMISSIONS, Integer.toString(mPermissions)); + } post.addRequestHeader(OCS_API_HEADER, OCS_API_HEADER_VALUE); diff --git a/src/com/owncloud/android/lib/resources/shares/OCShare.java b/src/com/owncloud/android/lib/resources/shares/OCShare.java index 16f0c394..644955cc 100644 --- a/src/com/owncloud/android/lib/resources/shares/OCShare.java +++ b/src/com/owncloud/android/lib/resources/shares/OCShare.java @@ -45,7 +45,9 @@ public class OCShare implements Parcelable, Serializable { private static final long serialVersionUID = 4124975224281327921L; private static final String TAG = OCShare.class.getSimpleName(); - + + public static final int DEFAULT_PERMISSION = -1; + private long mId; private long mFileSource; private long mItemSource; From caa9bb3d01a14423bb5c9f82357d3ebbd27acf26 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Tue, 27 Oct 2015 09:13:15 +0100 Subject: [PATCH 18/21] Added test for GetRemoteShareesOperation --- .../lib/test_project/test/GetShareesTest.java | 228 ++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 test_client/tests/src/com/owncloud/android/lib/test_project/test/GetShareesTest.java diff --git a/test_client/tests/src/com/owncloud/android/lib/test_project/test/GetShareesTest.java b/test_client/tests/src/com/owncloud/android/lib/test_project/test/GetShareesTest.java new file mode 100644 index 00000000..80bcd107 --- /dev/null +++ b/test_client/tests/src/com/owncloud/android/lib/test_project/test/GetShareesTest.java @@ -0,0 +1,228 @@ +/* ownCloud Android Library is available under MIT license + * @author David A. Velasco + * Copyright (C) 2015 ownCloud Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.owncloud.android.lib.test_project.test; + +import java.security.GeneralSecurityException; + +import junit.framework.AssertionFailedError; + +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; +import org.json.JSONException; +import org.json.JSONObject; + +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.OwnCloudClientFactory; +import com.owncloud.android.lib.common.OwnCloudCredentialsFactory; +import com.owncloud.android.lib.common.network.NetworkUtils; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.resources.shares.GetRemoteShareesOperation; +import com.owncloud.android.lib.test_project.R; +import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory; + +import android.content.Context; +import android.net.Uri; +import android.util.Log; + +/** + * Class to test GetRemoteShareesOperation + * + * With this TestCase we are experimenting a bit to improve the test suite design, in two aspects: + * + * - Reduce the dependency from the set of test cases on the "test project" needed to + * have an instrumented APK to install in the device, as required by the testing framework + * provided by Android. To get there, this class avoids calling TestActivity methods in the test + * method. + * + * - Reduce the impact of creating a remote fixture over the Internet, while the structure of the + * TestCase is kept easy to maintain. To get this, all the tests are done in a single test method, + * granting this way that setUp and tearDown are run only once. + * + */ + +public class GetShareesTest extends RemoteTest { + + private static final String LOG_TAG = GetShareesTest.class.getCanonicalName(); + + String mServerUri, mUser, mPass; + OwnCloudClient mClient = null; + + public GetShareesTest() { + super(); + + Protocol pr = Protocol.getProtocol("https"); + if (pr == null || !(pr.getSocketFactory() instanceof SelfSignedConfidentSslSocketFactory)) { + try { + ProtocolSocketFactory psf = new SelfSignedConfidentSslSocketFactory(); + Protocol.registerProtocol( + "https", + new Protocol("https", psf, 443)); + + } catch (GeneralSecurityException e) { + throw new AssertionFailedError( + "Self-signed confident SSL context could not be loaded"); + } + } + + } + + + protected Context getContext() { + return getActivity(); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + // Next initialization cannot be done in the constructor because getContext() is not + // ready yet, returns NULL. + initAccessToServer(getContext()); + + Log.v(LOG_TAG, "Setting up the remote fixture..."); + + Log.v(LOG_TAG, "Remote fixture created."); + + } + + + /** + * Test get sharees + * + * Requires OC server 8.2 or later + */ + public void testGetRemoteShareesOperation() { + Log.v(LOG_TAG, "testGetRemoteSharees in"); + + /// successful cases + + // search for sharees including "a" + GetRemoteShareesOperation getShareesOperation = new GetRemoteShareesOperation("a", 1, 50); + RemoteOperationResult result = getShareesOperation.execute(mClient); + JSONObject resultItem; + JSONObject value; + byte type; + int userCount = 0, groupCount = 0; + assertTrue(result.isSuccess() && result.getData().size() == 3); + try { + for (int i=0; i<3; i++) { + resultItem = (JSONObject) result.getData().get(i); + value = resultItem.getJSONObject(GetRemoteShareesOperation.NODE_VALUE); + type = (byte) value.getInt(GetRemoteShareesOperation.PROPERTY_SHARE_TYPE); + if (GetRemoteShareesOperation.GROUP_TYPE.equals(type)) { + groupCount++; + } else { + userCount++; + } + } + assertEquals(userCount, 2); + assertEquals(groupCount, 1); + } catch (JSONException e) { + AssertionFailedError afe = new AssertionFailedError(e.getLocalizedMessage()); + afe.setStackTrace(e.getStackTrace()); + throw afe; + } + + // search for sharees including "ad" + getShareesOperation = new GetRemoteShareesOperation("ad", 1, 50); + result = getShareesOperation.execute(mClient); + assertTrue(result.isSuccess() && result.getData().size() == 2); + userCount = 0; groupCount = 0; + try { + for (int i=0; i<2; i++) { + resultItem = (JSONObject) result.getData().get(i); + value = resultItem.getJSONObject(GetRemoteShareesOperation.NODE_VALUE); + type = (byte) value.getInt(GetRemoteShareesOperation.PROPERTY_SHARE_TYPE); + if (GetRemoteShareesOperation.GROUP_TYPE.equals(type)) { + groupCount++; + } else { + userCount++; + } + } + assertEquals(userCount, 1); + assertEquals(groupCount, 1); + } catch (JSONException e) { + AssertionFailedError afe = new AssertionFailedError(e.getLocalizedMessage()); + afe.setStackTrace(e.getStackTrace()); + throw afe; + } + + + // search for sharees including "b" + getShareesOperation = new GetRemoteShareesOperation("b", 1, 50); + result = getShareesOperation.execute(mClient); + assertTrue(result.isSuccess() && result.getData().size() == 0); + + + /// failed cases + + // search for sharees including wrong page values + getShareesOperation = new GetRemoteShareesOperation("a", 0, 50); + result = getShareesOperation.execute(mClient); + assertTrue(!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_BAD_REQUEST); + + getShareesOperation = new GetRemoteShareesOperation("a", 1, 0); + result = getShareesOperation.execute(mClient); + assertTrue(!result.isSuccess() && result.getHttpCode() == HttpStatus.SC_BAD_REQUEST); + } + + @Override + protected void tearDown() throws Exception { + Log.v(LOG_TAG, "Deleting remote fixture..."); + super.tearDown(); + Log.v(LOG_TAG, "Remote fixture delete."); + } + + + private void initAccessToServer(Context context) { + Log.v(LOG_TAG, "Setting up client instance to access OC server..."); + + mServerUri = context.getString(R.string.server_base_url); + mUser = context.getString(R.string.username); + mPass = context.getString(R.string.password); + + mClient = new OwnCloudClient( + Uri.parse(mServerUri), + NetworkUtils.getMultiThreadedConnManager() + ); + mClient.setDefaultTimeouts( + OwnCloudClientFactory.DEFAULT_DATA_TIMEOUT, + OwnCloudClientFactory.DEFAULT_CONNECTION_TIMEOUT); + mClient.setFollowRedirects(true); + mClient.setCredentials( + OwnCloudCredentialsFactory.newBasicCredentials( + mUser, + mPass + ) + ); + + Log.v(LOG_TAG, "Client instance set up."); + + } + + +} From 96825b43b93a0ee771649f6a8097ad722ab6cb82 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Thu, 29 Oct 2015 18:29:49 +0100 Subject: [PATCH 19/21] Updated test server --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8ccad6c8..fe5cb9c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,8 +20,8 @@ script: - ./gradlew clean build env: global: - - secure: HxHoqnC8mauCKi87zlo7pQcSsSw0W5MtW+iUcB8T11quwTBgUPWIOmycXv2FcmwpST0E43Ct+dhE+mttm+6P+5PSB33HQNLq00hfTVIJ4ttcb/5eWW8MnP7L+kPK8d0EtfDG6GQto7QktaybeG4+sNKKD336ZlFfM7xgPtPv+tg= - - secure: WQMw0ciloe8i2ApGhePhuTmmH8UgAV1Ri10C1qhUH9hVOJAr+/1X5A93VPYGrgJ2EH5MdiL6f2XMDCYAgb9efuvZIUKNE0J92xh8m/yRa8nAVWNBE0PBdS4+OycoHpIQfMcUghooERXjP4GUYd/ZwICvWA+sXdOYWDdKjODUgl4= - - secure: QPxKT8vC7sm1b/hYJcfkQkLgpwNRBvVKk8S8S0t43mmqPJfs94FJTQHH4kZaGSwOeuDkRQbGuKzYtXOnGOKX2hhUBqKJd1idpJnUID8id8Kqo6VutjG017+XxZQp0hPHmfmDxYkDvlaLeoZpP2NkpwZ1p4TL2MSCr2Ibl6uTWvc= + - secure: a21NrzTCQnkTKtRGo7B1lyF2WWbpBT2N64V2Tf+oUcRLOUx3XM/mDi60mAdGd0WXV9tHD8GGmu0tQ7LGZ2VsIxixVxjzEYwX4HRTodewYez6WxBMjVEHHy+3jmc1zU4k3AAqr+uW7L4BKa5r9tH+nq9ecJMDMgW8o9MKXuP7Vso= + - secure: UVnaC5Qzat2C8WlMMb8aycz1ChZKjP8Kz89qBbVcqYK+PLAGKpUNxFa39/2oA5jkMyyOcXYC9bX1ZYzHLH7nJ8LbQgaxXMT4gvgvN0l6KezjDavIW60idD9BbugkwzNj/cjoU/DdxBykPsTn4vSRaESVNTdEbM27YU4FBPzTANY= + - secure: XEQY8s7p65lWWOuKbVDdTh6ZJtRTJ74Zw3H/+2Ms6vjZhFZsdUJjGo66LW6YvlhmYDXgiPB9piYQGcrGgT3hXJwXoge6n1pdixnV250J0T0dIZMbXYTWTARxDsyq48+LgUuF3pgqvqDWhBcemrePWv48q7fs/mwzuFSOyc8QwLk= matrix: - ANDROID_TARGET=android-19 ANDROID_ABI=armeabi-v7a From b5074f4381217ff9acbc52cbbaba9c3331df3735 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Thu, 29 Oct 2015 18:52:14 +0100 Subject: [PATCH 20/21] Migrate Travis build to container-based infrastructure --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index fe5cb9c1..d12be4a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +sudo: false language: android android: components: From 5c48817712be36262002605c25abd0b41d02fb80 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Mon, 2 Nov 2015 14:59:01 +0100 Subject: [PATCH 21/21] Update unit tests with cases for creating private shares --- .../test_project/test/CreateShareTest.java | 151 +++++++++++++++++- 1 file changed, 148 insertions(+), 3 deletions(-) diff --git a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CreateShareTest.java b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CreateShareTest.java index 782c06d8..8d08dd81 100644 --- a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CreateShareTest.java +++ b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CreateShareTest.java @@ -31,6 +31,9 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCo import com.owncloud.android.lib.resources.shares.ShareType; import com.owncloud.android.lib.test_project.TestActivity; +/** + * Test Create Share: the server must support SHARE API + */ public class CreateShareTest extends RemoteTest { private static final String LOG_TAG = CreateShareTest.class.getCanonicalName(); @@ -38,15 +41,20 @@ public class CreateShareTest extends RemoteTest { /* File to share.*/ private static final String FILE_TO_SHARE = "/fileToShare.txt"; + /* Non-existent file*/ + private static final String NON_EXISTENT_FILE = "/nonExistentFile.txt"; + private TestActivity mActivity; private String mFullPath2FileToShare; + private String mFullPath2NonExistentFile; @Override protected void setUp() throws Exception { super.setUp(); setActivityInitialTouchMode(false); mActivity = getActivity(); - mFullPath2FileToShare = mBaseFolderPath + FILE_TO_SHARE; + mFullPath2FileToShare = mBaseFolderPath + FILE_TO_SHARE; + mFullPath2NonExistentFile = mBaseFolderPath + NON_EXISTENT_FILE; File textFile = mActivity.extractAsset(TestActivity.ASSETS__TEXT_FILE_NAME); RemoteOperationResult result = mActivity.uploadFile( @@ -57,11 +65,13 @@ public class CreateShareTest extends RemoteTest { Utils.logAndThrow(LOG_TAG, result); } } - + /** - * Test Create Share: the server must support SHARE API + * Test creation of public shares */ public void testCreatePublicShare() { + + /// Successful cases RemoteOperationResult result = mActivity.createShare( mFullPath2FileToShare, ShareType.PUBLIC_LINK, @@ -70,6 +80,141 @@ public class CreateShareTest extends RemoteTest { "", 1); assertTrue(result.isSuccess()); + + /// Failed cases + + // file doesn't exist + result = mActivity.createShare( + mFullPath2NonExistentFile, + ShareType.PUBLIC_LINK, + "", + false, + "", + 1); + assertFalse(result.isSuccess()); + assertEquals( + RemoteOperationResult.ResultCode.SHARE_NOT_FOUND, + result.getCode() + ); + assertTrue( // error message from server as part of the result + result.getData().size() == 1 && + result.getData().get(0) instanceof String + ); + + } + + + /** + * Test creation of private shares with groups + */ + public void testCreatePrivateShareWithUser() { + + /// Successful cases + RemoteOperationResult result = mActivity.createShare( + mFullPath2FileToShare, + ShareType.USER, + "admin", + false, + "", + 31); + assertTrue(result.isSuccess()); + + + /// Failed cases + + // sharee doesn't exist + result = mActivity.createShare( + mFullPath2FileToShare, + ShareType.USER, + "no_exist", + false, + "", + 31); + assertFalse(result.isSuccess()); + assertEquals( + RemoteOperationResult.ResultCode.SHARE_WRONG_PARAMETER, + result.getCode() + ); + assertTrue( // error message from server as part of the result + result.getData().size() == 1 && + result.getData().get(0) instanceof String + ); + + // file doesn't exist + result = mActivity.createShare( + mFullPath2NonExistentFile, + ShareType.USER, + "admin", + false, + "", + 31); + assertFalse(result.isSuccess()); + assertEquals( + RemoteOperationResult.ResultCode.SHARE_NOT_FOUND, + result.getCode() + ); + assertTrue( // error message from server as part of the result + result.getData().size() == 1 && + result.getData().get(0) instanceof String + ); + + } + + + /** + * Test creation of private shares with groups + */ + public void testCreatePrivateShareWithGroup() { + + /// Successful cases + RemoteOperationResult result = mActivity.createShare( + mFullPath2FileToShare, + ShareType.GROUP, + "admin", + false, + "", + 1); + assertTrue(result.isSuccess()); + + + /// Failed cases + + // sharee doesn't exist + result = mActivity.createShare( + mFullPath2FileToShare, + ShareType.GROUP, + "no_exist", + false, + "", + 31); + assertFalse(result.isSuccess()); + assertEquals( + RemoteOperationResult.ResultCode.SHARE_WRONG_PARAMETER, + result.getCode() + ); + assertTrue( // error message from server as part of the result + result.getData().size() == 1 && + result.getData().get(0) instanceof String + ); + + // file doesn't exist + result = mActivity.createShare( + mFullPath2NonExistentFile, + ShareType.GROUP, + "admin", + false, + "", + 31); + assertFalse(result.isSuccess()); + assertEquals( + RemoteOperationResult.ResultCode.SHARE_NOT_FOUND, + result.getCode() + ); + assertTrue( // error message from server as part of the result + result.getData().size() == 1 && + result.getData().get(0) instanceof String + ); + }