Skip to content

Commit

Permalink
Merge pull request #797 from kiwix/793-supporting-entries-ending-in
Browse files Browse the repository at this point in the history
793 supporting entries ending in "/"
  • Loading branch information
kelson42 committed Jun 9, 2024
2 parents 0738c5c + cc4c2aa commit b25fb09
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 10 deletions.
5 changes: 5 additions & 0 deletions Model/Utilities/String+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ extension String {
)
}

func removingPrefix(_ value: String) -> String {
guard hasPrefix(value) else { return self }
return String(dropFirst(value.count))
}

func replacingRegex(
matching pattern: String,
findingOptions: NSRegularExpression.Options = .caseInsensitive,
Expand Down
7 changes: 7 additions & 0 deletions Model/Utilities/URL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ extension URL {
var isKiwixURL: Bool { schemeType == .kiwix }
var isGeoURL: Bool { schemeType == .geo }

/// Returns the path, that should be used to resolve articles in ZIM files.
/// It makes sure that trailing slash is preserved,
/// and leading slash is removed.
var contentPath: String {
path(percentEncoded: false).removingPrefix("/")
}

// swiftlint:disable:next force_try
static let documentDirectory = try! FileManager.default.url(
for: .documentDirectory,
Expand Down
12 changes: 6 additions & 6 deletions Model/ZimFileService/ZimFileService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ extension ZimFileService {
func getRedirectedURL(url: URL) -> URL? {
guard let zimFileID = url.host,
let zimFileID = UUID(uuidString: zimFileID),
let redirectedPath = __getRedirectedPath(zimFileID, contentPath: url.path) else { return nil }
let redirectedPath = __getRedirectedPath(zimFileID, contentPath: url.contentPath) else { return nil }
return URL(zimFileID: zimFileID.uuidString, contentPath: redirectedPath)
}

Expand All @@ -107,24 +107,24 @@ extension ZimFileService {

func getURLContent(url: URL) -> URLContent? {
guard let zimFileID = url.host else { return nil }
return getURLContent(zimFileID: zimFileID, contentPath: url.path)
return getURLContent(zimFileID: zimFileID, contentPath: url.contentPath)
}

func getURLContent(url: URL, start: UInt, end: UInt) -> URLContent? {
guard let zimFileID = url.host else { return nil }
return getURLContent(zimFileID: zimFileID, contentPath: url.path, start: start, end: end)
return getURLContent(zimFileID: zimFileID, contentPath: url.contentPath, start: start, end: end)
}

func getContentSize(url: URL) -> NSNumber? {
guard let zimFileID = url.host,
let zimFileUUID = UUID(uuidString: zimFileID) else { return nil }
return __getContentSize(zimFileUUID, contentPath: url.path)
return __getContentSize(zimFileUUID, contentPath: url.contentPath)
}

func getDirectAccessInfo(url: URL) -> DirectAccessInfo? {
guard let zimFileID = url.host,
let zimFileUUID = UUID(uuidString: zimFileID),
let directAccess = __getDirectAccess(zimFileUUID, contentPath: url.path),
let directAccess = __getDirectAccess(zimFileUUID, contentPath: url.contentPath),
let path: String = directAccess["path"] as? String,
let offset: UInt = directAccess["offset"] as? UInt
else {
Expand All @@ -136,7 +136,7 @@ extension ZimFileService {
func getContentMetaData(url: URL) -> URLContentMetaData? {
guard let zimFileID = url.host,
let zimFileUUID = UUID(uuidString: zimFileID),
let content = __getMetaData(zimFileUUID, contentPath: url.path),
let content = __getMetaData(zimFileUUID, contentPath: url.contentPath),
let mime = content["mime"] as? String,
let size = content["size"] as? UInt,
let title = content["title"] as? String else { return nil }
Expand Down
46 changes: 46 additions & 0 deletions Tests/URLContentPathTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// This file is part of Kiwix for iOS & macOS.
//
// Kiwix 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 3 of the License, or
// any later version.
//
// Kiwix 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.
//
// You should have received a copy of the GNU General Public License
// along with Kiwix; If not, see https://www.gnu.org/licenses/.

import XCTest
@testable import Kiwix

final class URLContentPathTests: XCTestCase {

private let testURLs = [
URL(string: "kiwix://6E4F3D4A-2F8A-789A-3B88-212219F4FB27/irp.fas.org/doddir/milmed/index.html")!,
URL(string: "kiwix://861C031F-DAFB-9688-4DB4-8F1199FE2926/mesquartierschinois.wordpress.com/")!,
URL(string: "kiwix://861C031F-DAFB-9688-4DB4-8F1199FE2926/widgets.wp.com/likes/master.html%3Fver%3D20240530#ver=20240530&lang=fr&lang_ver=1713167421&origin=https://mesquartierschinois.wordpress.com")!
]

func test_no_leading_slash() {
testURLs.forEach { url in
XCTAssertFalse(url.contentPath.first == "/")
}
}

func test_preserves_trailing_slash() {
let url = URL(string: "kiwix://861C031F-DAFB-9688-4DB4-8F1199FE2926/mesquartierschinois.wordpress.com/")!
XCTAssertEqual(url.contentPath.last, "/")
}

func test_value() {
XCTAssertEqual(testURLs.map { $0.contentPath }, [
"irp.fas.org/doddir/milmed/index.html",
"mesquartierschinois.wordpress.com/",
"widgets.wp.com/likes/master.html?ver=20240530"
])
}

}
20 changes: 16 additions & 4 deletions ViewModel/BrowserViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import CoreData
import CoreLocation
import WebKit
import Defaults
import os

import OrderedCollections
import CoreKiwix
Expand Down Expand Up @@ -281,11 +282,22 @@ final class BrowserViewModel: NSObject, ObservableObject,
decisionHandler(.cancel)
} else if url.isKiwixURL {
guard ZimFileService.shared.getContentSize(url: url) != nil else {
// content is missing
decisionHandler(.cancel)
NotificationCenter.default.post(
name: .alert, object: nil, userInfo: ["rawValue": ActiveAlert.articleFailedToLoad.rawValue]
os_log(
"Missing content at url: %@ => %@",
log: Log.URLSchemeHandler,
type: .error,
url.absoluteString,
url.contentPath
)
decisionHandler(.cancel)
if navigationAction.request.mainDocumentURL == url {
// only show alerts for missing main document
NotificationCenter.default.post(
name: .alert,
object: nil,
userInfo: ["rawValue": ActiveAlert.articleFailedToLoad.rawValue]
)
}
return
}
decisionHandler(.allow)
Expand Down

0 comments on commit b25fb09

Please sign in to comment.