Repo created
This commit is contained in:
parent
324070df30
commit
2d33a757bf
644 changed files with 99721 additions and 2 deletions
140
app/src/main/kotlin/at/bitfire/davdroid/db/WebDavDocument.kt
Normal file
140
app/src/main/kotlin/at/bitfire/davdroid/db/WebDavDocument.kt
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
|
||||
*/
|
||||
|
||||
package at.bitfire.davdroid.db
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.provider.DocumentsContract.Document
|
||||
import android.webkit.MimeTypeMap
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
import at.bitfire.davdroid.util.DavUtils.MEDIA_TYPE_OCTET_STREAM
|
||||
import at.bitfire.davdroid.webdav.DocumentState
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import java.io.FileNotFoundException
|
||||
import java.time.Instant
|
||||
|
||||
@Entity(
|
||||
tableName = "webdav_document",
|
||||
foreignKeys = [
|
||||
ForeignKey(entity = WebDavMount::class, parentColumns = ["id"], childColumns = ["mountId"], onDelete = ForeignKey.CASCADE),
|
||||
ForeignKey(entity = WebDavDocument::class, parentColumns = ["id"], childColumns = ["parentId"], onDelete = ForeignKey.CASCADE)
|
||||
],
|
||||
indices = [
|
||||
Index("mountId", "parentId", "name", unique = true),
|
||||
Index("parentId")
|
||||
]
|
||||
)
|
||||
// If any column name is modified, also change it in [DavDocumentsProvider$queryChildDocuments]
|
||||
data class WebDavDocument(
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val id: Long = 0,
|
||||
|
||||
/** refers to the [WebDavMount] the document belongs to */
|
||||
val mountId: Long,
|
||||
|
||||
/** refers to parent document (*null* when this document is a root document) */
|
||||
val parentId: Long?,
|
||||
|
||||
/** file name (without any slashes) */
|
||||
val name: String,
|
||||
val isDirectory: Boolean = false,
|
||||
|
||||
val displayName: String? = null,
|
||||
val mimeType: MediaType? = null,
|
||||
val eTag: String? = null,
|
||||
val lastModified: Long? = null,
|
||||
val size: Long? = null,
|
||||
|
||||
val mayBind: Boolean? = null,
|
||||
val mayUnbind: Boolean? = null,
|
||||
val mayWriteContent: Boolean? = null,
|
||||
|
||||
val quotaAvailable: Long? = null,
|
||||
val quotaUsed: Long? = null
|
||||
|
||||
) {
|
||||
|
||||
fun cacheKey(): CacheKey? {
|
||||
if (eTag != null || lastModified != null)
|
||||
return CacheKey(id, DocumentState(eTag, lastModified?.let { ts -> Instant.ofEpochMilli(ts) }))
|
||||
return null
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
fun toBundle(parent: WebDavDocument?): Bundle {
|
||||
if (parent?.isDirectory == false)
|
||||
throw IllegalArgumentException("Parent must be a directory")
|
||||
|
||||
val bundle = bundleOf(
|
||||
Document.COLUMN_DOCUMENT_ID to id.toString(),
|
||||
Document.COLUMN_DISPLAY_NAME to name
|
||||
)
|
||||
|
||||
displayName?.let { bundle.putString(Document.COLUMN_SUMMARY, it) }
|
||||
size?.let { bundle.putLong(Document.COLUMN_SIZE, it) }
|
||||
lastModified?.let { bundle.putLong(Document.COLUMN_LAST_MODIFIED, it) }
|
||||
|
||||
// see RFC 3744 appendix B for required privileges for the various operations
|
||||
var flags = Document.FLAG_SUPPORTS_COPY
|
||||
if (isDirectory) {
|
||||
bundle.putString(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR)
|
||||
if (mayBind != false)
|
||||
flags += Document.FLAG_DIR_SUPPORTS_CREATE
|
||||
} else {
|
||||
val reportedMimeType = mimeType ?:
|
||||
MimeTypeMap.getSingleton().getMimeTypeFromExtension(
|
||||
MimeTypeMap.getFileExtensionFromUrl(name)
|
||||
)?.toMediaTypeOrNull() ?:
|
||||
MEDIA_TYPE_OCTET_STREAM
|
||||
|
||||
bundle.putString(Document.COLUMN_MIME_TYPE, reportedMimeType.toString())
|
||||
if (mimeType?.type == "image")
|
||||
flags += Document.FLAG_SUPPORTS_THUMBNAIL
|
||||
if (mayWriteContent != false)
|
||||
flags += Document.FLAG_SUPPORTS_WRITE
|
||||
}
|
||||
if (parent?.mayUnbind != false)
|
||||
flags += Document.FLAG_SUPPORTS_DELETE or
|
||||
Document.FLAG_SUPPORTS_MOVE or
|
||||
Document.FLAG_SUPPORTS_RENAME
|
||||
bundle.putInt(Document.COLUMN_FLAGS, flags)
|
||||
|
||||
return bundle
|
||||
}
|
||||
|
||||
suspend fun toHttpUrl(db: AppDatabase): HttpUrl {
|
||||
val mount = db.webDavMountDao().getById(mountId)
|
||||
|
||||
val segments = mutableListOf(name)
|
||||
var parentIter = parentId
|
||||
while (parentIter != null) {
|
||||
val parent = db.webDavDocumentDao().get(parentIter) ?: throw FileNotFoundException()
|
||||
segments += parent.name
|
||||
parentIter = parent.parentId
|
||||
}
|
||||
|
||||
val builder = mount.url.newBuilder()
|
||||
for (segment in segments.reversed())
|
||||
builder.addPathSegment(segment)
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents a WebDAV document in a given state (with a given ETag/Last-Modified).
|
||||
*/
|
||||
data class CacheKey(
|
||||
val docId: Long,
|
||||
val documentState: DocumentState
|
||||
)
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue