Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 265d899d authored by Ricki Hirner's avatar Ricki Hirner
Browse files

WebDAV: always return MIME type; change cached file size/modification time after successful upload

parent 7d4a5863
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ object DavUtils {
    }

    const val MIME_TYPE_ALL = "*/*"
    const val MIME_TYPE_OCTET_STREAM = "application/octet-stream"


    @Suppress("FunctionName")
+11 −1
Original line number Diff line number Diff line
package at.bitfire.davdroid.model

import android.annotation.SuppressLint
import android.os.Bundle
import android.provider.DocumentsContract.Document
import android.webkit.MimeTypeMap
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey
import at.bitfire.davdroid.DavUtils.MIME_TYPE_OCTET_STREAM
import okhttp3.HttpUrl
import java.io.FileNotFoundException

@@ -49,6 +52,7 @@ data class WebDavDocument(

): IdEntity {

    @SuppressLint("InlinedApi")
    fun toBundle(parent: WebDavDocument?): Bundle {
        if (parent?.isDirectory == false)
            throw IllegalArgumentException("Parent must be a directory")
@@ -68,7 +72,13 @@ data class WebDavDocument(
            if (mayBind != false)
                flags += Document.FLAG_DIR_SUPPORTS_CREATE
        } else {
            bundle.putString(Document.COLUMN_MIME_TYPE, mimeType)
            val reportedMimeType = mimeType ?:
                MimeTypeMap.getSingleton().getMimeTypeFromExtension(
                    MimeTypeMap.getFileExtensionFromUrl(name)
                ) ?:
                MIME_TYPE_OCTET_STREAM

            bundle.putString(Document.COLUMN_MIME_TYPE, reportedMimeType)
            if (mimeType?.startsWith("image/") == true)
                flags += Document.FLAG_SUPPORTS_THUMBNAIL
            if (mayWriteContent != false)
+13 −4
Original line number Diff line number Diff line
@@ -495,7 +495,7 @@ class DavDocumentsProvider: DocumentsProvider() {
        val client = httpClient(doc.mountId)

        val modeFlags = ParcelFileDescriptor.parseMode(mode)
        val readOnly = when (mode) {
        val readAccess = when (mode) {
            "r" -> true
            "w", "wt" -> false
            else -> throw UnsupportedOperationException("Mode $mode not supported by WebDAV")
@@ -512,7 +512,7 @@ class DavDocumentsProvider: DocumentsProvider() {

        return if (
            Build.VERSION.SDK_INT >= 26 &&      // openProxyFileDescriptor exists since Android 8.0
            readOnly &&                         // WebDAV doesn't support random write access natively
            readAccess &&                       // WebDAV doesn't support random write access natively
            fileInfo.size != null &&            // file descriptor must return a useful value on getFileSize()
            (fileInfo.eTag != null || fileInfo.lastModified != null) &&     // we need a method to determine whether the document has changed during access
            fileInfo.supportsPartial != false   // WebDAV server must support random access
@@ -520,12 +520,21 @@ class DavDocumentsProvider: DocumentsProvider() {
            val accessor = RandomAccessCallback(context!!, client, url, doc.mimeType, fileInfo, signal)
            storageManager.openProxyFileDescriptor(modeFlags, accessor, accessor.workerHandler)
        } else {
            val fd = StreamingFileDescriptor(context!!, client, url, doc.mimeType, signal) {
            val fd = StreamingFileDescriptor(context!!, client, url, doc.mimeType, signal) { transferred ->
                // called when transfer is finished

                val now = System.currentTimeMillis()
                if (!readAccess /* write access */) {
                    // write access, update file size
                    doc.size = transferred
                    doc.lastModified = now
                    documentDao.update(doc)
                }

                notifyFolderChanged(doc.parentId)
            }

            if (readOnly)
            if (readAccess)
                fd.download()
            else
                fd.upload()
+1 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ import android.provider.DocumentsContract

class DocumentsCursor(columns: Array<out String>): MatrixCursor(columns) {

    val documentsExtras = Bundle(1)
    private val documentsExtras = Bundle(1)

    override fun getExtras() = documentsExtras

+8 −4
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ class StreamingFileDescriptor(
    val url: HttpUrl,
    val mimeType: String?,
    val cancellationSignal: CancellationSignal?,
    val finishedCallback: () -> Unit
    val finishedCallback: OnSuccessCallback
) {

    companion object {
@@ -39,6 +39,7 @@ class StreamingFileDescriptor(
    }

    val dav = DavResource(client.okHttpClient, url)
    var transferred: Long = 0

    private val notificationManager = NotificationManagerCompat.from(context)
    private val notification = NotificationCompat.Builder(context, NotificationUtils.CHANNEL_STATUS)
@@ -77,7 +78,7 @@ class StreamingFileDescriptor(

            notificationManager.cancel(notificationTag, NotificationUtils.NOTIFY_WEBDAV_ACCESS)

            finishedCallback()
            finishedCallback.onSuccess(transferred)
        }

        cancellationSignal?.setOnCancelListener {
@@ -117,7 +118,6 @@ class StreamingFileDescriptor(
                        body.byteStream().use { source ->
                            // read first chunk
                            var bytes = source.read(buffer)
                            var transferred = 0L
                            while (bytes != -1) {
                                // update notification (if file size is known)
                                if (length != -1L)
@@ -162,7 +162,6 @@ class StreamingFileDescriptor(

                ParcelFileDescriptor.AutoCloseInputStream(readFd).use { input ->
                    val buffer = ByteArray(BUFFER_SIZE)
                    var transferred = 0L

                    // read first chunk
                    var size = input.read(buffer)
@@ -183,4 +182,9 @@ class StreamingFileDescriptor(
        }
    }


    fun interface OnSuccessCallback {
        fun onSuccess(transferred: Long)
    }

}
 No newline at end of file