Skip to content

Commit ed44030

Browse files
committed
Fixes #36 : Add support for mailbox.org
1 parent 55cb12f commit ed44030

File tree

4 files changed

+185
-7
lines changed

4 files changed

+185
-7
lines changed

app/src/main/java/com/phpbg/easysync/dav/WebDavService.kt

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ import java.nio.file.attribute.FileTime
6868
import java.time.ZonedDateTime
6969
import java.time.format.DateTimeFormatter.ISO_DATE_TIME
7070
import java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME
71+
import java.time.format.DateTimeParseException
7172
import java.util.concurrent.ConcurrentHashMap
7273
import java.util.concurrent.TimeUnit
7374

74-
7575
private const val TAG = "WebDavService"
7676

7777
class WebDavService(
@@ -313,6 +313,20 @@ class WebDavService(
313313
return splitted.joinToString("/") { UrlEscapers.urlPathSegmentEscaper().escape(it) }
314314
}
315315

316+
fun parseIsoOr1123DateTime(dateTimeString: String?): ZonedDateTime {
317+
return try {
318+
ZonedDateTime.parse(
319+
dateTimeString,
320+
ISO_DATE_TIME
321+
)
322+
} catch (e: DateTimeParseException) {
323+
ZonedDateTime.parse(
324+
dateTimeString,
325+
RFC_1123_DATE_TIME
326+
)
327+
}
328+
}
329+
316330
fun parsePropfind(reader: Reader, rootPath: RootPath): ArrayList<Resource> {
317331
val parserFactory = XmlPullParserFactory.newInstance()
318332
parserFactory.isNamespaceAware = true
@@ -341,12 +355,13 @@ class WebDavService(
341355

342356
XmlPullParser.END_TAG -> when (tag) {
343357
"href" -> resource = resource.copy(href = URLDecoder.decode(text, "UTF-8"))
344-
"creationdate" -> resource = resource.copy(
345-
creationdate = ZonedDateTime.parse(
346-
text,
347-
ISO_DATE_TIME // encoded in rfc3339 according to webdav spec
348-
).toInstant()
349-
)
358+
"creationdate" -> {
359+
resource = resource.copy(
360+
// should be encoded in rfc3339 according to webdav spec
361+
// but mailbox.org uses RFC 1123, so support both
362+
creationdate = parseIsoOr1123DateTime(text).toInstant()
363+
)
364+
}
350365

351366
"getlastmodified" -> resource = resource.copy(
352367
getlastmodified = ZonedDateTime.parse(

app/src/test/java/com/phpbg/easysync/dav/ParseTest.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,25 @@ class ParseTest {
3838
assert(res.size == 8)
3939
}
4040

41+
@Test
42+
fun propfind_mailbox_org_works() {
43+
val stream = this.javaClass.classLoader.getResourceAsStream("propfind_mailbox_org.xml")
44+
val rootPath = RootPath("https://foo")
45+
val res = WebDavService.parsePropfind(stream.reader(), rootPath)
46+
assert(res.size == 4)
47+
val expected = Resource(
48+
rootPath = rootPath,
49+
href = "/servlet/webdav.infostore/",
50+
creationdate = ZonedDateTime.parse("Tue, 11 Jun 2024 20:35:13 GMT", DateTimeFormatter.RFC_1123_DATE_TIME).toInstant(),
51+
getlastmodified = ZonedDateTime.parse("Tue, 11 Jun 2024 20:35:13 GMT", DateTimeFormatter.RFC_1123_DATE_TIME).toInstant(),
52+
isCollection = true,
53+
getetag = null,
54+
getcontentlength = null,
55+
getcontenttype = "httpd/unix-directory"
56+
)
57+
assert(expected == res.first())
58+
}
59+
4160
@Test
4261
fun propfind_file_works() {
4362
val stream = this.javaClass.classLoader.getResourceAsStream("file.xml")
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<D:multistatus xmlns:D="DAV:">
3+
<D:response>
4+
<D:href>/servlet/webdav.infostore/</D:href>
5+
<D:propstat>
6+
<D:prop>
7+
<D:creationdate xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Tue, 11 Jun 2024 20:35:13 GMT</D:creationdate>
8+
<D:displayname>infostore</D:displayname>
9+
<D:getcontenttype>httpd/unix-directory</D:getcontenttype>
10+
<D:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Tue, 11 Jun 2024 20:35:13 GMT</D:getlastmodified>
11+
<D:resourcetype>
12+
<D:collection />
13+
</D:resourcetype>
14+
<D:lockdiscovery />
15+
<D:supportedlock>
16+
<D:lockentry>
17+
<D:lockscope>
18+
<D:exclusive />
19+
</D:lockscope>
20+
<D:locktype>
21+
<D:write />
22+
</D:locktype>
23+
</D:lockentry>
24+
<D:lockentry>
25+
<D:lockscope>
26+
<D:shared />
27+
</D:lockscope>
28+
<D:locktype>
29+
<D:write />
30+
</D:locktype>
31+
</D:lockentry>
32+
</D:supportedlock>
33+
<D:source />
34+
</D:prop>
35+
<D:status>HTTP/1.1 200 OK</D:status>
36+
</D:propstat>
37+
</D:response>
38+
<D:response>
39+
<D:href>/servlet/webdav.infostore/Public%20infostore/</D:href>
40+
<D:propstat>
41+
<D:prop>
42+
<D:creationdate xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Tue, 11 Jun 2024 20:35:13 GMT</D:creationdate>
43+
<D:displayname>Public infostore</D:displayname>
44+
<D:getcontenttype>httpd/unix-directory</D:getcontenttype>
45+
<D:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Tue, 11 Jun 2024 20:35:13 GMT</D:getlastmodified>
46+
<D:resourcetype>
47+
<D:collection />
48+
</D:resourcetype>
49+
<D:lockdiscovery />
50+
<D:supportedlock>
51+
<D:lockentry>
52+
<D:lockscope>
53+
<D:exclusive />
54+
</D:lockscope>
55+
<D:locktype>
56+
<D:write />
57+
</D:locktype>
58+
</D:lockentry>
59+
<D:lockentry>
60+
<D:lockscope>
61+
<D:shared />
62+
</D:lockscope>
63+
<D:locktype>
64+
<D:write />
65+
</D:locktype>
66+
</D:lockentry>
67+
</D:supportedlock>
68+
<D:source />
69+
</D:prop>
70+
<D:status>HTTP/1.1 200 OK</D:status>
71+
</D:propstat>
72+
</D:response>
73+
<D:response>
74+
<D:href>/servlet/webdav.infostore/Trash/</D:href>
75+
<D:propstat>
76+
<D:prop>
77+
<D:creationdate xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Tue, 11 Jun 2024 20:35:13 GMT</D:creationdate>
78+
<D:displayname>Trash</D:displayname>
79+
<D:getcontenttype>httpd/unix-directory</D:getcontenttype>
80+
<D:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Tue, 11 Jun 2024 20:35:13 GMT</D:getlastmodified>
81+
<D:resourcetype>
82+
<D:collection />
83+
</D:resourcetype>
84+
<D:lockdiscovery />
85+
<D:supportedlock>
86+
<D:lockentry>
87+
<D:lockscope>
88+
<D:exclusive />
89+
</D:lockscope>
90+
<D:locktype>
91+
<D:write />
92+
</D:locktype>
93+
</D:lockentry>
94+
<D:lockentry>
95+
<D:lockscope>
96+
<D:shared />
97+
</D:lockscope>
98+
<D:locktype>
99+
<D:write />
100+
</D:locktype>
101+
</D:lockentry>
102+
</D:supportedlock>
103+
<D:source />
104+
</D:prop>
105+
<D:status>HTTP/1.1 200 OK</D:status>
106+
</D:propstat>
107+
</D:response>
108+
<D:response>
109+
<D:href>/servlet/webdav.infostore/Userstore/</D:href>
110+
<D:propstat>
111+
<D:prop>
112+
<D:creationdate xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Tue, 11 Jun 2024 20:35:13 GMT</D:creationdate>
113+
<D:displayname>Userstore</D:displayname>
114+
<D:getcontenttype>httpd/unix-directory</D:getcontenttype>
115+
<D:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Tue, 11 Jun 2024 20:35:13 GMT</D:getlastmodified>
116+
<D:resourcetype>
117+
<D:collection />
118+
</D:resourcetype>
119+
<D:lockdiscovery />
120+
<D:supportedlock>
121+
<D:lockentry>
122+
<D:lockscope>
123+
<D:exclusive />
124+
</D:lockscope>
125+
<D:locktype>
126+
<D:write />
127+
</D:locktype>
128+
</D:lockentry>
129+
<D:lockentry>
130+
<D:lockscope>
131+
<D:shared />
132+
</D:lockscope>
133+
<D:locktype>
134+
<D:write />
135+
</D:locktype>
136+
</D:lockentry>
137+
</D:supportedlock>
138+
<D:source />
139+
</D:prop>
140+
<D:status>HTTP/1.1 200 OK</D:status>
141+
</D:propstat>
142+
</D:response>
143+
</D:multistatus>

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ It should work with any DAV compliant server.
8989
* Nextcloud / owncloud (full support: preserves file creation timestamps)
9090
* nginx (basic support: does not preserve file creation timestamps, no etag support)
9191
* apache (basic support: does not preserve file creation timestamps)
92+
* mailbox.org (basic support: does not preserve file creation timestamps, no etag support, use `https://office.mailbox.org/servlet/webdav.infostore` as url and `/Userstore/<firstname lastname>/Documents` as remote folder)
9293
* *add your server here*
9394

9495
## Sync is slow on Nextcloud

0 commit comments

Comments
 (0)