0

In terminal this works:

/usr/bin/curl --connect-timeout 10 --max-time 60 https://en.wikipedia.org/wiki/The_Beatles -o /Users/username/Desktop/wikiData

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  909k  100  909k    0     0  2025k      0 --:--:-- --:--:-- --:--:-- 2025k

But in Xcode this does not:

let task = Process()
let pipe = Pipe()
task.launchPath = "/usr/bin/curl"
task.arguments = ["--connect-timeout","10","--max-time","60","en.wikipedia.org/wiki/The_Beatles","-o","/Users/username/Desktop/wikiData"]
task.standardOutput = pipe
task.launch()
task.waitUntilExit()

I get this:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
Warning: Failed to create the file /Users/username/Desktop/wikiData: 
Warning: Operation not permitted
curl: (23) Failed writing received data to disk/application

How do I give curl permission to write to disk? In Sandbox I checked "Network Incoming/Outgoing" to be able to talk to wikipedia, and set "File Access/User Selected File/Read/Write" but that doesn't seem to apply to curl. If I leave off "-o ..." I get no error. But I also seem to get no data. Ideas? Thanks.

vonlost
  • 875
  • 1
  • 7
  • 11
  • 1
    Is there a reason you're using `curl` in an app? Why not use `URLSession` instead? – Sam Apr 06 '20 at 21:52

2 Answers2

1

The reason cURL can't write the output is it would have to have permissions which the sandbox won't allow. You should probably take the stdout via pipe of cURL and then try and write the data atomically.

let filePath = "/Users/username/Desktop/wikiData/the_beatles.txt"
let task = Process()

task.launchPath = "/usr/bin/curl"
task.arguments = ["--connect-timeout","10","--max-time","60","https://en.wikipedia.org/wiki/The_Beatles"]

// stdout everything to pipe
let pipe = Pipe()
task.standardOutput = pipe

task.launch()

// collect output
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)

let str = output!
let filename = URL(fileURLWithPath: filePath)

do {
    try str.write(to: filename, atomically: true, encoding: String.Encoding.utf8.rawValue)
} catch {
    print("failed.")
}

There's likely cleaner ways to accomplish this (eg. URLSession), although this at least should give you some idea of how to write the data within the limitations of a sandboxed app.

l'L'l
  • 44,951
  • 10
  • 95
  • 146
  • Thanks I'L'I, that worked except for one small problem:```Failed writing to URL: file:///Users/username/Desktop/wikiData/the_beatles.txt, Error: You don’t have permission to save the file “the_beatles.txt” in the folder “wikiData”.``` I even set wikiData to R+W for everyone. ??? I'll look at URLSession next. – vonlost Apr 06 '20 at 23:26
  • @vonlost: Does a folder exist named "wikiData" on your Desktop? If it doesn't that might be the reason. You could try "/Users/username/Desktop/the_beatles.txt" and see if the result is any different. – l'L'l Apr 07 '20 at 21:10
0

I had to change

let filePath = "/Users/username/Desktop/wikiData/the_beatles.txt"

to

let filePath = NSHomeDirectory() + "/wikiData"

Thank you for your help; it's all working now. :-)

vonlost
  • 875
  • 1
  • 7
  • 11