1
- /* ownCloud Android Library is available under MIT license
2
- * @author masensio
3
- * @author David A. Velasco
4
- * @author David González Verdugo
5
- * Copyright (C) 2020 ownCloud GmbH
1
+ /*
2
+ * ownCloud Android client application
3
+ *
4
+ * @author masensio
5
+ * @author David A. Velasco
6
+ * @author David González Verdugo
7
+ * @author Fernando Sanz Velasco
8
+ * Copyright (C) 2021 ownCloud GmbH.
9
+ *
10
+ * This program is free software: you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License version 2,
12
+ * as published by the Free Software Foundation.
13
+ *
14
+ * This program is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
6
21
*
7
- * Permission is hereby granted, free of charge, to any person obtaining a copy
8
- * of this software and associated documentation files (the "Software"), to deal
9
- * in the Software without restriction, including without limitation the rights
10
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- * copies of the Software, and to permit persons to whom the Software is
12
- * furnished to do so, subject to the following conditions:
13
22
*
14
- * The above copyright notice and this permission notice shall be included in
15
- * all copies or substantial portions of the Software.
16
23
*
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
- * THE SOFTWARE.
25
24
*
26
25
*/
27
26
28
27
package com.owncloud.android.lib.resources.shares
29
28
29
+ import android.net.Uri
30
30
import com.owncloud.android.lib.common.OwnCloudClient
31
31
import com.owncloud.android.lib.common.http.HttpConstants
32
32
import com.owncloud.android.lib.common.http.methods.nonwebdav.PostMethod
33
33
import com.owncloud.android.lib.common.operations.RemoteOperation
34
34
import com.owncloud.android.lib.common.operations.RemoteOperationResult
35
+ import com.owncloud.android.lib.resources.CommonOcsResponse
35
36
import com.owncloud.android.lib.resources.shares.RemoteShare.Companion.INIT_EXPIRATION_DATE_IN_MILLIS
37
+ import com.owncloud.android.lib.resources.shares.responses.ShareItem
38
+ import com.squareup.moshi.JsonAdapter
39
+ import com.squareup.moshi.Moshi
40
+ import com.squareup.moshi.Types
36
41
import okhttp3.FormBody
37
42
import timber.log.Timber
43
+ import java.lang.reflect.Type
38
44
import java.net.URL
39
45
import java.text.SimpleDateFormat
40
46
import java.util.Calendar
41
47
import java.util.Locale
42
48
43
- /* *
44
- * Creates a new share. This allows sharing with a user or group or as a link.
45
- *
46
- * @author masensio
47
- * @author David A. Velasco
48
- * @author David González Verdugo
49
- */
50
-
51
49
/* *
52
50
* Constructor
53
51
*
@@ -71,6 +69,7 @@ class CreateRemoteShareOperation(
71
69
private val shareWith : String ,
72
70
private val permissions : Int
73
71
) : RemoteOperation<ShareResponse>() {
72
+
74
73
var name = " " // Name to set for the public link
75
74
76
75
var password: String = " " // Password to set for the public link
@@ -81,93 +80,120 @@ class CreateRemoteShareOperation(
81
80
82
81
var retrieveShareDetails = false // To retrieve more info about the just created share
83
82
84
- override fun run (client : OwnCloudClient ): RemoteOperationResult <ShareResponse > {
85
- var result: RemoteOperationResult <ShareResponse >
83
+ private fun buildRequestUri (baseUri : Uri ) =
84
+ baseUri.buildUpon()
85
+ .appendEncodedPath(OCS_ROUTE )
86
+ .appendQueryParameter(PARAM_FORMAT , VALUE_FORMAT )
87
+ .build()
88
+
89
+ private fun parseResponse (response : String ): ShareResponse ? {
90
+ val moshi = Moshi .Builder ().build()
91
+ val commonOcsType: Type = Types .newParameterizedType(CommonOcsResponse ::class .java, ShareItem ::class .java)
92
+ val adapter: JsonAdapter <CommonOcsResponse <ShareItem >> = moshi.adapter(commonOcsType)
93
+ val remoteShare = adapter.fromJson(response)?.ocs?.data?.toRemoteShare()
94
+ return ShareResponse (remoteShare?.let { listOf (it) } ? : listOf ())
95
+ }
86
96
87
- try {
88
- val formBodyBuilder = FormBody .Builder ()
89
- .add(PARAM_PATH , remoteFilePath)
90
- .add(PARAM_SHARE_TYPE , shareType.value.toString())
91
- .add(PARAM_SHARE_WITH , shareWith)
97
+ private fun onResultUnsuccessful (
98
+ method : PostMethod ,
99
+ response : String? ,
100
+ status : Int
101
+ ): RemoteOperationResult <ShareResponse > {
102
+ Timber .e(" Failed response while while creating new remote share operation " )
103
+ if (response != null ) {
104
+ Timber .e(" *** status code: $status ; response message: $response " )
105
+ } else {
106
+ Timber .e(" *** status code: $status " )
107
+ }
108
+ return RemoteOperationResult (method)
109
+ }
92
110
93
- if (name.isNotEmpty()) {
94
- formBodyBuilder.add(PARAM_NAME , name)
95
- }
111
+ private fun onRequestSuccessful (response : String? ): RemoteOperationResult <ShareResponse > {
112
+ val result = RemoteOperationResult <ShareResponse >(RemoteOperationResult .ResultCode .OK )
113
+ Timber .d(" Successful response: $response " )
114
+ result.data = parseResponse(response!! )
115
+ Timber .d(" *** Creating new remote share operation completed " )
116
+ return result
117
+ }
96
118
97
- if (expirationDateInMillis > INIT_EXPIRATION_DATE_IN_MILLIS ) {
98
- val dateFormat = SimpleDateFormat (FORMAT_EXPIRATION_DATE , Locale .getDefault())
99
- val expirationDate = Calendar .getInstance()
100
- expirationDate.timeInMillis = expirationDateInMillis
101
- val formattedExpirationDate = dateFormat.format(expirationDate.time)
102
- formBodyBuilder.add(PARAM_EXPIRATION_DATE , formattedExpirationDate)
103
- }
119
+ private fun createFormBodyBuilder (): FormBody .Builder {
104
120
105
- if (publicUpload) {
106
- formBodyBuilder.add(PARAM_PUBLIC_UPLOAD , publicUpload.toString())
107
- }
108
- if (password.isNotEmpty()) {
109
- formBodyBuilder.add(PARAM_PASSWORD , password)
110
- }
111
- if (RemoteShare .DEFAULT_PERMISSION != permissions) {
112
- formBodyBuilder.add(PARAM_PERMISSIONS , permissions.toString())
113
- }
121
+ val formBodyBuilder = FormBody .Builder ()
122
+ .add(PARAM_PATH , remoteFilePath)
123
+ .add(PARAM_SHARE_TYPE , shareType.value.toString())
124
+ .add(PARAM_SHARE_WITH , shareWith)
114
125
115
- val requestUri = client.baseUri
116
- val uriBuilder = requestUri.buildUpon( )
117
- uriBuilder.appendEncodedPath( ShareUtils . SHARING_API_PATH )
126
+ if (name.isNotEmpty()) {
127
+ formBodyBuilder.add( PARAM_NAME , name )
128
+ }
118
129
119
- val postMethod = PostMethod (URL (uriBuilder.build().toString()), formBodyBuilder.build())
130
+ if (expirationDateInMillis > INIT_EXPIRATION_DATE_IN_MILLIS ) {
131
+ val dateFormat = SimpleDateFormat (FORMAT_EXPIRATION_DATE , Locale .getDefault())
132
+ val expirationDate = Calendar .getInstance()
133
+ expirationDate.timeInMillis = expirationDateInMillis
134
+ val formattedExpirationDate = dateFormat.format(expirationDate.time)
135
+ formBodyBuilder.add(PARAM_EXPIRATION_DATE , formattedExpirationDate)
136
+ }
120
137
121
- postMethod.setRequestHeader(HttpConstants .CONTENT_TYPE_HEADER , HttpConstants .CONTENT_TYPE_URLENCODED_UTF8 )
122
- postMethod.addRequestHeader(OCS_API_HEADER , OCS_API_HEADER_VALUE )
138
+ if (publicUpload) {
139
+ formBodyBuilder.add(PARAM_PUBLIC_UPLOAD , publicUpload.toString())
140
+ }
141
+ if (password.isNotEmpty()) {
142
+ formBodyBuilder.add(PARAM_PASSWORD , password)
143
+ }
144
+ if (RemoteShare .DEFAULT_PERMISSION != permissions) {
145
+ formBodyBuilder.add(PARAM_PERMISSIONS , permissions.toString())
146
+ }
123
147
124
- val status = client.executeHttpMethod(postMethod)
148
+ return formBodyBuilder
149
+ }
125
150
126
- val parser = ShareToRemoteOperationResultParser (
127
- ShareXMLParser ()
128
- )
151
+ override fun run (client : OwnCloudClient ): RemoteOperationResult <ShareResponse > {
152
+ val requestUri = buildRequestUri(client.baseUri)
129
153
130
- if (isSuccess(status)) {
131
- parser.oneOrMoreSharesRequired = true
132
- parser.ownCloudVersion = client.ownCloudVersion
133
- parser.serverBaseUri = client.baseUri
134
- result = parser.parse(postMethod.getResponseBodyAsString())
154
+ val formBodyBuilder = createFormBodyBuilder()
135
155
136
- if (result.isSuccess && retrieveShareDetails) {
137
- // retrieve more info - POST only returns the index of the new share
138
- val emptyShare = result.data.shares[0 ]
139
- val getShares = GetRemoteShareOperation (
140
- emptyShare.id
141
- )
142
- val remoteOperationResult = getShares.execute(client)
156
+ val postMethod = PostMethod (URL (requestUri.toString()), formBodyBuilder.build()).apply {
157
+ setRequestHeader(HttpConstants .CONTENT_TYPE_HEADER , HttpConstants .CONTENT_TYPE_URLENCODED_UTF8 )
158
+ addRequestHeader(OCS_API_HEADER , OCS_API_HEADER_VALUE )
159
+ }
143
160
144
- result = RemoteOperationResult (remoteOperationResult)
145
- result.data = remoteOperationResult.data
146
- }
161
+ return try {
162
+ val status = client.executeHttpMethod(postMethod)
163
+ val response = postMethod.getResponseBodyAsString()
147
164
165
+ if (! isSuccess(status)) {
166
+ onResultUnsuccessful(postMethod, response, status)
148
167
} else {
149
- result = parser.parse(postMethod.getResponseBodyAsString() )
168
+ onRequestSuccessful(response )
150
169
}
151
170
152
171
} catch (e: Exception ) {
153
- result = RemoteOperationResult (e )
154
- Timber .e(e, " Exception while Creating New Share " )
172
+ Timber .e(e, " Exception while creating new remote share operation " )
173
+ RemoteOperationResult (e )
155
174
}
156
-
157
- return result
158
175
}
159
176
160
177
private fun isSuccess (status : Int ): Boolean = status == HttpConstants .HTTP_OK
161
178
162
179
companion object {
180
+
181
+ // OCS Route
182
+ private const val OCS_ROUTE = " ocs/v2.php/apps/files_sharing/api/v1/shares"
183
+
184
+ // Arguments - names
185
+ private const val PARAM_FORMAT = " format"
163
186
private const val PARAM_NAME = " name"
164
- private const val PARAM_PASSWORD = " password"
165
187
private const val PARAM_EXPIRATION_DATE = " expireDate"
166
- private const val PARAM_PUBLIC_UPLOAD = " publicUpload"
167
188
private const val PARAM_PATH = " path"
168
189
private const val PARAM_SHARE_TYPE = " shareType"
169
190
private const val PARAM_SHARE_WITH = " shareWith"
191
+ private const val PARAM_PASSWORD = " password"
192
+ private const val PARAM_PUBLIC_UPLOAD = " publicUpload"
170
193
private const val PARAM_PERMISSIONS = " permissions"
194
+
195
+ // Arguments - constant values
196
+ private const val VALUE_FORMAT = " json"
171
197
private const val FORMAT_EXPIRATION_DATE = " yyyy-MM-dd"
172
198
}
173
199
}
0 commit comments