Skip to content

Commit b9e8471

Browse files
committed
Feat!: Add WebDAV support
Bug: #191
1 parent ce44215 commit b9e8471

29 files changed

+1970
-4
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ An open source Material Design file manager, for Android 5.0+.
2222
- Breadcrumbs: Navigate in the filesystem with ease.
2323
- Root support: View and manage files with root access.
2424
- Archive support: View, extract and create common compressed files.
25-
- NAS support: View and manage files on FTP, SFTP and SMB servers.
25+
- NAS support: View and manage files on FTP, SFTP, SMB and WebDAV servers.
2626
- Themes: Customizable UI colors, plus night mode with optional true black.
2727
- Linux-aware: Like [Nautilus](https://wiki.gnome.org/action/show/Apps/Files), knows symbolic links, file permissions and SELinux context.
2828
- Robust: Uses Linux system calls under the hood, not yet another [`ls` parser](https://news.ycombinator.com/item?id=7994720).

README_zh-CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
- 面包屑导航栏:点击导航栏所显示路径中的任一文件夹即可快速访问。
2121
- Root 支持:使用 root 权限查看和管理文件。
2222
- 压缩文件支持:查看、提取和创建常见的压缩文件。
23-
- NAS 支持:查看和管理 FTP、SFTP 和 SMB 服务器上的文件。
23+
- NAS 支持:查看和管理 FTP、SFTP、SMBWebDAV 服务器上的文件。
2424
- 主题:可定制的界面颜色,以及可选纯黑的夜间模式。
2525
- Linux 友好:类似 [Nautilus](https://wiki.gnome.org/action/show/Apps/Files),支持符号链接、文件权限和 SELinux 上下文。
2626
- 健壮性:使用 Linux 系统调用实现,而不是另一个 [`ls` 解析器](https://news.ycombinator.com/item?id=7994720)

app/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ repositories {
104104
}
105105
}
106106
dependencies {
107+
// TODO: Remove DavResource.moveCompat once https://github.com/bitfireAT/dav4jvm/issues/39 is
108+
// fixed.
109+
implementation 'com.github.bitfireAT:dav4jvm:2.2.1'
107110
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
108111
releaseImplementation 'com.github.mypplication:stetho-noop:1.1'
109112
implementation 'com.github.topjohnwu.libsu:service:5.2.2'
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) 2024 Hai Zhang <[email protected]>
3+
* All Rights Reserved.
4+
*/
5+
6+
package at.bitfire.dav4jvm;
7+
8+
import java.io.IOException;
9+
10+
import androidx.annotation.NonNull;
11+
import at.bitfire.dav4jvm.exception.DavException;
12+
import at.bitfire.dav4jvm.exception.HttpException;
13+
import kotlin.jvm.functions.Function0;
14+
import okhttp3.Response;
15+
16+
public class DavResourceAccessor {
17+
private DavResourceAccessor() {}
18+
19+
public static void checkStatus(@NonNull DavResource davResource, @NonNull Response response)
20+
throws HttpException {
21+
davResource.checkStatus(response);
22+
}
23+
24+
public static Response followRedirects(@NonNull DavResource davResource,
25+
@NonNull Function0<Response> sendRequest) throws DavException, IOException {
26+
return davResource.followRedirects$build(sendRequest);
27+
}
28+
}

app/src/main/java/me/zhanghai/android/files/app/SystemServices.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import androidx.core.app.NotificationManagerCompat
1717
import androidx.preference.PreferenceManager
1818
import me.zhanghai.android.files.compat.getSystemServiceCompat
1919
import me.zhanghai.android.files.compat.mainExecutorCompat
20+
import okhttp3.OkHttpClient
2021
import java.util.concurrent.Executor
2122

2223
val appClassLoader = AppProvider::class.java.classLoader
@@ -31,6 +32,8 @@ val defaultSharedPreferences: SharedPreferences by lazy {
3132
PreferenceManager.getDefaultSharedPreferences(application)
3233
}
3334

35+
val okHttpClient: OkHttpClient by lazy { OkHttpClient() }
36+
3437
val inputMethodManager: InputMethodManager by lazy {
3538
application.getSystemServiceCompat(InputMethodManager::class.java)
3639
}

app/src/main/java/me/zhanghai/android/files/compat/DateTimeCompat.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,10 @@ package me.zhanghai.android.files.compat
33
import org.threeten.bp.DateTimeUtils
44
import org.threeten.bp.Instant
55
import java.util.Calendar
6+
import java.util.Date
67

78
fun Calendar.toInstantCompat(): Instant = DateTimeUtils.toInstant(this)
9+
10+
fun Date.toInstantCompat(): Instant = DateTimeUtils.toInstant(this)
11+
12+
fun Instant.toDateCompat(): Date = DateTimeUtils.toDate(this)

app/src/main/java/me/zhanghai/android/files/provider/FileSystemProviders.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import me.zhanghai.android.files.provider.linux.LinuxFileSystemProvider
1919
import me.zhanghai.android.files.provider.root.isRunningAsRoot
2020
import me.zhanghai.android.files.provider.sftp.SftpFileSystemProvider
2121
import me.zhanghai.android.files.provider.smb.SmbFileSystemProvider
22+
import me.zhanghai.android.files.provider.webdav.WebDavFileSystemProvider
23+
import me.zhanghai.android.files.provider.webdav.WebDavsFileSystemProvider
2224

2325
object FileSystemProviders {
2426
/**
@@ -42,6 +44,8 @@ object FileSystemProviders {
4244
FileSystemProvider.installProvider(FtpesFileSystemProvider)
4345
FileSystemProvider.installProvider(SftpFileSystemProvider)
4446
FileSystemProvider.installProvider(SmbFileSystemProvider)
47+
FileSystemProvider.installProvider(WebDavFileSystemProvider)
48+
FileSystemProvider.installProvider(WebDavsFileSystemProvider)
4549
}
4650
Files.installFileTypeDetector(AndroidFileTypeDetector)
4751
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package me.zhanghai.android.files.provider.webdav
2+
3+
import at.bitfire.dav4jvm.exception.ConflictException
4+
import at.bitfire.dav4jvm.exception.DavException
5+
import at.bitfire.dav4jvm.exception.ForbiddenException
6+
import at.bitfire.dav4jvm.exception.NotFoundException
7+
import at.bitfire.dav4jvm.exception.UnauthorizedException
8+
import java8.nio.file.AccessDeniedException
9+
import java8.nio.file.FileAlreadyExistsException
10+
import java8.nio.file.FileSystemException
11+
import java8.nio.file.NoSuchFileException
12+
import me.zhanghai.android.files.provider.webdav.client.DavIOException
13+
14+
fun DavException.toFileSystemException(
15+
file: String?,
16+
other: String? = null
17+
): FileSystemException {
18+
return when (this) {
19+
is DavIOException ->
20+
return FileSystemException(file, other, message).apply { initCause(cause) }
21+
is UnauthorizedException, is ForbiddenException ->
22+
AccessDeniedException(file, other, message)
23+
is NotFoundException -> NoSuchFileException(file, other, message)
24+
is ConflictException -> FileAlreadyExistsException(file, other, message)
25+
else -> FileSystemException(file, other, message)
26+
}.apply { initCause(this@toFileSystemException) }
27+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright (c) 2024 Hai Zhang <[email protected]>
3+
* All Rights Reserved.
4+
*/
5+
6+
package me.zhanghai.android.files.provider.webdav
7+
8+
import java8.nio.file.StandardOpenOption
9+
import me.zhanghai.android.files.provider.common.OpenOptions
10+
11+
internal fun OpenOptions.checkForWebDav() {
12+
if (deleteOnClose) {
13+
throw UnsupportedOperationException(StandardOpenOption.DELETE_ON_CLOSE.toString())
14+
}
15+
if (sync) {
16+
throw UnsupportedOperationException(StandardOpenOption.SYNC.toString())
17+
}
18+
if (dsync) {
19+
throw UnsupportedOperationException(StandardOpenOption.DSYNC.toString())
20+
}
21+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright (c) 2024 Hai Zhang <[email protected]>
3+
* All Rights Reserved.
4+
*/
5+
6+
package me.zhanghai.android.files.provider.webdav
7+
8+
import java8.nio.file.Path
9+
import me.zhanghai.android.files.provider.webdav.client.Authority
10+
11+
fun Authority.createWebDavRootPath(): Path =
12+
WebDavFileSystemProvider.getOrNewFileSystem(this).rootDirectory

0 commit comments

Comments
 (0)