Skip to content

Commit 39fcd31

Browse files
wip
Signed-off-by: tobiasKaminsky <[email protected]>
1 parent 60a3055 commit 39fcd31

File tree

24 files changed

+1338
-90
lines changed

24 files changed

+1338
-90
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "dav4jvm"]
2+
path = dav4jvm
3+
url = /home/tobi/projekt/github/bitfireAT/dav4jvm

dav4jvm

Submodule dav4jvm added at c61e4b0

library/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ configurations {
5050
dependencies {
5151
implementation 'org.apache.jackrabbit:jackrabbit-webdav:2.13.5'
5252
api 'com.squareup.okhttp3:okhttp:5.0.0-alpha.10'
53-
implementation 'com.gitlab.bitfireAT:dav4jvm:2.1.3' // in transition phase, we use old and new libs
53+
implementation 'com.github.bitfireAT:dav4jvm:2.1.4'
54+
// in transition phase, we use old and new libs
5455
implementation group: 'com.google.code.gson', name: 'gson', version: '2.9.1'
5556
implementation 'androidx.annotation:annotation:1.5.0'
5657
compileOnly 'com.google.code.findbugs:annotations:3.0.1u2'

library/src/androidTest/java/com/owncloud/android/AbstractIT.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ public static void beforeAll() throws InterruptedException,
112112
String userId = loginName; // for test same as userId
113113
String credentials = Credentials.basic(loginName, password);
114114
nextcloudClient = new NextcloudClient(url, userId, credentials, context);
115+
nextcloudClient.setUserId(userId);
115116

116117
waitForServer(client, url);
117118
testConnection();
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
/*
2+
* Nextcloud Android client application
3+
*
4+
* @author Tobias Kaminsky
5+
* Copyright (C) 2022 Tobias Kaminsky
6+
* Copyright (C) 2022 Nextcloud GmbH
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Affero General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU Affero General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Affero General Public License
19+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
*
21+
*/
22+
23+
package com.owncloud.android
24+
25+
import at.bitfire.dav4jvm.DavResource
26+
import at.bitfire.dav4jvm.PropertyRegistry
27+
import at.bitfire.dav4jvm.Response
28+
import at.bitfire.dav4jvm.property.CreationDate
29+
import at.bitfire.dav4jvm.property.GetContentType
30+
import at.bitfire.dav4jvm.property.GetLastModified
31+
import at.bitfire.dav4jvm.property.ResourceType
32+
import com.nextcloud.common.NextcloudAuthenticator
33+
import com.nextcloud.talk.components.filebrowser.models.properties.OCId
34+
import com.nextcloud.talk.components.filebrowser.models.properties.OCOwnerDisplayName
35+
import com.nextcloud.talk.components.filebrowser.models.properties.OCOwnerId
36+
import com.nextcloud.talk.components.filebrowser.models.properties.OCSize
37+
import com.owncloud.android.lib.common.network.WebdavUtils
38+
import com.owncloud.android.lib.common.utils.WebDavFileUtils
39+
import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation
40+
import com.owncloud.android.lib.resources.files.ReadFolderRemoteOperation
41+
import com.owncloud.android.lib.resources.files.SearchRemoteOperation
42+
import com.owncloud.android.lib.resources.files.ToggleFavoriteRemoteOperation
43+
import com.owncloud.android.lib.resources.files.UploadFileRemoteOperation
44+
import com.owncloud.android.lib.resources.files.model.RemoteFile
45+
import com.owncloud.android.lib.resources.files.webdav.NCEtag
46+
import com.owncloud.android.lib.resources.files.webdav.NCFavorite
47+
import com.owncloud.android.lib.resources.files.webdav.NCMountType
48+
import com.owncloud.android.lib.resources.files.webdav.Permissions
49+
import com.owncloud.android.lib.resources.status.OCCapability
50+
import okhttp3.HttpUrl.Companion.toHttpUrl
51+
import org.apache.jackrabbit.webdav.DavConstants
52+
import org.junit.Assert.assertEquals
53+
import org.junit.Assert.assertTrue
54+
import org.junit.Test
55+
import java.io.IOException
56+
57+
class Dav4JVMtest : AbstractIT() {
58+
@Test
59+
@Throws(IOException::class)
60+
fun singlePropfind() {
61+
val path = "/testFolder/"
62+
63+
// create folder
64+
CreateFolderRemoteOperation(
65+
path,
66+
true
67+
).execute(client).isSuccess
68+
69+
// verify folder
70+
assertTrue(ReadFolderRemoteOperation(path).execute(client).isSuccess)
71+
72+
// add favorite
73+
assertTrue(ToggleFavoriteRemoteOperation(true, path).execute(client).isSuccess)
74+
75+
// do old read folder operation to compare data against it
76+
val result = ReadFolderRemoteOperation(path).execute(client).data as List<RemoteFile>
77+
val oldRemoteFile = result[0]
78+
79+
// new
80+
val httpUrl = (nextcloudClient.filesDavUri.toString() + path).toHttpUrl()
81+
82+
var davResponse: Response? = null
83+
84+
val memberElements: MutableList<Response> = ArrayList()
85+
var rootElement: Response? = null
86+
87+
// disable redirect
88+
val client = nextcloudClient.client
89+
.newBuilder()
90+
.followRedirects(false)
91+
.authenticator(NextcloudAuthenticator(nextcloudClient.credentials, "Authorization"))
92+
.build()
93+
94+
// register custom property
95+
registerProperties()
96+
97+
DavResource(
98+
client,
99+
httpUrl
100+
)
101+
102+
DavResource(
103+
client,
104+
httpUrl
105+
).propfind(
106+
DavConstants.DEPTH_1,
107+
CreationDate.NAME,
108+
NCFavorite.NAME,
109+
NCEtag.NAME,
110+
GetLastModified.NAME,
111+
GetContentType.NAME,
112+
ResourceType.NAME,
113+
Permissions.NAME,
114+
OCId.NAME,
115+
OCSize.NAME,
116+
NCMountType.NAME,
117+
OCOwnerId.NAME,
118+
OCOwnerDisplayName.NAME
119+
) { response: Response, hrefRelation: Response.HrefRelation? ->
120+
davResponse = response
121+
when (hrefRelation) {
122+
Response.HrefRelation.MEMBER -> memberElements.add(response)
123+
Response.HrefRelation.SELF -> rootElement = response
124+
Response.HrefRelation.OTHER -> {}
125+
else -> {}
126+
}
127+
}
128+
129+
assertTrue(davResponse?.isSuccess() == true)
130+
assertTrue(rootElement != null)
131+
assertEquals(0, memberElements.size)
132+
133+
val remoteFile = WebDavFileUtils().parseResponse(rootElement, nextcloudClient.filesDavUri)
134+
135+
val date = davResponse?.get(CreationDate::class.java)
136+
assertEquals(
137+
oldRemoteFile.creationTimestamp,
138+
(WebdavUtils.parseResponseDate(date?.creationDate)?.time ?: 0) / 1000
139+
)
140+
141+
assertTrue(oldRemoteFile.isFavorite)
142+
val favorite = davResponse?.get(NCFavorite::class.java)
143+
assertTrue(favorite?.isOcFavorite == true)
144+
145+
assertEquals(oldRemoteFile.remotePath, remoteFile.remotePath)
146+
assertEquals(oldRemoteFile.mimeType, remoteFile.mimeType)
147+
assertEquals(oldRemoteFile.length, remoteFile.length)
148+
assertEquals(oldRemoteFile.creationTimestamp, remoteFile.creationTimestamp)
149+
// assertEquals(oldRemoteFile.modifiedTimestamp, remoteFile.modifiedTimestamp)
150+
assertEquals(oldRemoteFile.uploadTimestamp, remoteFile.uploadTimestamp)
151+
assertEquals(oldRemoteFile.etag, remoteFile.etag)
152+
assertEquals(oldRemoteFile.permissions, remoteFile.permissions)
153+
assertEquals(oldRemoteFile.remoteId, remoteFile.remoteId)
154+
assertEquals(oldRemoteFile.size, remoteFile.size)
155+
assertEquals(oldRemoteFile.isFavorite, remoteFile.isFavorite)
156+
assertEquals(oldRemoteFile.isEncrypted, remoteFile.isEncrypted)
157+
assertEquals(oldRemoteFile.mountType, remoteFile.mountType)
158+
assertEquals(oldRemoteFile.ownerId, remoteFile.ownerId)
159+
assertEquals(oldRemoteFile.ownerDisplayName, remoteFile.ownerDisplayName)
160+
assertEquals(oldRemoteFile.unreadCommentsCount, remoteFile.unreadCommentsCount)
161+
assertEquals(oldRemoteFile.isHasPreview, remoteFile.isHasPreview)
162+
assertEquals(oldRemoteFile.note, remoteFile.note)
163+
assertEquals(oldRemoteFile.sharees, remoteFile.sharees)
164+
assertEquals(oldRemoteFile.richWorkspace, remoteFile.richWorkspace)
165+
assertEquals(oldRemoteFile.isLocked, remoteFile.isLocked)
166+
assertEquals(oldRemoteFile.lockType, remoteFile.lockType)
167+
assertEquals(oldRemoteFile.lockOwner, remoteFile.lockOwner)
168+
assertEquals(oldRemoteFile.lockOwnerDisplayName, remoteFile.lockOwnerDisplayName)
169+
assertEquals(oldRemoteFile.lockTimestamp, remoteFile.lockTimestamp)
170+
assertEquals(oldRemoteFile.lockOwnerEditor, remoteFile.lockOwnerEditor)
171+
assertEquals(oldRemoteFile.lockTimeout, remoteFile.lockTimeout)
172+
assertEquals(oldRemoteFile.lockToken, remoteFile.lockToken)
173+
assertEquals(oldRemoteFile.localId, remoteFile.localId)
174+
175+
// assertEquals(oldRemoteFile, remoteFile)
176+
}
177+
178+
@Test
179+
fun search() {
180+
val path = "/testFolder/"
181+
182+
// create folder
183+
// assertTrue(
184+
CreateFolderRemoteOperation(
185+
path,
186+
true
187+
).execute(client).isSuccess
188+
// )
189+
190+
// create file
191+
val filePath = createFile("text")
192+
val remotePath = "/test.md"
193+
194+
assertTrue(
195+
UploadFileRemoteOperation(
196+
filePath,
197+
remotePath,
198+
"text/markdown",
199+
"",
200+
RANDOM_MTIME,
201+
System.currentTimeMillis(),
202+
true
203+
).execute(client).isSuccess
204+
)
205+
206+
registerProperties()
207+
208+
var ror = SearchRemoteOperation(
209+
"test",
210+
SearchRemoteOperation.SearchType.FILE_SEARCH,
211+
false,
212+
OCCapability(23, 0, 0)
213+
).execute(
214+
client
215+
)
216+
217+
assertTrue(ror.isSuccess)
218+
assertEquals(2, ror.resultData.size)
219+
220+
val oldRemoteFile = ror.resultData[0]
221+
assertEquals(path, oldRemoteFile.remotePath)
222+
223+
ror = SearchRemoteOperation(
224+
"test",
225+
SearchRemoteOperation.SearchType.FILE_SEARCH,
226+
false,
227+
OCCapability(23, 0, 0)
228+
).execute(
229+
nextcloudClient
230+
)
231+
232+
assertTrue(ror.isSuccess)
233+
assertEquals(2, ror.resultData.size)
234+
235+
val remoteFile = ror.resultData[0]
236+
assertEquals(path, remoteFile.remotePath)
237+
238+
assertEquals(oldRemoteFile.remoteId, remoteFile.remoteId)
239+
}
240+
241+
@Test
242+
fun proppatch() {
243+
assertTrue(false)
244+
}
245+
246+
private fun registerProperties() {
247+
val list = listOf(
248+
NCFavorite.Factory(),
249+
NCEtag.Factory(),
250+
Permissions.Factory(),
251+
OCId.Factory(),
252+
OCSize.Factory(),
253+
NCMountType.Factory(),
254+
OCOwnerId.Factory(),
255+
OCOwnerDisplayName.Factory()
256+
)
257+
258+
PropertyRegistry.register(list)
259+
}
260+
}

library/src/androidTest/java/com/owncloud/android/FileIT.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
*/
2727
package com.owncloud.android;
2828

29+
import static org.junit.Assert.assertEquals;
30+
import static org.junit.Assert.assertFalse;
31+
import static org.junit.Assert.assertTrue;
32+
2933
import android.net.Uri;
3034

3135
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
@@ -43,10 +47,6 @@
4347
import java.util.ArrayList;
4448
import java.util.List;
4549

46-
import static org.junit.Assert.assertEquals;
47-
import static org.junit.Assert.assertFalse;
48-
import static org.junit.Assert.assertTrue;
49-
5050
/**
5151
* Tests related to file operations
5252
*/
@@ -60,6 +60,7 @@ public void testCreateFolderSuccess() {
6060

6161
// verify folder
6262
assertTrue(new ReadFolderRemoteOperation(path).execute(client).isSuccess());
63+
assertTrue(new ReadFolderRemoteOperation(path).execute(nextcloudClient).isSuccess());
6364

6465
// remove folder
6566
assertTrue(new RemoveFileRemoteOperation(path).execute(client).isSuccess());
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Nextcloud Android client application
3+
*
4+
* @author Tobias Kaminsky
5+
* Copyright (C) 2022 Tobias Kaminsky
6+
* Copyright (C) 2022 Nextcloud GmbH
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Affero General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU Affero General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Affero General Public License
19+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
*
21+
*/
22+
23+
package com.nextcloud.common;
24+
25+
import androidx.annotation.NonNull;
26+
import androidx.annotation.Nullable;
27+
28+
import okhttp3.Authenticator;
29+
import okhttp3.Request;
30+
import okhttp3.Response;
31+
import okhttp3.Route;
32+
33+
public class NextcloudAuthenticator implements Authenticator {
34+
private String credentials;
35+
private String authenticatorType;
36+
37+
public NextcloudAuthenticator(@NonNull String credentials, @NonNull String authenticatorType) {
38+
this.credentials = credentials;
39+
this.authenticatorType = authenticatorType;
40+
}
41+
42+
@Nullable
43+
@Override
44+
public Request authenticate(@Nullable Route route, @NonNull Response response) {
45+
if (response.request().header(authenticatorType) != null) {
46+
return null;
47+
}
48+
49+
Response countedResponse = response;
50+
51+
int attemptsCount = 0;
52+
53+
while ((countedResponse = countedResponse.priorResponse()) != null) {
54+
attemptsCount++;
55+
if (attemptsCount == 3) {
56+
return null;
57+
}
58+
}
59+
60+
return response.request().newBuilder()
61+
.header(authenticatorType, credentials)
62+
.build();
63+
}
64+
}

0 commit comments

Comments
 (0)