From 4dbe52457922377065a4a28df5b373da44a0a48a Mon Sep 17 00:00:00 2001 From: Alpha Date: Mon, 18 Mar 2024 11:23:49 -0400 Subject: [PATCH] fix(ios): support excluding privacy sensitive API usage Closes #73 --- README.md | 9 +++++++++ ReactNativeFileAccess.podspec | 7 +++++++ ios/FileAccess.swift | 11 ++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e0540e0..a864d30 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,15 @@ npm install react-native-file-access cd ios && pod install ``` +Apple restricts usage of certain privacy sensitive API calls. If you do not +use disk space measurements or file timestamps, define the following variable +in your Podfile to exclude restricted API calls. +[More details.](https://github.com/alpha0010/react-native-file-access/issues/73) + +```ruby +$RNFANoPrivacyAPI = true +``` + If the app does not use autolinking, continue to the [manual install instructions](https://github.com/alpha0010/react-native-file-access/wiki/Manual-Installation) in the wiki. ### Compatibility diff --git a/ReactNativeFileAccess.podspec b/ReactNativeFileAccess.podspec index b5322b0..ef080d2 100644 --- a/ReactNativeFileAccess.podspec +++ b/ReactNativeFileAccess.podspec @@ -19,6 +19,13 @@ Pod::Spec.new do |s| s.dependency "React-Core" s.dependency "ZIPFoundation", "0.9.11" + if defined?($RNFANoPrivacyAPI) + Pod::UI.puts "#{s.name}: Removing privacy sensitive API calls" + s.pod_target_xcconfig = { + "OTHER_SWIFT_FLAGS" => "-DNO_PRIVACY_API" + } + end + # Don't install the dependencies when we run `pod install` in the old architecture. if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" diff --git a/ios/FileAccess.swift b/ios/FileAccess.swift index 51edb34..7264573 100644 --- a/ios/FileAccess.swift +++ b/ios/FileAccess.swift @@ -126,6 +126,9 @@ public class FileAccess : NSObject { @objc(df:withRejecter:) public func df(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void { DispatchQueue.global().async { +#if NO_PRIVACY_API + reject("ERR", "Filesystem stat API disabled via compile time flag.", nil) +#else do { let stat = try FileManager.default.attributesOfFileSystem( forPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! @@ -138,6 +141,7 @@ public class FileAccess : NSObject { } catch { reject("ERR", "Failed to stat filesystem. \(error.localizedDescription)", error) } +#endif } } @@ -350,9 +354,14 @@ public class FileAccess : NSObject { private func statFile(path: String) throws -> [String : Any?] { let pathUrl = URL(fileURLWithPath: path.path()) let attrs = try FileManager.default.attributesOfItem(atPath: path.path()) +#if NO_PRIVACY_API + let lastModified = 0 +#else + let lastModified = 1000 * (attrs[.modificationDate] as! NSDate).timeIntervalSince1970 +#endif return [ "filename": pathUrl.lastPathComponent, - "lastModified": 1000 * (attrs[.modificationDate] as! NSDate).timeIntervalSince1970, + "lastModified": lastModified, "path": pathUrl.path, "size": attrs[.size], "type": self.checkIfIsDirectory(path: path).isDirectory ? "directory" : "file"