5 // Created by Diggory Laycock
6 // Copyright 2005-2006 The Growl Project All rights reserved.
9 #import "GrowlSMSPrefs.h"
10 #import "GrowlDefinesInternal.h"
11 #import "NSStringAdditions.h"
12 #import <Security/SecKeychain.h>
13 #import <Security/SecKeychainItem.h>
15 #define GrowlSMSPrefDomain @"com.Growl.SMS"
16 #define accountNameKey @"SMS - Account Name"
17 #define accountAPIIDKey @"SMS - Account API ID"
18 #define destinationNumberKey @"SMS - Destination Number"
20 #define keychainServiceName "GrowlSMS"
21 #define keychainAccountName "SMSWebServicePassword"
24 @implementation GrowlSMSPrefs
26 - (NSString *) mainNibName {
27 return @"GrowlSMSPrefs";
31 SYNCHRONIZE_GROWL_PREFS();
36 - (NSString *) getAccountName {
37 NSString *value = nil;
38 READ_GROWL_PREF_VALUE(accountNameKey, GrowlSMSPrefDomain, NSString *, &value);
40 CFMakeCollectable(value);
41 return [value autorelease];
44 - (void) setAccountName:(NSString *)value {
47 WRITE_GROWL_PREF_VALUE(accountNameKey, value, GrowlSMSPrefDomain);
52 - (NSString *) getAccountAPIID {
53 NSString *value = nil;
54 READ_GROWL_PREF_VALUE(accountAPIIDKey, GrowlSMSPrefDomain, NSString *, &value);
56 CFMakeCollectable(value);
57 return [value autorelease];
60 - (void) setAccountAPIID:(NSString *)value {
63 WRITE_GROWL_PREF_VALUE(accountAPIIDKey, value, GrowlSMSPrefDomain);
68 - (NSString *) getDestinationNumber {
69 NSString *value = nil;
70 READ_GROWL_PREF_VALUE(destinationNumberKey, GrowlSMSPrefDomain, NSString *, &value);
72 CFMakeCollectable(value);
73 return [value autorelease];
76 - (void) setDestinationNumber:(NSString *)value {
79 WRITE_GROWL_PREF_VALUE(destinationNumberKey, value, GrowlSMSPrefDomain);
84 - (NSString *) accountPassword {
85 unsigned char *password;
86 UInt32 passwordLength;
88 status = SecKeychainFindGenericPassword( NULL,
89 (UInt32)strlen(keychainServiceName), keychainServiceName,
90 (UInt32)strlen(keychainAccountName), keychainAccountName,
91 &passwordLength, (void **)&password, NULL );
93 NSString *passwordString;
94 if (status == noErr) {
95 passwordString = (NSString *)CFStringCreateWithBytes(kCFAllocatorDefault, password, passwordLength, kCFStringEncodingUTF8, false);
97 CFMakeCollectable(passwordString);
98 [passwordString autorelease];
99 SecKeychainItemFreeContent(NULL, password);
101 if (status != errSecItemNotFound)
102 NSLog(@"Failed to retrieve SMS Account password from keychain. Error: %d", status);
103 passwordString = @"";
106 return passwordString;
109 - (void) setAccountPassword:(NSString *)value {
110 const char *password = value ? [value UTF8String] : "";
111 UInt32 length = (UInt32)strlen(password);
113 SecKeychainItemRef itemRef = nil;
114 status = SecKeychainFindGenericPassword( NULL,
115 (UInt32)strlen(keychainServiceName), keychainServiceName,
116 (UInt32)strlen(keychainAccountName), keychainAccountName,
117 NULL, NULL, &itemRef );
118 if (status == errSecItemNotFound) {
120 status = SecKeychainAddGenericPassword( NULL,
121 (UInt32)strlen(keychainServiceName), keychainServiceName,
122 (UInt32)strlen(keychainAccountName), keychainAccountName,
123 length, password, NULL );
125 NSLog(@"Failed to add SMS Account password to keychain.");
127 // change existing password
128 SecKeychainAttribute attrs[] = {
129 { kSecAccountItemAttr, (UInt32)strlen(keychainAccountName), (char *)keychainAccountName },
130 { kSecServiceItemAttr, (UInt32)strlen(keychainServiceName), (char *)keychainServiceName }
132 const SecKeychainAttributeList attributes = { (UInt32)sizeof(attrs) / (UInt32)sizeof(attrs[0]), attrs };
133 status = SecKeychainItemModifyAttributesAndData( itemRef, // the item reference
134 &attributes, // no change to attributes
135 length, // length of password
136 password // pointer to password data
141 NSLog(@"Failed to change SMS password in keychain.");