- Adaptive iPhone/iPad layout with NavigationSplitView sidebar - Auto-detect SSL-pinned domains, fall back to passthrough - Certificate install via local HTTP server (Safari profile flow) - App Group-backed CA, per-domain leaf cert LRU cache - DB-backed config repository, Darwin notification throttling - Rules engine, breakpoint rules, pinned domain tracking - os.Logger instrumentation across tunnel/proxy/mitm/capture/cert/rules/db/ipc/ui - Fix dyld framework embed, race conditions, thread safety
83 lines
3.0 KiB
Swift
83 lines
3.0 KiB
Swift
import Foundation
|
|
|
|
/// Centralized rules engine that checks proxy rules (block list, map local, DNS spoofing, no-cache)
|
|
/// against live traffic. All methods are static and synchronous for use in NIO pipeline handlers.
|
|
public enum RulesEngine {
|
|
|
|
private static let rulesRepo = RulesRepository()
|
|
|
|
// MARK: - Block List
|
|
|
|
/// Returns the `BlockAction` if the given URL + method matches an enabled block rule, or nil.
|
|
public static func checkBlockList(url: String, method: String) -> BlockAction? {
|
|
guard IPCManager.shared.isBlockListEnabled else { return nil }
|
|
do {
|
|
let entries = try rulesRepo.fetchEnabledBlockEntries()
|
|
for entry in entries {
|
|
guard entry.method == "ANY" || entry.method == method else { continue }
|
|
if blockEntry(entry, matches: url) {
|
|
return entry.action
|
|
}
|
|
}
|
|
} catch {
|
|
print("[RulesEngine] Failed to check block list: \(error)")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// MARK: - Map Local
|
|
|
|
/// Returns the first matching `MapLocalRule` for the URL + method, or nil.
|
|
public static func checkMapLocal(url: String, method: String) -> MapLocalRule? {
|
|
do {
|
|
let rules = try rulesRepo.fetchEnabledMapLocalRules()
|
|
for rule in rules {
|
|
guard rule.method == "ANY" || rule.method == method else { continue }
|
|
if WildcardMatcher.matches(url, pattern: rule.urlPattern) {
|
|
return rule
|
|
}
|
|
}
|
|
} catch {
|
|
print("[RulesEngine] Failed to check map local rules: \(error)")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// MARK: - DNS Spoofing
|
|
|
|
/// Returns the target domain if the given domain matches an enabled DNS spoof rule, or nil.
|
|
public static func checkDNSSpoof(domain: String) -> String? {
|
|
guard IPCManager.shared.isDNSSpoofingEnabled else { return nil }
|
|
do {
|
|
let rules = try rulesRepo.fetchEnabledDNSSpoofRules()
|
|
for rule in rules {
|
|
if WildcardMatcher.matches(domain, pattern: rule.sourceDomain) {
|
|
return rule.targetDomain
|
|
}
|
|
}
|
|
} catch {
|
|
print("[RulesEngine] Failed to check DNS spoof rules: \(error)")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// MARK: - No-Cache
|
|
|
|
/// Returns true if the no-caching toggle is enabled.
|
|
public static func shouldStripCache() -> Bool {
|
|
IPCManager.shared.isNoCachingEnabled
|
|
}
|
|
|
|
private static func blockEntry(_ entry: BlockListEntry, matches url: String) -> Bool {
|
|
if WildcardMatcher.matches(url, pattern: entry.urlPattern) {
|
|
return true
|
|
}
|
|
|
|
guard entry.includeSubpaths else { return false }
|
|
guard !entry.urlPattern.contains("*"), !entry.urlPattern.contains("?") else { return false }
|
|
|
|
let normalizedPattern = entry.urlPattern.hasSuffix("/") ? entry.urlPattern : "\(entry.urlPattern)/"
|
|
return url == entry.urlPattern || url.hasPrefix(normalizedPattern)
|
|
}
|
|
}
|