Problem with NSWorkspace.shared.openApplication in Swift under BigSur - swift

I try to start the Preview App from within my Swift-App.
I think it worked like this before updating to BigSur (unfortunately I cannot test it in a prior OS).
The App shall be able to show any file in the filesystem with the Preview-App.
What I tried:
removed Sandbox from the targets capabilities
added iCloud Documents
added com.apple.security.temporary-exception.files.absolute-path.read-write with the value "/" to the entitlements.
func openPreviewApp(path : String)
{
let url = NSURL(fileURLWithPath: "/System/Applications/Preview.app", isDirectory: true) as URL
let configuration = NSWorkspace.OpenConfiguration()
configuration.arguments = [path]
NSWorkspace.shared.openApplication(at: url,
configuration: configuration,
completionHandler: nil)
}
The function opens the Preview App but not the file given in path - instead the fileselection dialog is presented.
open -a Preview THISPATH in Terminal works fine.
Any Ideas?

Related

How to get the current directory in iCloud Drive of macOS with Swift script?

I write Swift scripts to solve small tasks in using macOS.
I now need to get the current directory in my script.
The following program takes the path of the current directory as a string and converts it to an URL.
// myscript.swift
import Foundation
let path = FileManager.default.currentDirectoryPath
let url = URL(string: path)
print("path:", path)
print("url :", url)
When I ran it in ~/Downloads, I was able to get the URL of the current directory correctly.
The same was true for the other directories.
$ cd ~/Downloads
$ swift myscript.swift
path: /Users/myname/Downloads
url : Optional(/Users/myname/Downloads)
However, when I ran this program in iCloud Drive directory, I could not get the URL.
$ cd ~/Library/Mobile\ Documents/com\~apple\~CloudDocs/MyScripts
$ swift myscript.swift
path: /Users/myname/Library/Mobile Documents/com~apple~CloudDocs/MyScripts
url : nil
Is there any way to solve this?
I would like to solve this in order to handle files in iCloud Drive with my Swift scripts.
Thanks.
(I used a translation tool to ask this question.)
You need to encode the string since it contains a space
path = "/Users/myname/Library/Mobile Documents/com~apple~CloudDocs/MyScripts"
if let encoded = path.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
let url = URL(string: encoded) {
print(url)
}
/Users/myname/Library/Mobile%20Documents/com~apple~CloudDocs/MyScripts"

Trouble reading file in xcode command line app

I am having trouble reading a file within a command line tool project in Xcode 11.6.
Steps:
Create a new command line tool project using the template in the mac os section.
In main.swift:
import Foundation
let fileURL = URL( fileURLWithPath: "/Users/ausom4/Desktop/myTest.txt" )
var rawDataString: String
var errorString: String?
do {
rawDataString = try String( contentsOf: fileURL, encoding: .utf8 )
print(rawDataString)
} catch let error as NSError {
errorString = error.description
rawDataString = ""
print(rawDataString)
}
This will build successfully in Xcode however will always print a null string in the console.
However if I go to the location of my product in terminal and run the build I get the contents of the file.
I do not have sandboxing enabled. Sandboxing is also not enabled by default in this xcode template. I have also given xcode full disk access.
I can run this code in a playground.
What could be the issue here?
It is not sandbox - it is macOS Security & Privacy system.
On first launch you had to get alert asking something like “TestFileReading” would like to access files in your Desktop folder. so you grand access for this application.
If you did not grant access then (or for some reason macOS forgot to ask that) there is possibility to grant access manually in System Preferences at any time:
With all this passed your code snippet works as expected - tested with Xcode 12 / macOS 10.15.6

Is it possible to execute a binary located inside a macOS app's sandbox container?

Is it possible to execute a binary located inside a macOS app's sandbox container?
As a test, I tried using Process() to run the PHP binary. This works fine when running the PHP found at usr/bin/php but if I copy that into the app's sandbox container, it won't run. The error is launch path not accessible.
Steps to demonstrate the issue:
Put this in a bare sandboxed app's ViewController:
let path = "/usr/bin/php"
let process = Process()
process.launchPath = path
process.arguments = ["-v"]
process.launch()
Result in the console:
PHP 7.1.16 (cli) (built: Apr 1 2018 13:14:42) ( NTS )
Change the path in the code above, to:
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let path = documentsURL.absoluteString + "php"
print(path)
The correct path is printed to the console:
file:///Users/myuser/Library/Containers/com.domain.SandboxedApp/Data/Documents/php
Copy the PHP binary to the container:
$ cp /usr/bin/php /Users/myuser/Library/Containers/com.domain.SandboxedApp/Data/Documents
The resulting error in the console:
2018-07-01 20:08:30.630442+1200 SandboxedApp[43579:20898286] Failed to set (contentViewController) user defined inspected property on (NSWindow): launch path not accessible
Why won't Process() run PHP from the container? And why such a weird error message?
(nb you could ask why I would want to do this. There are several reasons eg I would like to understand more deeply how the sandbox permissions work; I would like to sandbox an app which is able to run user-supplied binaries not provided by macOS nor distributed in the app's bundle — yes, not intended for distribution on the MAS, I know this breaks their terms).

How to create a directory in downloads folder with swift on macos? Permission exception.

I am struggling to simply create a folder in the users download directory on macos with this code:
static func createFolderInDownloadsDirectory() {
let downloadsDirectory = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!
let downloadsDirectoryWithFolder = downloadsDirectory.appendingPathComponent("FolderToCreate")
do {
try FileManager.default.createDirectory(at: downloadsDirectoryWithFolder, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
print(error.localizedDescription)
}
}
This is the output:
You don’t have permission to save the file “FolderToCreate” in the folder “Downloads”.
How can I fix this?
Xcode 9 and later enables sandboxing by default, which severely limits interactions with the system. However you can still write to the Downloads folder by adding an entitlement to your app:
Select your target, then Capabilities and set Downloads Folder to Read/Write:
If you have no intention of distributing your app through the Mac App Store, you can turn off sandboxing. Your application can still be signed but users will get a warning when they first launch your app.

How can upload a zip file into FTP server using swift 3 and iOS 10?

How can upload a zip file into FTP server using swift 3 and iOS 10? I need to do this in my app to send logs files.
You can use this framework to upload files to an FTP server: https://github.com/Constantine-Fry/rebekka
With this, you just need to set configuration in AppDelegate (like this) and to upload you use this code:
if let URL = NSBundle.main.URL(forResource:"MyLog", withExtension: "zip") {
let path = "/upload/\(UUID.init().uuidString).zip"
self.session.upload(URL, path: path) {
(result, error) -> Void in
print("Upload file with result:\n\(result), error: \(error)\n\n")
}
}