Skip to content

Commit

Permalink
GPGWatcher can now watch .conf and raise a new notification
Browse files Browse the repository at this point in the history
- new GPGConfigurationModifiedNotification for gpg.conf
  and gpg-agent.conf

- can now detect file creation; whereas before it could only
  detect file modification.

- GPGOptions observes GPGConfigurationModifiedNotification
  so that gpg.conf and gpg-agent.conf are re-read

- add to keyPathsForValuesAffectingValueForKey for gpgConf
  and gpgAgentConf dependents

- synchronize gpgConf and gpgAgentConf properties. At least
  one background thread I can think of (GPGServices' new
  ServiceWorker) accesses GPGOptions

- greatly reduce windows where fs events are dropped by
  GPGWatcher. latency is still 5s; toleranceBefore down to 1s
  from 10; toleranceAfter down to 1s from 5

- GPGWatcher timerFired: does not need to redundantly check
  times

- new pinentry deps: pinentry-mac falls back to curses when
  PINENTRY_USER_DATA contains USE_CURSES=1, to support ssh

for unit testing:

- test GPGConfigurationModifiedNotification

- rework GPGWatcher as normally a singleton, but allow another
  instance

- make toleranceBefore/After assignable properties

- a non-shared instance of GPGOptions can be properly
  deallocated, with event observers unregistered
  • Loading branch information
idodeclare committed May 27, 2012
1 parent 4bafd93 commit e202bf6
Show file tree
Hide file tree
Showing 13 changed files with 327 additions and 102 deletions.
2 changes: 1 addition & 1 deletion Dependencies/GPGTools_Core
Submodule GPGTools_Core updated from 55eb29 to 64d89b
2 changes: 1 addition & 1 deletion Dependencies/pinentry-mac
6 changes: 6 additions & 0 deletions Libmacgpg.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
45891A3F151BA1C9002D7410 /* SignedInputStringLF.txt in Resources */ = {isa = PBXBuildFile; fileRef = 45891A3D151BA1C9002D7410 /* SignedInputStringLF.txt */; };
45891A41151BA1EC002D7410 /* SignedInputStringCR.txt in Resources */ = {isa = PBXBuildFile; fileRef = 45891A40151BA1EC002D7410 /* SignedInputStringCR.txt */; };
4591C4CA14F85AA3007F6D47 /* GPGConfReaderTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4591C4C914F85AA3007F6D47 /* GPGConfReaderTest.m */; };
45B8C6AC157140A600FD49CD /* NSRunLoop+TimeOutAndFlag.m in Sources */ = {isa = PBXBuildFile; fileRef = 45B8C6AB157140A600FD49CD /* NSRunLoop+TimeOutAndFlag.m */; };
45B9A7F6151C9A6D00DAD67A /* OpenPGP.asc in Resources */ = {isa = PBXBuildFile; fileRef = 45B9A7F5151C9A6D00DAD67A /* OpenPGP.asc */; };
45C0BC03151B65C700AA8BF6 /* GPGTestVerify.m in Sources */ = {isa = PBXBuildFile; fileRef = 45C0BC02151B65C700AA8BF6 /* GPGTestVerify.m */; };
45C0BC18151B66F500AA8BF6 /* GPGResourceUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 45C0BC17151B66F500AA8BF6 /* GPGResourceUtil.m */; };
Expand Down Expand Up @@ -204,6 +205,8 @@
4591C4D314F86D38007F6D47 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
4591C4D414F86D38007F6D47 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
4591C4D514F86D38007F6D47 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
45B8C6AA157140A600FD49CD /* NSRunLoop+TimeOutAndFlag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSRunLoop+TimeOutAndFlag.h"; sourceTree = "<group>"; };
45B8C6AB157140A600FD49CD /* NSRunLoop+TimeOutAndFlag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSRunLoop+TimeOutAndFlag.m"; sourceTree = "<group>"; };
45B9A7F5151C9A6D00DAD67A /* OpenPGP.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = OpenPGP.asc; sourceTree = "<group>"; };
45C0BC02151B65C700AA8BF6 /* GPGTestVerify.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPGTestVerify.m; sourceTree = "<group>"; };
45C0BC16151B66F500AA8BF6 /* GPGResourceUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPGResourceUtil.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -378,6 +381,8 @@
isa = PBXGroup;
children = (
45C0BC13151B664D00AA8BF6 /* Resources */,
45B8C6AA157140A600FD49CD /* NSRunLoop+TimeOutAndFlag.h */,
45B8C6AB157140A600FD49CD /* NSRunLoop+TimeOutAndFlag.m */,
45C0BC16151B66F500AA8BF6 /* GPGResourceUtil.h */,
45C0BC17151B66F500AA8BF6 /* GPGResourceUtil.m */,
30C8B39A1395052D00F49AA1 /* Test1.h */,
Expand Down Expand Up @@ -611,6 +616,7 @@
45C0BC03151B65C700AA8BF6 /* GPGTestVerify.m in Sources */,
45C0BC18151B66F500AA8BF6 /* GPGResourceUtil.m in Sources */,
45DD3D4C15642A0D00C9A4C1 /* GPGSignatureTest.m in Sources */,
45B8C6AC157140A600FD49CD /* NSRunLoop+TimeOutAndFlag.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
5 changes: 3 additions & 2 deletions Source/GPGGlobals.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,9 @@ enum gpgStatusCodes {
#define GPGDebugLog(...) {if ([GPGOptions debugLog]) NSLog(__VA_ARGS__);}
#define GPG_SERVICE_NAME "GnuPG"

extern NSString *GPGKeysChangedNotification;
extern NSString *GPGOptionsChangedNotification;
extern NSString * const GPGKeysChangedNotification;
extern NSString * const GPGOptionsChangedNotification;
extern NSString * const GPGConfigurationModifiedNotification;



Expand Down
5 changes: 3 additions & 2 deletions Source/GPGGlobals.m
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,9 @@ - (NSSet *)usableGPGKeys {
@end


NSString *GPGKeysChangedNotification = @"GPGKeysChangedNotification";
NSString *GPGOptionsChangedNotification = @"GPGOptionsChangedNotification";
NSString * const GPGKeysChangedNotification = @"GPGKeysChangedNotification";
NSString * const GPGOptionsChangedNotification = @"GPGOptionsChangedNotification";
NSString * const GPGConfigurationModifiedNotification = @"GPGConfigurationModifiedNotification";


int hexToByte (const char *text) {
Expand Down
4 changes: 4 additions & 0 deletions Source/GPGOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

#import <Cocoa/Cocoa.h>
#import <SystemConfiguration/SCPreferences.h>

@class GPGConf;

Expand Down Expand Up @@ -46,6 +47,9 @@ typedef enum {
GPGConf *gpgAgentConf;
NSString *identifier;
NSUInteger updating;

SCPreferencesRef preferences;
id syncRoot;
}

@property (readonly) NSString *httpProxy;
Expand Down
103 changes: 85 additions & 18 deletions Source/GPGOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,12 @@ @interface GPGOptions ()
@property (readonly) NSMutableDictionary *standardDefaults;
- (GPGConf *)gpgConf;
- (GPGConf *)gpgAgentConf;
+ (GPGOptionsDomain)domainForKey:(NSString *)key;
- (void)valueChanged:(id)value forKey:(NSString *)key inDomain:(GPGOptionsDomain)domain;
- (void)valueChangedNotification:(NSNotification *)notification;
- (void)dotConfChangedNotification:(NSNotification *)notification;

- (void)stopSystemConfigurationWatch;
@end


Expand All @@ -46,6 +50,8 @@ @implementation GPGOptions
NSMutableDictionary *defaults = nil;
uint8 debugLog;

static NSString * const kGpgConfKVKey = @"gpgConf";
static NSString * const kGpgAgentConfKVKey = @"gpgAgentConf";

// Methods to configure GPGOptions.
- (BOOL)autoSave {
Expand Down Expand Up @@ -359,18 +365,22 @@ - (void)setValueInGPGAgentConf:(id)value forKey:(NSString *)key {

// Propertys.
- (GPGConf *)gpgConf {
if (!gpgConf) {
NSString *gpath = [[self gpgHome] stringByAppendingPathComponent:@"gpg.conf"];
gpgConf = [[GPGConf alloc] initWithPath:gpath andDomain:GPGDomain_gpgConf];
}
return [[gpgConf retain] autorelease];
@synchronized(syncRoot) {
if (!gpgConf) {
NSString *gpath = [[self gpgHome] stringByAppendingPathComponent:@"gpg.conf"];
gpgConf = [[GPGConf alloc] initWithPath:gpath andDomain:GPGDomain_gpgConf];
}
return [[gpgConf retain] autorelease];
}
}
- (GPGConf *)gpgAgentConf {
if (!gpgAgentConf) {
NSString *gpath = [[self gpgHome] stringByAppendingPathComponent:@"gpg-agent.conf"];
gpgAgentConf = [[GPGConf alloc] initWithPath:gpath andDomain:GPGDomain_gpgAgentConf];
}
return [[gpgAgentConf retain] autorelease];
@synchronized(syncRoot) {
if (!gpgAgentConf) {
NSString *gpath = [[self gpgHome] stringByAppendingPathComponent:@"gpg-agent.conf"];
gpgAgentConf = [[GPGConf alloc] initWithPath:gpath andDomain:GPGDomain_gpgAgentConf];
}
return [[gpgAgentConf retain] autorelease];
}
}

- (NSString *)gpgHome {
Expand Down Expand Up @@ -422,6 +432,9 @@ + (BOOL)debugLog {

// Helper methods.
- (GPGOptionsDomain)domainForKey:(NSString *)key {
return [GPGOptions domainForKey:key];
}
+ (GPGOptionsDomain)domainForKey:(NSString *)key {
for (NSNumber *keyType in domainKeys) {
NSSet *keys = [domainKeys objectForKey:keyType];
if ([keys containsObject:key]) {
Expand Down Expand Up @@ -461,12 +474,16 @@ void SystemConfigurationDidChange(SCPreferencesRef prefs, SCPreferencesNotificat
}
- (void)initSystemConfigurationWatch {
SCPreferencesContext context = {0, self, nil, nil, nil};
SCPreferencesRef preferences = SCPreferencesCreate(nil, (CFStringRef)[[NSProcessInfo processInfo] processName], nil);
preferences = SCPreferencesCreate(nil, (CFStringRef)[[NSProcessInfo processInfo] processName], nil);
SCPreferencesSetCallback(preferences, SystemConfigurationDidChange, &context);
SCPreferencesScheduleWithRunLoop(preferences, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFRelease(preferences);
}

- (void)stopSystemConfigurationWatch {
SCPreferencesUnscheduleFromRunLoop(preferences, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFRelease(preferences);
}

- (void)valueChanged:(id)value forKey:(NSString *)key inDomain:(GPGOptionsDomain)domain {
if (!updating) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:key, @"key", value, @"value", [NSNumber numberWithInt:domain], @"domain", (domain == GPGDomain_standard && standardDomain) ? standardDomain : nil, @"domainName", nil];
Expand Down Expand Up @@ -502,10 +519,25 @@ - (void)valueChangedNotification:(NSNotification *)notification {
}
}


- (void)dotConfChangedNotification:(NSNotification *)notification {
[self willChangeValueForKey:kGpgConfKVKey];
[self willChangeValueForKey:kGpgAgentConfKVKey];
@synchronized(syncRoot) {
[gpgConf release];
gpgConf = nil;
[gpgAgentConf release];
gpgAgentConf = nil;
}
[self didChangeValueForKey:kGpgConfKVKey];
[self didChangeValueForKey:kGpgAgentConfKVKey];
}

// Whatever…
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {

NSMutableSet *keyPaths = [NSMutableSet setWithSet:[super keyPathsForValuesAffectingValueForKey:key]];
// standard key will always be set; affectingKey may be set
NSString *standardKey = key;
NSString *affectingKey = nil;
if ([key rangeOfString:@"_"].length > 0) {
NSCharacterSet *set = [[NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyz_"] invertedSet];
Expand All @@ -521,10 +553,24 @@ + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
}
}
if (affectingKey) {
return [NSSet setWithObject:affectingKey];
} else {
return [super keyPathsForValuesAffectingValueForKey:key];
}
[keyPaths addObject:affectingKey];
standardKey = affectingKey;
}

// .conf dependents
switch ([GPGOptions domainForKey:standardKey]) {
case GPGDomain_gpgConf:
[keyPaths addObject:kGpgConfKVKey];
break;
case GPGDomain_gpgAgentConf:
[keyPaths addObject:kGpgAgentConfKVKey];
break;
default:
// nothing
break;
}

return keyPaths;
}


Expand Down Expand Up @@ -656,12 +702,33 @@ + (id)sharedOptions {
- (id)init {
self = [super init];
if(self) {
syncRoot = [[NSObject alloc] init];
autoSave = YES;
identifier = [[NSString alloc] initWithFormat:@"%i%p", [[NSProcessInfo processInfo] processIdentifier], self];
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(valueChangedNotification:) name:GPGOptionsChangedNotification object:nil];
NSDistributedNotificationCenter *notifsCenter = [NSDistributedNotificationCenter defaultCenter];
[notifsCenter addObserver:self selector:@selector(valueChangedNotification:) name:GPGOptionsChangedNotification object:nil];
[notifsCenter addObserver:self selector:@selector(dotConfChangedNotification:) name:GPGConfigurationModifiedNotification object:nil];
[self initSystemConfigurationWatch];
}
return self;
}

- (void)dealloc
{
NSDistributedNotificationCenter *notifsCenter = [NSDistributedNotificationCenter defaultCenter];
[notifsCenter removeObserver:self];
[self stopSystemConfigurationWatch];

[identifier release];
[environment release];
[standardDefaults release];
[commonDefaults release];
[httpProxy release];
[standardDomain release];
[gpgConf release];
[gpgAgentConf release];
[syncRoot release];
[super dealloc];
}

@end
19 changes: 18 additions & 1 deletion Source/GPGWatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,29 @@

@interface GPGWatcher : NSObject <DirectoryWatcherDelegate> {
DirectoryWatcher *dirWatcher;
// for pubring and secring
NSTimeInterval lastKnownChange; // Zeitpunkt der letzten Änderung durch eine Libmacgpg instanz.
NSTimeInterval lastFoundChange; // Zeitpunkt der letzten Änderung an einer Datei.
// for .conf
NSTimeInterval lastConfKnownChange;

NSString *identifier;
NSMutableDictionary *changeDates;
NSDictionary *filesToWatch;
NSString *gpgSpecifiedHome;

NSTimeInterval toleranceBefore;
NSTimeInterval toleranceAfter;
}

// default is 1.0
@property (assign, nonatomic) NSTimeInterval toleranceBefore;
// default is 1.0
@property (assign, nonatomic) NSTimeInterval toleranceAfter;

+ (id)sharedInstance;
+ (void)activate;

// really for unit testing. Use sharedInstance normally!
- (id)initWithGpgHome:(NSString *)directoryPath;

@end
Loading

0 comments on commit e202bf6

Please sign in to comment.