Skip to content

Commit cbede62

Browse files
committed
fix: Metadata lookup for items with hashtag in name.
This surfaced in-house for myself when I tried to navigate to a subfolder which is named something like "Ticket#123" and the folder content enumeration failed. It turned out that the URL operations for deriving the parent remote URL were not taking the URL fragment into account. The strange thing is: I could have sworn that this worked before. Maybe the underlying frameworks changed in behavior of their APIs. Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
1 parent 3aed8ec commit cbede62

2 files changed

Lines changed: 42 additions & 19 deletions

File tree

Sources/NextcloudFileProviderKit/Database/FilesDatabaseManager+Directories.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,8 @@ public extension FilesDatabaseManager {
2828
.count
2929
}
3030

31-
func parentDirectoryMetadataForItem(
32-
_ itemMetadata: SendableItemMetadata
33-
) -> SendableItemMetadata? {
34-
self.itemMetadata(
35-
account: itemMetadata.account, locatedAtRemoteUrl: itemMetadata.serverUrl
36-
)
31+
func parentDirectoryMetadataForItem(_ itemMetadata: SendableItemMetadata) -> SendableItemMetadata? {
32+
self.itemMetadata(account: itemMetadata.account, locatedAtRemoteUrl: itemMetadata.serverUrl)
3733
}
3834

3935
func directoryMetadata(ocId: String) -> SendableItemMetadata? {

Sources/NextcloudFileProviderKit/Database/FilesDatabaseManager.swift

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -211,24 +211,51 @@ public final class FilesDatabaseManager: Sendable {
211211
return nil
212212
}
213213

214-
public func itemMetadata(
215-
account: String, locatedAtRemoteUrl remoteUrl: String // Is the URL for the actual item
216-
) -> SendableItemMetadata? {
217-
guard let actualRemoteUrl = URL(string: remoteUrl) else { return nil }
218-
let fileName = actualRemoteUrl.lastPathComponent
219-
guard var serverUrl = actualRemoteUrl
220-
.deletingLastPathComponent()
221-
.absoluteString
222-
.removingPercentEncoding
223-
else { return nil }
224-
if serverUrl.hasSuffix("/") {
225-
serverUrl.removeLast()
214+
///
215+
/// Look up the item metadata by its account identifier and remote address.
216+
///
217+
/// - Parameters:
218+
/// - account: The account this item is scoped by.
219+
/// - remoteURL: The full remote URL of the item as a `String`.
220+
///
221+
/// - Returns: Metadata related to the item found by the parameters.
222+
///
223+
public func itemMetadata(account: String, locatedAtRemoteUrl rawRemoteURL: String) -> SendableItemMetadata? {
224+
guard let remoteURLComponents = URLComponents(string: rawRemoteURL) else {
225+
return nil
226226
}
227+
228+
guard let remoteURL = remoteURLComponents.url else {
229+
return nil
230+
}
231+
232+
// Get the file name but also take the possible fragment into consideration which is not part of a URL path but a file name.
233+
var fileName = remoteURL.lastPathComponent
234+
235+
if let fragment = remoteURL.fragment {
236+
fileName = "\(fileName)#\(fragment)"
237+
}
238+
239+
// Derive the parent address by removing the last path component and discarding the fragment which may actually be part of the file name and not a URL fragment.
240+
var parentURLComponents = remoteURLComponents
241+
parentURLComponents.path = remoteURL.deletingLastPathComponent().path
242+
parentURLComponents.fragment = nil
243+
244+
guard var rawParentURL = parentURLComponents.url?.absoluteString.removingPercentEncoding else {
245+
return nil
246+
}
247+
248+
// Remove any trailing slash.
249+
if rawParentURL.hasSuffix("/") {
250+
rawParentURL.removeLast()
251+
}
252+
227253
if let metadata = itemMetadatas.where({
228-
$0.account == account && $0.serverUrl == serverUrl && $0.fileName == fileName
254+
$0.account == account && $0.serverUrl == rawParentURL && $0.fileName == fileName
229255
}).first {
230256
return SendableItemMetadata(value: metadata)
231257
}
258+
232259
return nil
233260
}
234261

0 commit comments

Comments
 (0)