diff --git a/CHANGELOG.md b/CHANGELOG.md index d73c0def..66adc1c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1 @@ -- 修复 ZIP 归档中位于子目录的 dylib 文件无法正确导入的问题。 -- 新增 “所有应用” 分类。 -- 新增免责声明。 -- 新增中文名称 “巨魔注入器”。 - ------- - -- Fixed an issue where dylib files located in subdirectories in ZIP archives could not be imported correctly. -- Added “All Applications” category. -- Added disclaimer. +- Inject `.bundle` additionally if `.deb` file contains both `.dylib` and `.bundle` \ No newline at end of file diff --git a/TrollFools/InjectorV3+Preprocess.swift b/TrollFools/InjectorV3+Preprocess.swift index ca4325a0..772aa6e2 100644 --- a/TrollFools/InjectorV3+Preprocess.swift +++ b/TrollFools/InjectorV3+Preprocess.swift @@ -141,28 +141,90 @@ fileprivate extension InjectorV3 { var hasAnyDylib = false var tarReader = TarReader(fileHandle: tarHandle) + var processedBundles = Set() + var bundleContents: [String: [(info: TarEntryInfo, data: Data?)]] = [:] while let entry = try tarReader.read() { - guard entry.info.type == .regular, - entry.info.name.hasSuffix(".dylib"), - let entryData = entry.data - else { - continue - } - - let dylibName = URL(fileURLWithPath: entry.info.name, relativeTo: targetURL).lastPathComponent - guard !dylibName.hasPrefix(".") else { - continue - } + if entry.info.type == .regular && entry.info.name.hasSuffix(".dylib") { + guard let entryData = entry.data else { + continue + } + let dylibName = URL(fileURLWithPath: entry.info.name, relativeTo: targetURL).lastPathComponent + guard !dylibName.hasPrefix(".") else { + continue + } - DDLogWarn("Found dylib \(entry.info.name) name \(dylibName)", ddlog: logger) + DDLogWarn("Found dylib \(entry.info.name) name \(dylibName)", ddlog: logger) + + let entryURL = targetURL.appendingPathComponent(dylibName) + try entryData.write(to: entryURL) + hasAnyDylib = true + } else if entry.info.type == .directory && entry.info.name.hasSuffix(".bundle") { + // Extract bundle name + let bundleName = URL(fileURLWithPath: entry.info.name).lastPathComponent + // Avoid processing duplicate or nested bundles + guard !processedBundles.contains(bundleName) else { + continue + } + // Track that we're processing this bundle + processedBundles.insert(bundleName) + // Store bundle entries for later processing + bundleContents[entry.info.name] = [] - let entryURL = targetURL.appendingPathComponent(dylibName) - try entryData.write(to: entryURL) - hasAnyDylib = true + DDLogWarn("Found bundle \(entry.info.name) name \(bundleName)", ddlog: logger) + } else { + // Collect contents for all bundles + for (bundlePath, _) in bundleContents { + if entry.info.name.starts(with: bundlePath + "/") { + bundleContents[bundlePath]?.append((entry.info, entry.data)) + } + } + } } if !hasAnyDylib { throw Error.generic(NSLocalizedString("No dylib found in the Debian package.", comment: "")) } + let fileManager = FileManager.default + // Process collected bundle contents + for (bundlePath, contents) in bundleContents { + let bundleName = URL(fileURLWithPath: bundlePath).lastPathComponent + + DDLogInfo("Preparing to copy bundle \(bundlePath)", ddlog: logger) + + // Destination for the bundle + let destinationBundleURL = targetURL.appendingPathComponent(bundleName) + // Remove existing bundle if it exists + if fileManager.fileExists(atPath: destinationBundleURL.path) { + try fileManager.removeItem(at: destinationBundleURL) + } + // Create destination directory for the bundle + try fileManager.createDirectory(at: destinationBundleURL, withIntermediateDirectories: true) + + // Copy bundle contents + for entry in contents { + // Get relative path within the bundle + let relativePath = String(entry.info.name.dropFirst(bundlePath.count + 1)) + let destinationPath = destinationBundleURL.appendingPathComponent(relativePath) + // Handle different entry types + switch entry.info.type { + case .directory: + // Create subdirectories + try fileManager.createDirectory(at: destinationPath, withIntermediateDirectories: true) + case .regular: + // Ensure destination directory exists + try fileManager.createDirectory(at: destinationPath.deletingLastPathComponent(), withIntermediateDirectories: true) + // Write file contents + guard let fileData = entry.data else { + DDLogWarn("Unable to read data for \(entry.info.name)", ddlog: logger) + continue + } + try fileData.write(to: destinationPath) + default: + continue + } + } + + DDLogInfo("Successfully copied bundle \(bundleName)", ddlog: logger) + } } }