Post

Replies

Boosts

Views

Activity

Reply to My macOS TestFlight app keep deactivating its windows as if there's another invisible window in front
(Argh, this damn forum software lost my edit to the original post above after I submitted it because I had been logged out due to inactivity. Sonow I have to type it in again. Grrr!) New findings: When I close the Prefs window, the other window becomes briefly activated and then immediately deactivates. I used CGWindowListCopyWindowInfo to compare the windows of the correctly vs the badly behaving app versions, and found no differences. So it's rather something where my window get explicitly deactivated. I have no such calls in my own code, though.
May ’24
Reply to Getting metadata (identity) about an SMB volume's server
@eskimo, There's a new problem I just ran into: If the host is a Windows server, the domain name of the mounted volume resolve to a name that I cannot use - neither directly nor with the proposed SRVResolver. For instance, I set up a Windows server with the netbios(?) name "win-serv", and a volume named "WinServer". When I Get Info on the mounted volume, it shows as: smb://win-serv/WinServer When I retrieve the domain name, e.g. with statfs, the name I get is just "win-serv", but that can't be used as an IP address. I found that I can resolve this name with the shell cmd smbutil lookup win-serv, though. So my questions are: Is there an API for doing what smbutil lookup does? How do I tell that I need to use this method? I guess I could just always fall back to it when I cannot reach the server via its given name, but is there a clearer indicator that this is a WINS(?) and not a usual DNS name? I have a related question on StackOverflow but that hasn't gotten me anywhere, either. This entire WINS/NetBIOS thing is a mystery on macOS, it seems.
Topic: App & System Services SubTopic: Core OS Tags:
Mar ’24
Reply to Getting metadata (identity) about an SMB volume's server
Alright, I figured out a way to identify the server by contacting it via https and then checking its certificate. That should be pretty reliable. Below the code I use, though I ran into one complication: The mount URL I get for my QNAP NAS is: "QNAS._smb._tcp.local", but that is not a valid host name I can use in a NSURLRequest! I need to transform that into the actual host name, which is "QNAS.local". Since the former is a Bonjour related name, and when I browse the Bonjour registry with BonJeff, I can find the mapping, this seems to be an overly complicated method. I wonder what the proper way is to get the basic host name from such a service name. I've googled for a while but could not find anything about it. For now, I simply remove all components from the host name that start with an underscore, but I'm not sure if that's a safe method. #import <NetFS/NetFS.h> #import <Security/Security.h> #import "AppDelegate.h" @interface AppDelegate () <NSURLSessionDelegate> @end @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { CFURLRef furl = CFURLCreateWithFileSystemPath(NULL, CFSTR("/Volumes/TheNAS"), kCFURLPOSIXPathStyle, true); NSURL *url = CFBridgingRelease(NetFSCopyURLForRemountingVolume (furl)); NSArray *parts = [[url.host componentsSeparatedByString:@"."] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSString* _Nullable part, id _Nullable bindings) { return ![part hasPrefix:@"_"]; }]]; NSString *addr = [parts componentsJoinedByString:@"."]; NSLog(@"host: %@ -> %@", url.host, addr); NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://%@", addr]]]; NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil]; [[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSLog(@"Done."); [NSApp terminate:self]; }] resume]; } -(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler { SecTrustRef trustRef = [[challenge protectionSpace] serverTrust]; SecCertificateRef certRef = SecTrustGetCertificateAtIndex(trustRef, 0); CFStringRef name = nil; SecCertificateCopyCommonName(certRef, &name); NSLog(@"name: %@", name); // reject the challenge because we have all we wanted completionHandler (NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); } @end
Topic: App & System Services SubTopic: Core OS Tags:
Dec ’23
Reply to Error `sandbox_extension_issue_file` when resolving security-scoped bookmark of file under `/System/Volumes/Data/...`
Just a guess: Since /System/Volumes/Data/ contents are merged into /, you need to replace those paths accordingly (i.e. replace that long prefer in a path with the root path), and then you'll probably get permission. If that works, then I suspect that the Sandbox path access validation code has not been updated to match these aliased paths when volume groups were introduced. I've run into several related issues, outside sandbox, and need to employ similar work-arounds. One would hope that Apple would provide APIs for determining the members and paths of volume groups, and conversion methods, but that's not happening (see also https://stackoverflow.com/q/63876549/43615) Oh, and if you don't like the path replacement method, you could also try getting the CanonicalPath instead - that should also point to the regular path, but take more time than the simple string replacement. If you only do this for a few bookmarks, that shouldn't have an impact and is safer. In fact, there are two ways I use in my apps to get the canonical path. I don't remember which one works, so try them both: Get the fileReferenceURL This code (see also https://stackoverflow.com/questions/64720189): NSString* canonicalFilePath (NSURL *url) { // Caution: Will expand /var/ into /private/var/ NSString *result = nil; if (@available(macOS 10.12, *)) { NSString *cpath; if ([url getResourceValue:&cpath forKey:NSURLCanonicalPathKey error:nil] && cpath) { result = cpath; } else { result = url.URLByResolvingSymlinksInPath.path; } } else { result = [[url fileReferenceURL] filePathURL].path; } return result; }
Topic: App & System Services SubTopic: General Tags:
Jan ’22
Reply to How detect SDK version
To those who need an answer on how to conditionally compile depending on the used SDK version, here's what I found to work: #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 120000 // ... compiles only when using the macOS12.0 SDK (or later) that comes with Xcode 13.1 #endif
Topic: Programming Languages SubTopic: General Tags:
Nov ’21
Reply to Bug: If you have ever made a TestFlight build with a higher version number, you won't get any crash nor feedback reports from users for lower versions!
I have submitted this to Apple (case number 102307509885). So far, they have not acknowledged anything, though. And the WWDC seems to put a halt on all communications.
Replies
Boosts
Views
Activity
Jun ’24
Reply to My macOS TestFlight app keep deactivating its windows as if there's another invisible window in front
Nevermind this - it was indeed a bug in my code, but not where I looked. I have a helper app that may keep running in the background, and that is tied to the running app in a way that if they're not synched, like it is when the app is signed for TestFlight, it gets something wrong.
Replies
Boosts
Views
Activity
May ’24
Reply to My macOS TestFlight app keep deactivating its windows as if there's another invisible window in front
(Argh, this damn forum software lost my edit to the original post above after I submitted it because I had been logged out due to inactivity. Sonow I have to type it in again. Grrr!) New findings: When I close the Prefs window, the other window becomes briefly activated and then immediately deactivates. I used CGWindowListCopyWindowInfo to compare the windows of the correctly vs the badly behaving app versions, and found no differences. So it's rather something where my window get explicitly deactivated. I have no such calls in my own code, though.
Replies
Boosts
Views
Activity
May ’24
Reply to Getting metadata (identity) about an SMB volume's server
BTW, I found out that taking the common name from the certificate is not a reliable identification method to identify Synology NAS systems, because their cert can be self-signed with a custom name. Instead, Synology NAS can be reliably located with the SSDP protocol. I've published code for this here: https://github.com/tempelmann/SSDP-Browser
Topic: App & System Services SubTopic: Core OS Tags:
Replies
Boosts
Views
Activity
May ’24
Reply to Getting metadata (identity) about an SMB volume's server
@eskimo, There's a new problem I just ran into: If the host is a Windows server, the domain name of the mounted volume resolve to a name that I cannot use - neither directly nor with the proposed SRVResolver. For instance, I set up a Windows server with the netbios(?) name "win-serv", and a volume named "WinServer". When I Get Info on the mounted volume, it shows as: smb://win-serv/WinServer When I retrieve the domain name, e.g. with statfs, the name I get is just "win-serv", but that can't be used as an IP address. I found that I can resolve this name with the shell cmd smbutil lookup win-serv, though. So my questions are: Is there an API for doing what smbutil lookup does? How do I tell that I need to use this method? I guess I could just always fall back to it when I cannot reach the server via its given name, but is there a clearer indicator that this is a WINS(?) and not a usual DNS name? I have a related question on StackOverflow but that hasn't gotten me anywhere, either. This entire WINS/NetBIOS thing is a mystery on macOS, it seems.
Topic: App & System Services SubTopic: Core OS Tags:
Replies
Boosts
Views
Activity
Mar ’24
Reply to Determine the user name that was used to login to a network server
The remote user name can be found in the f_mntfromname field from the statfs() call.
Topic: App & System Services SubTopic: Core OS Tags:
Replies
Boosts
Views
Activity
Feb ’24
Reply to Determine the original network volume name in case it's been renamed automatically due to a name conflict
I found the solution myself by trial-and-error: The NSURL resource key NSURLVolumeNameKey contains the original name. It's not clearly documented that it does, but in my tests that did return the desired result.
Topic: App & System Services SubTopic: Core OS Tags:
Replies
Boosts
Views
Activity
Jan ’24
Reply to Getting metadata (identity) about an SMB volume's server
@eskimo, With the code from SRVResolver I can indeed resolve QNAS._smb._tcp.local. Problem is: If the host name is a plain one, like syno.local, then I get neither an error nor a callback. And using a Timeout for a local-only NS resolve seems wrong to me. How should I best handle this? Is there a way to tell when I need to use the SRV record resolver?
Topic: App & System Services SubTopic: Core OS Tags:
Replies
Boosts
Views
Activity
Dec ’23
Reply to Getting metadata (identity) about an SMB volume's server
Alright, I figured out a way to identify the server by contacting it via https and then checking its certificate. That should be pretty reliable. Below the code I use, though I ran into one complication: The mount URL I get for my QNAP NAS is: "QNAS._smb._tcp.local", but that is not a valid host name I can use in a NSURLRequest! I need to transform that into the actual host name, which is "QNAS.local". Since the former is a Bonjour related name, and when I browse the Bonjour registry with BonJeff, I can find the mapping, this seems to be an overly complicated method. I wonder what the proper way is to get the basic host name from such a service name. I've googled for a while but could not find anything about it. For now, I simply remove all components from the host name that start with an underscore, but I'm not sure if that's a safe method. #import <NetFS/NetFS.h> #import <Security/Security.h> #import "AppDelegate.h" @interface AppDelegate () <NSURLSessionDelegate> @end @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { CFURLRef furl = CFURLCreateWithFileSystemPath(NULL, CFSTR("/Volumes/TheNAS"), kCFURLPOSIXPathStyle, true); NSURL *url = CFBridgingRelease(NetFSCopyURLForRemountingVolume (furl)); NSArray *parts = [[url.host componentsSeparatedByString:@"."] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSString* _Nullable part, id _Nullable bindings) { return ![part hasPrefix:@"_"]; }]]; NSString *addr = [parts componentsJoinedByString:@"."]; NSLog(@"host: %@ -> %@", url.host, addr); NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://%@", addr]]]; NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil]; [[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { NSLog(@"Done."); [NSApp terminate:self]; }] resume]; } -(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler { SecTrustRef trustRef = [[challenge protectionSpace] serverTrust]; SecCertificateRef certRef = SecTrustGetCertificateAtIndex(trustRef, 0); CFStringRef name = nil; SecCertificateCopyCommonName(certRef, &name); NSLog(@"name: %@", name); // reject the challenge because we have all we wanted completionHandler (NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); } @end
Topic: App & System Services SubTopic: Core OS Tags:
Replies
Boosts
Views
Activity
Dec ’23
Reply to Xcode 10.1 can't install its required components (CSSMERR_TP_CERT_EXPIRED)
Oh hell! It's not my fault, it's Apple's. The signature appears to be outdated, or refences an expired cert. The fix is to temporarily change the system date to before Oct 1, 2019 for the installation.
Replies
Boosts
Views
Activity
Jun ’22
Reply to Intermittent crash in [NSPathControl mouseDown:] around `setHighlighted:`
Still getting these occasionally, including macOS 12.2. I just realize that the aforementioned crashes in 10.8 were actually more than one separate crashes in Finder, see http://www.applephoon.com/Finder-path-bar-makes-finder-crash-thread-75359-1-1.html
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Feb ’22
Reply to Why is app_version sometimes empty in .ips crash reports from macOS Monterey? (is_first_party)
The Stackoverflow link is https://stackoverflow.com/q/70584180
Replies
Boosts
Views
Activity
Jan ’22
Reply to Error `sandbox_extension_issue_file` when resolving security-scoped bookmark of file under `/System/Volumes/Data/...`
Just a guess: Since /System/Volumes/Data/ contents are merged into /, you need to replace those paths accordingly (i.e. replace that long prefer in a path with the root path), and then you'll probably get permission. If that works, then I suspect that the Sandbox path access validation code has not been updated to match these aliased paths when volume groups were introduced. I've run into several related issues, outside sandbox, and need to employ similar work-arounds. One would hope that Apple would provide APIs for determining the members and paths of volume groups, and conversion methods, but that's not happening (see also https://stackoverflow.com/q/63876549/43615) Oh, and if you don't like the path replacement method, you could also try getting the CanonicalPath instead - that should also point to the regular path, but take more time than the simple string replacement. If you only do this for a few bookmarks, that shouldn't have an impact and is safer. In fact, there are two ways I use in my apps to get the canonical path. I don't remember which one works, so try them both: Get the fileReferenceURL This code (see also https://stackoverflow.com/questions/64720189): NSString* canonicalFilePath (NSURL *url) { // Caution: Will expand /var/ into /private/var/ NSString *result = nil; if (@available(macOS 10.12, *)) { NSString *cpath; if ([url getResourceValue:&cpath forKey:NSURLCanonicalPathKey error:nil] && cpath) { result = cpath; } else { result = url.URLByResolvingSymlinksInPath.path; } } else { result = [[url fileReferenceURL] filePathURL].path; } return result; }
Topic: App & System Services SubTopic: General Tags:
Replies
Boosts
Views
Activity
Jan ’22
Reply to NSDockTilePlugin tutorial....
It is important to note that apps with Dock Tile plugins are not allowed in the Mac App Store! So don't waste your time on this if you plan to publish your app only in the MAS.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Dec ’21
Reply to How detect SDK version
To those who need an answer on how to conditionally compile depending on the used SDK version, here's what I found to work: #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 120000 // ... compiles only when using the macOS12.0 SDK (or later) that comes with Xcode 13.1 #endif
Topic: Programming Languages SubTopic: General Tags:
Replies
Boosts
Views
Activity
Nov ’21