diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b7f288a..0162736 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,9 +8,7 @@ jobs: runs-on: macos-latest steps: - name: Checkout - uses: actions/checkout@v2 - with: - submodules: 'true' + uses: actions/checkout@v4 - name: Build run: | xcodebuild -project EstEIDTokenApp.xcodeproj -target package CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO DSTROOT=$PWD/tmp install @@ -20,4 +18,4 @@ jobs: uses: actions/upload-artifact@v2 with: name: pkg - path: upload \ No newline at end of file + path: upload diff --git a/EstEIDToken/Info.plist b/EstEIDToken/Info.plist index 2feef93..9fe2f01 100644 --- a/EstEIDToken/Info.plist +++ b/EstEIDToken/Info.plist @@ -30,8 +30,6 @@ com.apple.ctk.aid - F04573744549442076657220312E - D23300000045737445494420763335 A000000077010800070000FE00000100 com.apple.ctk.class-id diff --git a/EstEIDToken/Token.h b/EstEIDToken/Token.h index 1f41b52..ddf72c7 100644 --- a/EstEIDToken/Token.h +++ b/EstEIDToken/Token.h @@ -35,18 +35,12 @@ static const TKTokenOperationConstraint EstEIDConstraintPIN = @"PIN"; @interface Token : TKSmartCardToken @end -@interface EstEIDToken : Token -@end - @interface IDEMIAToken : Token @end @interface TokenSession : TKSmartCardTokenSession @end -@interface EstEIDTokenSession : TokenSession -@end - @interface IDEMIATokenSession : TokenSession @end diff --git a/EstEIDToken/Token.m b/EstEIDToken/Token.m index 755d010..7eadd04 100644 --- a/EstEIDToken/Token.m +++ b/EstEIDToken/Token.m @@ -77,19 +77,6 @@ - (nullable NSData*)readCert:(NSData*)file error:(NSError **) error { return fileData; } -- (nullable NSString*)readRecord:(UInt8)record error:(NSError **) error { - UInt16 sw = 0; - NSData *data = [self sendIns:0xB2 p1:record p2:0x04 data:nil le:@0 sw:&sw error:error]; - if (sw == 0x9000) { - return [[NSString alloc] initWithData:data encoding:NSWindowsCP1252StringEncoding]; - } - NSLog(@"EstEIDToken readRecord failed to read record %@", @(record)); - if (error != nil) { - *error = [NSError errorWithDomain:TKErrorDomain code:TKErrorCodeObjectNotFound userInfo:nil]; - } - return nil; -} - @end @implementation TKTokenKeychainItem(EstEIDDataFormat) @@ -148,11 +135,10 @@ - (BOOL)populateIdentity:(NSData*)certificateData certificateID:(NSData*)certifi } [keyItem setName:NSLocalizedString(auth ? @"AUTH_KEY" : @"SIGN_KEY", nil)]; keyItem.canSign = YES; - keyItem.canDecrypt = NO; //auth; FIXME: implement decryption + keyItem.canDecrypt = NO; keyItem.suitableForLogin = NO; //auth; FIXME: implement login keyItem.canPerformKeyExchange = NO; //auth; FIXME: implement derive keyItem.constraints = @{ @(TKTokenOperationSignData): EstEIDConstraintPIN }; - // keyItem.constraints = constraints[@(TKTokenOperationDecryptData)] = EstEIDConstraintPIN; //auth; FIXME: implement decryption // keyItem.constraints = constraints[@(TKTokenOperationPerformKeyExchange)] = EstEIDConstraintPIN; //auth; FIXME: implement derive // Populate keychain state with keys. [self.keychainContents fillWithItems:@[certificateItem, keyItem]]; @@ -161,36 +147,6 @@ - (BOOL)populateIdentity:(NSData*)certificateData certificateID:(NSData*)certifi @end -@implementation EstEIDToken - -- (nullable instancetype)initWithSmartCard:(TKSmartCard *)smartCard AID:(nullable NSData *)AID tokenDriver:(TKSmartCardTokenDriver *)tokenDriver error:(NSError **)error { - NSLog(@"EstEIDToken initWithSmartCard AID %@", AID); - NSString *instanceID; - if ([smartCard selectFile:0x00 p2:0x0C file:nil error:error] == nil || - [smartCard selectFile:0x01 p2:0x0C file:NSDATA(2, 0xEE, 0xEE) error:error] == nil || - [smartCard selectFile:0x02 p2:0x0C file:NSDATA(2, 0x50, 0x44) error:error] == nil || - (instanceID = [smartCard readRecord:0x08 error:error]) == nil) { - NSLog(@"EstEIDToken initWithSmartCard failed to read card"); - return nil; - } - NSLog(@"EstEIDToken initWithSmartCard %@", instanceID); - if (self = [super initWithSmartCard:smartCard AID:AID instanceID:instanceID tokenDriver:tokenDriver]) { - NSData *certificateID = NSDATA(2, 0xAA, 0xCE); - NSData *keyID = NSDATA(2, 0x11, 0x00); - if (![super populateIdentity:[smartCard readCert:certificateID error:error] certificateID:certificateID keyID:keyID auth:YES error:error]) { - return nil; - } - } - return self; -} - -- (TKTokenSession *)token:(TKToken *)token createSessionWithError:(NSError **)error { - NSLog(@"EstEIDToken createSessionWithError %@", self.AID); - return [[EstEIDTokenSession alloc] initWithToken:self]; -} - -@end - @implementation IDEMIAToken - (nullable instancetype)initWithSmartCard:(TKSmartCard *)smartCard AID:(nullable NSData *)AID tokenDriver:(TKSmartCardTokenDriver *)tokenDriver error:(NSError **)error { @@ -229,10 +185,7 @@ - (TKSmartCardToken *)tokenDriver:(TKSmartCardTokenDriver *)driver createTokenFo NSBundle *bundle = [NSBundle bundleForClass:EstEIDTokenDriver.class]; NSLog(@"EstEIDTokenDriver createTokenForSmartCard AID %@ version %@.%@", AID, bundle.infoDictionary[@"CFBundleShortVersionString"], bundle.infoDictionary[@"CFBundleVersion"]); [EstEIDTokenDriver showNotification:nil]; - if ([AID isEqualToData:NSDATA(16, 0xA0, 0x00, 0x00, 0x00, 0x77, 0x01, 0x08, 0x00, 0x07, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x01, 0x00)]) { - return [[IDEMIAToken alloc] initWithSmartCard:smartCard AID:AID tokenDriver:self error:error]; - } - return [[EstEIDToken alloc] initWithSmartCard:smartCard AID:AID tokenDriver:self error:error]; + return [[IDEMIAToken alloc] initWithSmartCard:smartCard AID:AID tokenDriver:self error:error]; } + (void)showNotification:(NSString*__nullable)msg { @@ -248,8 +201,9 @@ + (void)showNotification:(NSString*__nullable)msg { NSBundle *bundle = [NSBundle bundleForClass:EstEIDTokenDriver.class]; NSString *path = [bundle.bundlePath.stringByDeletingLastPathComponent.stringByDeletingLastPathComponent stringByAppendingString:@"/Resources/EstEIDTokenNotify.app"]; NSLog(@"EstEIDTokenDriver showNotification path: %@", path); - BOOL isLaunched = [NSWorkspace.sharedWorkspace launchApplication:path]; - NSLog(@"EstEIDTokenDriver showNotification launchApplication: %d", isLaunched); + [NSWorkspace.sharedWorkspace openApplicationAtURL:[NSURL fileURLWithPath:path isDirectory:YES] configuration:NSWorkspaceOpenConfiguration.configuration completionHandler:^(NSRunningApplication *app, NSError *error) { + NSLog(@"EstEIDTokenDriver showNotification openApplicationAtURL: %@", error); + }]; } [NSDistributedNotificationCenter.defaultCenter postNotificationName:@"EstEIDTokenNotify" object:msg userInfo:nil deliverImmediately:YES]; } diff --git a/EstEIDToken/TokenSession.m b/EstEIDToken/TokenSession.m index 75c4040..c60f021 100644 --- a/EstEIDToken/TokenSession.m +++ b/EstEIDToken/TokenSession.m @@ -352,54 +352,6 @@ - (NSData *)tokenSession:(TKTokenSession *)session signData:(NSData *)dataToSign @end -@implementation EstEIDTokenSession - -- (BOOL)initSignEnv:(NSError **)error { - NSLog(@"EstEIDTokenSession initSignEnv"); - UInt16 sw; - [self.smartCard sendIns:0x22 p1:0xF3 p2:0x01 data:nil le:@0 sw:&sw error:error]; - if (sw != 0x9000) { - NSLog(@"EstEIDTokenSession signData failed to set sec env"); - if (error != nil) { - *error = [NSError errorWithDomain:TKErrorDomain code:TKErrorCodeCorruptedData userInfo:nil]; - } - [self closeSession]; - return NO; - } - - [self.smartCard sendIns:0x22 p1:0x41 p2:0xB8 data:NSDATA(2, 0x83, 0x00) le:nil sw:&sw error:error]; //Key reference, 8303801100 - if (sw != 0x9000) { - NSLog(@"EstEIDTokenSession signData failed to select default key"); - if (error != nil) { - *error = [NSError errorWithDomain:TKErrorDomain code:TKErrorCodeCorruptedData userInfo:nil]; - } - [self closeSession]; - return NO; - } - return YES; -} - -- (UInt8)triesLeft:(NSError **)error { - NSLog(@"EstEIDTokenSession triesLeft"); - UInt16 sw; - NSData *pinStatus; - if ([self.smartCard sendIns:0xA4 p1:0x00 p2:0x0C data:nil le:@0 sw:&sw error:error] == nil || - [self.smartCard sendIns:0xA4 p1:0x02 p2:0x0C data:NSDATA(2, 0x00, 0x16) le:@0 sw:&sw error:error] == nil || - (pinStatus = [self.smartCard sendIns:0xB2 p1:0x01 p2:0x04 data:nil le:@0 sw:&sw error:error]) == nil) { - NSLog(@"EstEIDTokenSession triesLeft %d %@", sw, pinStatus); - [self closeSession]; - if (error != nil) { - *error = [NSError errorWithDomain:TKErrorDomain code:TKErrorCodeAuthenticationFailed userInfo:@{NSLocalizedDescriptionKey:NSLocalizedString(@"WRONG_CONSTR", nil)}]; - } - return 0; - } - UInt8 triesLeft = 0; - [pinStatus getBytes:&triesLeft range:NSMakeRange(5, sizeof(triesLeft))]; - return triesLeft; -} - -@end - @implementation IDEMIATokenSession - (BOOL)initSignEnv:(NSError **)error { diff --git a/EstEIDTokenApp.xcodeproj/project.pbxproj b/EstEIDTokenApp.xcodeproj/project.pbxproj index 8adddbf..8449239 100644 --- a/EstEIDTokenApp.xcodeproj/project.pbxproj +++ b/EstEIDTokenApp.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -27,7 +27,7 @@ 2F3883A21CF46C6E00F114A7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2F3883A11CF46C6E00F114A7 /* Assets.xcassets */; }; 2F3883A51CF46C6F00F114A7 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2F3883A31CF46C6F00F114A7 /* MainMenu.xib */; }; 2F3883B91CF46C9D00F114A7 /* Token.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F3883B81CF46C9D00F114A7 /* Token.m */; }; - 2F3883BF1CF46C9D00F114A7 /* EstEIDToken.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 2F3883B01CF46C9D00F114A7 /* EstEIDToken.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 2F3883BF1CF46C9D00F114A7 /* EstEIDToken.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 2F3883B01CF46C9D00F114A7 /* EstEIDToken.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 2F3883C51CF46D6F00F114A7 /* TokenSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F3883C41CF46D6F00F114A7 /* TokenSession.m */; }; 2F7767771CF5E0A00062B0A8 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2F7767731CF5E0A00062B0A8 /* Localizable.strings */; }; 2F7767781CF5E0A00062B0A8 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 2F7767751CF5E0A00062B0A8 /* Localizable.stringsdict */; }; @@ -63,15 +63,15 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ - 2F3883C31CF46C9D00F114A7 /* Embed App Extensions */ = { + 2F3883C31CF46C9D00F114A7 /* Embed Foundation Extensions */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 13; files = ( - 2F3883BF1CF46C9D00F114A7 /* EstEIDToken.appex in Embed App Extensions */, + 2F3883BF1CF46C9D00F114A7 /* EstEIDToken.appex in Embed Foundation Extensions */, ); - name = "Embed App Extensions"; + name = "Embed Foundation Extensions"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ @@ -208,7 +208,7 @@ 2F3883941CF46C6E00F114A7 /* Sources */, 2F3883951CF46C6E00F114A7 /* Frameworks */, 2F3883961CF46C6E00F114A7 /* Resources */, - 2F3883C31CF46C9D00F114A7 /* Embed App Extensions */, + 2F3883C31CF46C9D00F114A7 /* Embed Foundation Extensions */, ); buildRules = ( ); @@ -261,7 +261,8 @@ 2F3883901CF46C6E00F114A7 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1230; + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1500; ORGANIZATIONNAME = ""; TargetAttributes = { 2F3883971CF46C6E00F114A7 = { @@ -453,10 +454,11 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -486,10 +488,12 @@ CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 0; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 4F425HHPH8; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -504,8 +508,8 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MARKETING_VERSION = 1.3.3; + MACOSX_DEPLOYMENT_TARGET = 11.0; + MARKETING_VERSION = 1.4.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; @@ -515,10 +519,11 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -549,10 +554,12 @@ CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 0; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 4F425HHPH8; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -561,8 +568,8 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MARKETING_VERSION = 1.3.3; + MACOSX_DEPLOYMENT_TARGET = 11.0; + MARKETING_VERSION = 1.4.0; OTHER_CODE_SIGN_FLAGS = "--timestamp --options=runtime"; SDKROOT = macosx; }; @@ -573,6 +580,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; INFOPLIST_FILE = EstEIDTokenApp/Info.plist; INSTALL_PATH = "$(LOCAL_APPS_DIR)/Utilities"; LD_RUNPATH_SEARCH_PATHS = ( @@ -589,6 +597,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; INFOPLIST_FILE = EstEIDTokenApp/Info.plist; INSTALL_PATH = "$(LOCAL_APPS_DIR)/Utilities"; LD_RUNPATH_SEARCH_PATHS = ( @@ -605,6 +614,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = EstEIDToken/EstEIDToken.entitlements; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; INFOPLIST_FILE = EstEIDToken/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -622,6 +632,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = EstEIDToken/EstEIDToken.entitlements; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; INFOPLIST_FILE = EstEIDToken/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -637,6 +648,7 @@ 4E5814FB20225F53008493DC /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + DEAD_CODE_STRIPPING = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -644,6 +656,7 @@ 4E5814FC20225F53008493DC /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + DEAD_CODE_STRIPPING = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -653,6 +666,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; INFOPLIST_FILE = EstEIDTokenNotify/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -669,6 +683,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; + DEAD_CODE_STRIPPING = YES; INFOPLIST_FILE = EstEIDTokenNotify/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/EstEIDTokenNotify/AppDelegate.m b/EstEIDTokenNotify/AppDelegate.m index 923f1f2..9bcab25 100644 --- a/EstEIDTokenNotify/AppDelegate.m +++ b/EstEIDTokenNotify/AppDelegate.m @@ -18,51 +18,45 @@ */ #import +#import -@interface AppDelegate : NSObject +@interface AppDelegate : NSObject @end @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)notification { + UNUserNotificationCenter *center = UNUserNotificationCenter.currentNotificationCenter; + UNAuthorizationOptions options = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge; + [center requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError *error) { + if (granted) { + NSLog(@"EstEIDTokenNotify: requestAuthorizationWithOptions %i %@", granted, error); + } + }]; [NSDistributedNotificationCenter.defaultCenter addObserver:self selector:@selector(notificationEvent:) name:@"EstEIDTokenNotify" object:nil]; } -(void)notificationEvent:(NSNotification *)notification { - NSLog(@"EstEIDTokenNotify: notificationEvent %@", notification.object); - NSUserNotificationCenter *center = NSUserNotificationCenter.defaultUserNotificationCenter; + UNUserNotificationCenter *center = UNUserNotificationCenter.currentNotificationCenter; if (notification.object != nil) { NSArray *list = [(NSString*)notification.object componentsSeparatedByString:@"\n"]; - NSUserNotification *ui = [NSUserNotification new]; + UNMutableNotificationContent *ui = [UNMutableNotificationContent new]; ui.title = list[0]; if (list.count > 1) { ui.subtitle = list[1]; } - ui.hasActionButton = NO; - ui.soundName = NSUserNotificationDefaultSoundName; - center.delegate = self; - [center deliverNotification:ui]; + //ui.hasActionButton = NO; + ui.sound = UNNotificationSound.defaultSound; + NSString *uuidString = NSUUID.UUID.UUIDString; + UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:uuidString content:ui trigger:nil]; + [center addNotificationRequest:request withCompletionHandler:^(NSError *error) { + NSLog(@"EstEIDTokenNotify: addNotificationRequest %@", error); + }]; } else { [center removeAllDeliveredNotifications]; } } -- (void)userNotificationCenter:(NSUserNotificationCenter *)center didDeliverNotification:(NSUserNotification *)notification -{ - NSLog(@"EstEIDTokenNotify: didDeliverNotification %d", notification.isPresented); -} - -- (void)userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification -{ - NSLog(@"EstEIDTokenNotify: didActivateNotification"); -} - -- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification -{ - NSLog(@"EstEIDTokenNotify: shouldPresentNotification"); - return YES; -} - @end