I'm building a MacOS app that lets users edit a file. To access a file, I use a security scoped bookmark like so:
do {
self.securityScopedBookmark = try asset?.url.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
} catch {
print("failed bookmark. error info: \(error)")
}
When the user is done and the NSDocument is deinitialized, I stop accessing the bookmark like so:
deinit {
if let securityScopedBookmark = self.securityScopedBookmark {
do {
var isStale: Bool = false
let url = try URL.init(resolvingBookmarkData: securityScopedBookmark, options: [.withoutUI, .withSecurityScope], relativeTo: nil, bookmarkDataIsStale: &isStale)
url.stopAccessingSecurityScopedResource()
} catch let error as NSError {
print("Bookmark Access Fails: \(error.description)")
}
}
}
However when trying to call .stopAccessingSecurityScopedBookmark(), I get a couple log errors.
[scoped] handle 0: sandbox_extension_release error [22: Invalid argument]
[scoped] <0x60000202e400 file:///Users/user/Desktop/file.mp4>: internal sandbox error for <StopAccessing>
I'm not sure if these errors will create a problem or not. Everything seems to be working either way, but I'm worried that in deployment there will be problems.
I am using the following security entitlement keys:
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.files.bookmarks.document-scope</key>
<true/>
Related
I'm trying to create an app that can take screenshots. I check to see if I have a secure session and if I has graphical access and I do. But all I get is my app windows and the wallpaper. No other apps are captured.
I tried to use the screencapture. It work well in terminal but not in the app. Also each time I try the function it asks me to give permission even thought it already has permission.
This is my code:
var attrs = SessionAttributeBits(rawValue: 0)
let session = SessionGetInfo(callerSecuritySession, nil, &attrs)
if session != 0 || !attrs.contains(.sessionHasGraphicAccess) {
result(FlutterError(code: "NO_GRAPHIC_ACCESS", message: "We don't run in a GUI.", details: nil))
} else {
do {
let directory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let image = CGWindowListCreateImage(CGRect.infinite, [.optionOnScreenOnly, .excludeDesktopElements], kCGNullWindowID, .nominalResolution)
if let _image = image {
let bitmap = NSBitmapImageRep(cgImage: _image)
let data = bitmap.representation(using: .png, properties: [:])
if let _data = data {
let url: URL = directory.appendingPathComponent("\(Int(Date().timeIntervalSince1970 * 1000000)).png")
try _data.write(to: url, options: .atomicWrite)
} else {
result(FlutterError(code: "IMAGE_REPRESENTATION_FAILED", message: nil, details: nil))
}
} else {
result(FlutterError(code: "IMAGE_IS_NULL", message: nil, details: nil))
}
} catch {
result(FlutterError(code: "ERROR", message: "\(error)", details: nil))
}
}
It seems to be a strange XCode behavior. If you run your application directly from XCode, user will always be prompted to confirm permission, even if your app is already in you settings exceptions (https://support.apple.com/guide/mac-help/change-privacy-preferences-on-mac-mh32356/mac).
If you archive your application and install it in your mac, then permissions will be asked only once. It seems that every build of the app in XCode generate a new app, this don't happen in iOS and iPadOS simulators or devices.
Give your program permissions for screen recording. See this.
Currently I am writing FinderSync Extension for my App using Swift language. My Extension require to do the REST call to the Server which is running on local host at port number 40322. Based on the response I will create the context menu Items. For same reason I wrote the following code in "FinderSync.swift"
file as
let config = URLSessionConfiguration.default
// Session Configuration
let session = URLSession(configuration: config)
// Load configuration into Session
let request_url = URL(string: "http://127.0.0.1:40322/api/get_rclick_settings_and_check_target")!
let task = session.dataTask(with: request_url, completionHandler: {
(data, response, error) in
if error != nil {
print("TAKS ERROR: \(error!.localizedDescription)")
}
else {
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any]
{
NSLog("TASK RESPONSE: \(json)")
}
} catch {
NSLog("error in JSONSerialization")
}
}
})
task.resume()
But The code giving Error as
"nw_socket_connect connectx failed: [1] Operation not permitted"
But the same code is running of playground after importing XCPlayground and adding line as "XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true)"
My Question is do we need to add any elements in "info.plist" of application or FinderSync Extension to allow the extension to do the REST call or is there any other way to solve this problem?
Have you set the extension's Capabilities tab to allow network connections?
Your app extension uses a different .entitlements file than the main app. Make sure you additionally add any capabilities the extension will require there.
<key>com.apple.security.network.client</key>
<true/>
I am a new student working on a summer project following my freshman year with little experience and I am getting the error
Error Domain=NSURLErrorDomain Code=-1012 "(null)"
UserInfo={NSErrorFailingURLKey=https://localhost/donate/payment.php,
NSErrorFailingURLStringKey=https://localhost/donate/payment.php}
when I try to run a credit card payment through stripe, the code I have is
func postStripeToken(token: STPToken) {
let URL = "https://localhost/donate/payment.php"
let params : [String: AnyObject] = ["stripeToken": token.tokenId,
"amount": myInt,
"currency": "usd",
"description": self.emailTextField.text!]
let manager = AFHTTPRequestOperationManager()
manager.POST(URL, parameters: params, success: { (operation, responseObject) -> Void in
if let response = responseObject as? [String: String] {
UIAlertView(title: response["status"],
message: response["message"],
delegate: nil,
cancelButtonTitle: "OK").show()
}
}) { (operation, error) -> Void in
self.handleError(error!)
}
}
It wants a HTTP url instead of a HTTPS but when i change it to HTTP and its not secure when the user presses pay with their card they get an error
The resource could not be loaded beach the APP Transport Security
Policy requires the use of a secure connection.
Is there anyway I can use a HTTPS without getting the NSURL error or I can make a secure connection without HTTPS? Any Tips would be very helpful!
manager.securityPolicy.allowInvalidCertificates = true;
I also tried adding this statement with no luck.
For this issue “The resource could not be loaded beach the APP Transport Security Policy requires the use of a secure connection”
just write following code in your info.plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
I used a tutorial to learn how to log in with Facebook through Parse and followed it step by step. The link to the tutorial is: http://blog.oskoui-oskoui.com/?p=8161
It worked great in Xcode 6.2 and I had no problems with my code, but now after updating to Xcode 6.3 I am getting an error that says: "missing argument for parameter 'selector' in call". This error appears right after "PFFacebookUtils.logInWithPermissions" in the code below. I have tried a few different things and all I get is a different error. How can I fix this?
let permissions = ["public_profile"]
#IBAction func facebookLogInButton(sender: AnyObject) {
PFFacebookUtils.logInWithPermissions(permissions: permissions, {
(user: PFUser!, error: NSError!) -> Void in
if user == nil {
NSLog("Uh oh. The user cancelled the Facebook login.")
} else if user.isNew {
NSLog("User signed up and logged in through Facebook! \(user)")
} else {
NSLog("User logged in through Facebook! \(user)")
}
})
}
This could be a case of Xcode misreading an error. At the beginning of the closure, the two variables should have "?" instead of "!". The code would be
(user:PFUser?, error:NSError?) in
This fixed the problem.
#IBAction func fbLoginClick(sender: AnyObject) {
PFFacebookUtils.logInWithPermissions(self.permissions, block: {
(user: PFUser?, error: NSError?) -> Void in
if user == nil {
NSLog("Uh oh. The user cancelled the Facebook login.")
} else if user!.isNew {
NSLog("User signed up and logged in through Facebook! \(user)")
} else {
NSLog("User logged in through Facebook! \(user)")
}
})
}
I am trying to find a way to mount a SMB share in a Cocoa app that I am creating however all documentation points to FSMountServerVolumeSync however when I put this into my code I get an error
'FSMountServerVolumeSync' is unavailable: APIs deprecated as of OS X 10.9 and earlier are unavailable in Swift
I came across some info on an old alternative - DADiskMount but I don't know if this is a suitable replacement nor how to implement it.
Is there now a Swift way to mount an SMB share that works with the latest version of Swift?
So for anyone looking for the answer to this, there seems to be no documentation on this provided by Apple but after much searching I discovered that the NetFS.framework is still very much valid and hopefully supported.
Once I included the NetFS framework into the Swift file and had a play around, everything worked as expected.
include Coco
include NetFS
func mountShare( serverAddress: String, shareName: String, userName: String, password: String) {
let fm = NSFileManager.defaultManager()
let mountPoint = "/Volumes/".stringByAppendingString(shareName)
var isDir : ObjCBool = false
if fm.fileExistsAtPath(mountPoint, isDirectory:&isDir) {
if isDir {
unmount(mountPoint, 0)
println("unmount \(mountPoint)")
}
}
let sharePath = NSURL(string: "\(serverAddress)/\(shareName)")!
let mounted: Int32 = NetFSMountURLSync(sharePath, nil, userName, self.decodeStr(password), nil, nil, nil)
if mounted > 0 {
println("Error: sharePath: \(sharePath) Not Valid")
} else {
println("Mounted: \(sharePath)")
}
}