Peter Steinbergerfix: harden Qoder usage parsing5ff4c254 months agoHistory
109 lines · 4.3 KB · Swift
RawDownload
import Foundation #if os(macOS)import SweetCookieKit public enum QoderCookieImporter {    private static let log = CodexBarLog.logger(LogCategories.qoderCookie)    private static let cookieClient = BrowserCookieClient()    private static let cookieImportOrder: BrowserCookieImportOrder =        ProviderDefaults.metadata[.qoder]?.browserCookieOrder ?? Browser.defaultImportOrder     public struct SessionInfo: Sendable {        public let cookies: [HTTPCookie]        public let sourceLabel: String        public let site: QoderWebSite         public init(cookies: [HTTPCookie], sourceLabel: String, site: QoderWebSite) {            self.cookies = cookies            self.sourceLabel = sourceLabel            self.site = site        }         public var cookieHeader: String {            self.cookies.map { "\($0.name)=\($0.value)" }.joined(separator: "; ")        }    }     public static func importSession(        browserDetection: BrowserDetection = BrowserDetection(),        preferredBrowsers: [Browser] = [],        logger: ((String) -> Void)? = nil) throws -> SessionInfo    {        guard let session = try self.importSessions(            browserDetection: browserDetection,            preferredBrowsers: preferredBrowsers,            logger: logger).first        else {            throw QoderUsageError.missingCredentials        }        return session    }     public static func importSessions(        browserDetection: BrowserDetection = BrowserDetection(),        preferredBrowsers: [Browser] = [],        logger: ((String) -> Void)? = nil) throws -> [SessionInfo]    {        let installedBrowsers = preferredBrowsers.isEmpty            ? self.cookieImportOrder.cookieImportCandidates(using: browserDetection)            : preferredBrowsers.cookieImportCandidates(using: browserDetection)        var sessions: [SessionInfo] = []         for browserSource in installedBrowsers {            for site in QoderWebSite.allCases {                do {                    let query = Self.cookieQuery(for: site)                    let sources = try Self.cookieClient.codexBarRecords(                        matching: query,                        in: browserSource,                        logger: { msg in self.emit(msg, logger: logger) })                    for source in sources where !source.records.isEmpty {                        let records = self.records(source.records, for: site)                        let cookies = BrowserCookieClient.makeHTTPCookies(records, origin: query.origin)                        guard !cookies.isEmpty else { continue }                        self.emit("Found \(cookies.count) cookies in \(source.label)", logger: logger)                        sessions.append(SessionInfo(cookies: cookies, sourceLabel: source.label, site: site))                    }                } catch {                    BrowserCookieAccessGate.recordIfNeeded(error)                    self.emit(                        "\(browserSource.displayName) cookie import failed: \(error.localizedDescription)",                        logger: logger)                }            }        }         guard !sessions.isEmpty else {            throw QoderUsageError.missingCredentials        }        return sessions    }     static func cookieQuery(for site: QoderWebSite) -> BrowserCookieQuery {        BrowserCookieQuery(domains: site.cookieDomains, domainMatch: .exact)    }     static func records(_ records: [BrowserCookieRecord], for site: QoderWebSite) -> [BrowserCookieRecord] {        records.filter { record in            self.cookieDomainMatchesSite(record.domain, site: site)        }    }     private static func cookieDomainMatchesSite(_ rawDomain: String, site: QoderWebSite) -> Bool {        let domain = self.normalizedCookieDomain(rawDomain)        return site.cookieDomains.contains { self.normalizedCookieDomain($0) == domain }    }     private static func normalizedCookieDomain(_ rawDomain: String) -> String {        let trimmed = rawDomain.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()        guard trimmed.hasPrefix(".") else { return trimmed }        return String(trimmed.dropFirst())    }     private static func emit(_ message: String, logger: ((String) -> Void)?) {        logger?("[qoder-cookie] \(message)")        self.log.debug(message)    }}#endif