2023-01-05 22:59:50 +03:00
/*
* Copyright ( C ) 2022 by Claudio Cambra < claudio . cambra @ nextcloud . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* for more details .
*/
import Foundation
import RealmSwift
2023-01-10 20:36:10 +03:00
import FileProvider
2023-01-13 16:53:40 +03:00
import NextcloudKit
2023-01-05 22:59:50 +03:00
class NextcloudFilesDatabaseManager : NSObject {
static let shared = {
return NextcloudFilesDatabaseManager ( ) ;
} ( )
2023-01-12 18:51:44 +03:00
let relativeDatabaseFolderPath : String = " Database/ "
2023-01-05 22:59:50 +03:00
let databaseFilename : String = " fileproviderextdatabase.realm "
let relativeDatabaseFilePath : String
var databasePath : URL ?
let schemaVersion : UInt64 = 100
override init ( ) {
self . relativeDatabaseFilePath = self . relativeDatabaseFolderPath + self . databaseFilename
2023-01-12 18:51:44 +03:00
guard let fileProviderDataDirUrl = pathForFileProviderExtData ( ) else {
2023-01-05 22:59:50 +03:00
super . init ( )
return
}
2023-01-12 18:51:44 +03:00
self . databasePath = fileProviderDataDirUrl . appendingPathExtension ( self . relativeDatabaseFilePath )
2023-01-05 22:59:50 +03:00
// D i s a b l e f i l e p r o t e c t i o n f o r d i r e c t o r y D B
// h t t p s : / / d o c s . m o n g o d b . c o m / r e a l m / s d k / i o s / e x a m p l e s / c o n f i g u r e - a n d - o p e n - a - r e a l m / # s t d - l a b e l - i o s - o p e n - a - l o c a l - r e a l m
2023-01-12 18:51:44 +03:00
let folderPath = fileProviderDataDirUrl . appendingPathComponent ( self . relativeDatabaseFolderPath ) . path
do {
try FileManager . default . setAttributes ( [ FileAttributeKey . protectionKey : FileProtectionType . completeUntilFirstUserAuthentication ] , ofItemAtPath : folderPath )
} catch {
print ( " Could not set permission level for File Provider database folder " )
2023-01-05 22:59:50 +03:00
}
let config = Realm . Configuration (
fileURL : self . databasePath ,
schemaVersion : self . schemaVersion ,
2023-01-12 23:16:49 +03:00
objectTypes : [ NextcloudItemMetadataTable . self ]
2023-01-05 22:59:50 +03:00
)
Realm . Configuration . defaultConfiguration = config
do {
let realm = try Realm ( )
print ( " Successfully started Realm db for FileProviderExt " )
} catch let error as NSError {
print ( " Error opening Realm db: %@ " , error . localizedDescription )
}
super . init ( )
}
2023-01-10 19:58:00 +03:00
2023-01-10 21:23:33 +03:00
private func ncDatabase ( ) -> Realm {
2023-01-10 19:58:00 +03:00
let realm = try ! Realm ( )
realm . refresh ( )
2023-01-10 21:23:33 +03:00
return realm
2023-01-10 19:58:00 +03:00
}
2023-01-10 20:36:10 +03:00
2023-01-12 23:16:49 +03:00
func itemMetadataFromOcId ( _ ocId : String ) -> NextcloudItemMetadataTable ? {
return ncDatabase ( ) . objects ( NextcloudItemMetadataTable . self ) . filter ( " ocId == %@ " , ocId ) . first
2023-01-10 21:23:33 +03:00
}
2023-01-23 19:25:00 +03:00
private func sortedItemMetadatas ( _ metadatas : Results < NextcloudItemMetadataTable > ) -> [ NextcloudItemMetadataTable ] {
2023-01-13 16:17:04 +03:00
let sortedMetadatas = metadatas . sorted ( byKeyPath : " fileName " , ascending : true )
return Array ( sortedMetadatas . map { $0 } )
}
2023-01-23 19:25:00 +03:00
func itemMetadatas ( account : String , serverUrl : String ) -> [ NextcloudItemMetadataTable ] {
let metadatas = ncDatabase ( ) . objects ( NextcloudItemMetadataTable . self ) . filter ( " account == %@ AND serverUrl == %@ " , account , serverUrl )
return sortedItemMetadatas ( metadatas )
}
func itemMetadatas ( account : String , serverUrl : String , status : NextcloudItemMetadataTable . Status ) -> [ NextcloudItemMetadataTable ] {
let metadatas = ncDatabase ( ) . objects ( NextcloudItemMetadataTable . self ) . filter ( " account == %@ AND serverUrl == %@ AND status == %@ " , account , serverUrl , status )
return sortedItemMetadatas ( metadatas )
}
2023-01-12 23:16:49 +03:00
func itemMetadataFromFileProviderItemIdentifier ( _ identifier : NSFileProviderItemIdentifier ) -> NextcloudItemMetadataTable ? {
2023-01-10 20:36:10 +03:00
let ocId = identifier . rawValue
2023-01-12 23:16:49 +03:00
return itemMetadataFromOcId ( ocId )
2023-01-10 20:36:10 +03:00
}
2023-01-10 22:24:34 +03:00
2023-01-13 03:59:50 +03:00
func directoryMetadata ( account : String , serverUrl : String ) -> NextcloudDirectoryMetadataTable ? {
return ncDatabase ( ) . objects ( NextcloudDirectoryMetadataTable . self ) . filter ( " account == %@ AND serverUrl == %@ " , account , serverUrl ) . first
}
2023-01-12 23:16:49 +03:00
func parentDirectoryMetadataForItem ( _ itemMetadata : NextcloudItemMetadataTable ) -> NextcloudDirectoryMetadataTable ? {
2023-01-13 03:59:50 +03:00
return directoryMetadata ( account : itemMetadata . account , serverUrl : itemMetadata . serverUrl )
2023-01-10 22:24:34 +03:00
}
2023-01-12 23:36:51 +03:00
func localFileMetadataFromOcId ( _ ocId : String ) -> NextcloudLocalFileMetadataTable ? {
return ncDatabase ( ) . objects ( NextcloudLocalFileMetadataTable . self ) . filter ( " ocId == %@ " , ocId ) . first
}
2023-01-13 16:53:40 +03:00
@objc func convertNKFileToItemMetadata ( _ file : NKFile , account : String ) -> NextcloudItemMetadataTable {
let metadata = NextcloudItemMetadataTable ( )
metadata . account = account
metadata . checksums = file . checksums
metadata . commentsUnread = file . commentsUnread
metadata . contentType = file . contentType
if let date = file . creationDate {
metadata . creationDate = date
} else {
metadata . creationDate = file . date
}
metadata . dataFingerprint = file . dataFingerprint
metadata . date = file . date
metadata . directory = file . directory
metadata . downloadURL = file . downloadURL
metadata . e2eEncrypted = file . e2eEncrypted
metadata . etag = file . etag
metadata . favorite = file . favorite
metadata . fileId = file . fileId
metadata . fileName = file . fileName
metadata . fileNameView = file . fileName
metadata . hasPreview = file . hasPreview
metadata . iconName = file . iconName
metadata . mountType = file . mountType
metadata . name = file . name
metadata . note = file . note
metadata . ocId = file . ocId
metadata . ownerId = file . ownerId
metadata . ownerDisplayName = file . ownerDisplayName
metadata . lock = file . lock
metadata . lockOwner = file . lockOwner
metadata . lockOwnerEditor = file . lockOwnerEditor
metadata . lockOwnerType = file . lockOwnerType
metadata . lockOwnerDisplayName = file . lockOwnerDisplayName
metadata . lockTime = file . lockTime
metadata . lockTimeOut = file . lockTimeOut
metadata . path = file . path
metadata . permissions = file . permissions
metadata . quotaUsedBytes = file . quotaUsedBytes
metadata . quotaAvailableBytes = file . quotaAvailableBytes
metadata . richWorkspace = file . richWorkspace
metadata . resourceType = file . resourceType
metadata . serverUrl = file . serverUrl
metadata . sharePermissionsCollaborationServices = file . sharePermissionsCollaborationServices
for element in file . sharePermissionsCloudMesh {
metadata . sharePermissionsCloudMesh . append ( element )
}
for element in file . shareType {
metadata . shareType . append ( element )
}
metadata . size = file . size
metadata . classFile = file . classFile
// FIXME: i O S 1 2 . 0 , * d o n ' t d e t e c t U T I t e x t / m a r k d o w n , t e x t / x - m a r k d o w n
if ( metadata . contentType = = " text/markdown " || metadata . contentType = = " text/x-markdown " ) && metadata . classFile = = NKCommon . typeClassFile . unknow . rawValue {
metadata . classFile = NKCommon . typeClassFile . document . rawValue
}
if let date = file . uploadDate {
metadata . uploadDate = date
} else {
metadata . uploadDate = file . date
}
metadata . urlBase = file . urlBase
metadata . user = file . user
metadata . userId = file . userId
// S u p p o r t f o r f i n d i n g t h e c o r r e c t f i l e n a m e f o r e 2 e e f i l e s s h o u l d g o h e r e
return metadata
}
func convertNKFilesToItemMetadatas ( _ files : [ NKFile ] , account : String , completionHandler : @ escaping ( _ directoryMetadata : NextcloudItemMetadataTable , _ childDirectoriesMetadatas : [ NextcloudItemMetadataTable ] , _ metadatas : [ NextcloudItemMetadataTable ] ) -> Void ) {
var directoryMetadataSet = false
var directoryMetadata = NextcloudItemMetadataTable ( )
var childDirectoriesMetadatas : [ NextcloudItemMetadataTable ] = [ ]
var metadatas : [ NextcloudItemMetadataTable ] = [ ]
for file in files {
let metadata = convertNKFileToItemMetadata ( file , account : account )
if metadatas . isEmpty && ! directoryMetadataSet {
directoryMetadata = metadata ;
directoryMetadataSet = true ;
} else {
metadatas . append ( metadata )
if metadata . directory {
childDirectoriesMetadatas . append ( metadata )
}
}
}
completionHandler ( directoryMetadata , childDirectoriesMetadatas , metadatas )
}
2023-01-05 22:59:50 +03:00
}