Merge lp:~rockstar/ubuntuoneauthkit/more-cleanup into lp:ubuntuoneauthkit

Proposed by Paul Hummer
Status: Merged
Approved by: Paul Hummer
Approved revision: 16
Merged at revision: 7
Proposed branch: lp:~rockstar/ubuntuoneauthkit/more-cleanup
Merge into: lp:ubuntuoneauthkit
Diff against target: 1446 lines (+214/-995)
14 files modified
.bzrignore (+1/-0)
Reachability.h (+0/-89)
Reachability.m (+0/-274)
SFHFKeychainUtils.h (+0/-41)
SFHFKeychainUtils.m (+0/-272)
Subsonic.h (+0/-51)
Subsonic.m (+0/-148)
SynthesizeSingleton.h (+0/-68)
UbuntuOneAuthKit.xcodeproj/project.pbxproj (+24/-28)
UbuntuOneAuthKit/UOAuthManager.h (+5/-0)
UbuntuOneAuthKit/UOAuthManager.m (+20/-20)
UbuntuOneAuthKit/UOKeyManager.h (+16/-0)
UbuntuOneAuthKit/UOKeyManager.m (+92/-0)
UbuntuOneAuthKitTests/UbuntuOneAuthKitTests.m (+56/-4)
To merge this branch: bzr merge lp:~rockstar/ubuntuoneauthkit/more-cleanup
Reviewer Review Type Date Requested Status
Zachery Bir Approve
Review via email: mp+126339@code.launchpad.net

Commit message

Kill Subsonic deps, teach UOAuthManager about Subsonic creds.

Description of the change

This branch kills two dependencies: Subsonic and SFHFKeychainUtils. The way I killed these deps is by implementing a private UOKeyManager that handles the low-level keychain stuff. As I did this, I wrote tests to make sure everything worked the way it should. I then made UOAuthManager use this new class instead of Subsonic (and, subsequently, SFHFKeychainUtils). Now UOAuthManager knows enough to handle its own auth methods.

There's a companion branch for Music that will go with this branch, essentially implementing these changes. When running the tests for this, I learned that it operates on the "production" keychain, so you'll blow away your credentials if you run the tests. I chased a bug where I wasn't cleaning up the tests properly, and the tests were poisoning my credentials, and that's how I discovered this. The tests now clean up properly, but will delete your actual keychain details.

To post a comment you must log in.
Revision history for this message
Zachery Bir (urbanape) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2012-09-15 17:33:52 +0000
3+++ .bzrignore 2012-09-25 21:23:23 +0000
4@@ -1,2 +1,3 @@
5 .DS_Store
6 UbuntuOneAuthKit.xcodeproj/xcuserdata
7+UbuntuOneAuthKit.xcodeproj/project.xcworkspace/
8
9=== removed file 'Reachability.h'
10--- Reachability.h 2012-09-17 03:30:01 +0000
11+++ Reachability.h 1970-01-01 00:00:00 +0000
12@@ -1,89 +0,0 @@
13-/*
14-
15- File: Reachability.h
16- Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
17-
18- Version: 2.0
19-
20- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
21- ("Apple") in consideration of your agreement to the following terms, and your
22- use, installation, modification or redistribution of this Apple software
23- constitutes acceptance of these terms. If you do not agree with these terms,
24- please do not use, install, modify or redistribute this Apple software.
25-
26- In consideration of your agreement to abide by the following terms, and subject
27- to these terms, Apple grants you a personal, non-exclusive license, under
28- Apple's copyrights in this original Apple software (the "Apple Software"), to
29- use, reproduce, modify and redistribute the Apple Software, with or without
30- modifications, in source and/or binary forms; provided that if you redistribute
31- the Apple Software in its entirety and without modifications, you must retain
32- this notice and the following text and disclaimers in all such redistributions
33- of the Apple Software.
34- Neither the name, trademarks, service marks or logos of Apple Inc. may be used
35- to endorse or promote products derived from the Apple Software without specific
36- prior written permission from Apple. Except as expressly stated in this notice,
37- no other rights or licenses, express or implied, are granted by Apple herein,
38- including but not limited to any patent rights that may be infringed by your
39- derivative works or by other works in which the Apple Software may be
40- incorporated.
41-
42- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
43- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
44- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
45- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
46- COMBINATION WITH YOUR PRODUCTS.
47-
48- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
49- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
50- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
52- DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
53- CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
54- APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55-
56- Copyright (C) 2009 Apple Inc. All Rights Reserved.
57-
58-*/
59-
60-
61-#import <Foundation/Foundation.h>
62-#import <SystemConfiguration/SystemConfiguration.h>
63-#import <netinet/in.h>
64-
65-typedef enum {
66- NotReachable = 0,
67- ReachableViaWiFi,
68- ReachableViaWWAN
69-} NetworkStatus;
70-#define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification"
71-
72-@interface Reachability: NSObject
73-{
74- BOOL localWiFiRef;
75- SCNetworkReachabilityRef reachabilityRef;
76-}
77-
78-//reachabilityWithHostName- Use to check the reachability of a particular host name.
79-+ (Reachability*) reachabilityWithHostName: (NSString*) hostName;
80-
81-//reachabilityWithAddress- Use to check the reachability of a particular IP address.
82-+ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
83-
84-//reachabilityForInternetConnection- checks whether the default route is available.
85-// Should be used by applications that do not connect to a particular host
86-+ (Reachability*) reachabilityForInternetConnection;
87-
88-//reachabilityForLocalWiFi- checks whether a local wifi connection is available.
89-+ (Reachability*) reachabilityForLocalWiFi;
90-
91-//Start listening for reachability notifications on the current run loop
92-- (BOOL) startNotifer;
93-- (void) stopNotifer;
94-
95-- (NetworkStatus) currentReachabilityStatus;
96-//WWAN may be available, but not active until a connection has been established.
97-//WiFi may require a connection for VPN on Demand.
98-- (BOOL) connectionRequired;
99-@end
100-
101-
102
103=== removed file 'Reachability.m'
104--- Reachability.m 2012-09-17 03:30:01 +0000
105+++ Reachability.m 1970-01-01 00:00:00 +0000
106@@ -1,274 +0,0 @@
107-/*
108-
109- File: Reachability.m
110- Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
111-
112- Version: 2.0
113-
114- Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc.
115- ("Apple") in consideration of your agreement to the following terms, and your
116- use, installation, modification or redistribution of this Apple software
117- constitutes acceptance of these terms. If you do not agree with these terms,
118- please do not use, install, modify or redistribute this Apple software.
119-
120- In consideration of your agreement to abide by the following terms, and subject
121- to these terms, Apple grants you a personal, non-exclusive license, under
122- Apple's copyrights in this original Apple software (the "Apple Software"), to
123- use, reproduce, modify and redistribute the Apple Software, with or without
124- modifications, in source and/or binary forms; provided that if you redistribute
125- the Apple Software in its entirety and without modifications, you must retain
126- this notice and the following text and disclaimers in all such redistributions
127- of the Apple Software.
128- Neither the name, trademarks, service marks or logos of Apple Inc. may be used
129- to endorse or promote products derived from the Apple Software without specific
130- prior written permission from Apple. Except as expressly stated in this notice,
131- no other rights or licenses, express or implied, are granted by Apple herein,
132- including but not limited to any patent rights that may be infringed by your
133- derivative works or by other works in which the Apple Software may be
134- incorporated.
135-
136- The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
137- WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
138- WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
139- PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
140- COMBINATION WITH YOUR PRODUCTS.
141-
142- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
143- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
144- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
145- ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR
146- DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF
147- CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
148- APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
149-
150- Copyright (C) 2009 Apple Inc. All Rights Reserved.
151-
152-*/
153-
154-#import <sys/socket.h>
155-#import <netinet/in.h>
156-#import <netinet6/in6.h>
157-#import <arpa/inet.h>
158-#import <ifaddrs.h>
159-#import <netdb.h>
160-
161-#import <CoreFoundation/CoreFoundation.h>
162-
163-#import "Reachability.h"
164-
165-#define kShouldPrintReachabilityFlags 0
166-
167-static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment)
168-{
169-#if kShouldPrintReachabilityFlags
170-
171- NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
172- (flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
173- (flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
174-
175- (flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
176- (flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
177- (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
178- (flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
179- (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
180- (flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
181- (flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-',
182- comment
183- );
184-#endif
185-}
186-
187-
188-@implementation Reachability
189-static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
190-{
191- #pragma unused (target, flags)
192- NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
193- NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
194-
195- //We're on the main RunLoop, so an NSAutoreleasePool is not necessary, but is added defensively
196- // in case someon uses the Reachablity object in a different thread.
197- NSAutoreleasePool* myPool = [[NSAutoreleasePool alloc] init];
198-
199- Reachability* noteObject = (Reachability*) info;
200- // Post a notification to notify the client that the network reachability changed.
201- [[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
202-
203- [myPool release];
204-}
205-
206-- (BOOL) startNotifer
207-{
208- BOOL retVal = NO;
209- SCNetworkReachabilityContext context = {0, self, NULL, NULL, NULL};
210- if(SCNetworkReachabilitySetCallback(reachabilityRef, ReachabilityCallback, &context))
211- {
212- if(SCNetworkReachabilityScheduleWithRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
213- {
214- retVal = YES;
215- }
216- }
217- return retVal;
218-}
219-
220-- (void) stopNotifer
221-{
222- if(reachabilityRef!= NULL)
223- {
224- SCNetworkReachabilityUnscheduleFromRunLoop(reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
225- }
226-}
227-
228-- (void) dealloc
229-{
230- [self stopNotifer];
231- if(reachabilityRef!= NULL)
232- {
233- CFRelease(reachabilityRef);
234- }
235- [super dealloc];
236-}
237-
238-+ (Reachability*) reachabilityWithHostName: (NSString*) hostName;
239-{
240- Reachability* retVal = NULL;
241- SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
242- if(reachability!= NULL)
243- {
244- retVal= [[[self alloc] init] autorelease];
245- if(retVal!= NULL)
246- {
247- retVal->reachabilityRef = reachability;
248- retVal->localWiFiRef = NO;
249- }
250- }
251- return retVal;
252-}
253-
254-+ (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress;
255-{
256- SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
257- Reachability* retVal = NULL;
258- if(reachability!= NULL)
259- {
260- retVal= [[[self alloc] init] autorelease];
261- if(retVal!= NULL)
262- {
263- retVal->reachabilityRef = reachability;
264- retVal->localWiFiRef = NO;
265- }
266- }
267- return retVal;
268-}
269-
270-+ (Reachability*) reachabilityForInternetConnection;
271-{
272- struct sockaddr_in zeroAddress;
273- bzero(&zeroAddress, sizeof(zeroAddress));
274- zeroAddress.sin_len = sizeof(zeroAddress);
275- zeroAddress.sin_family = AF_INET;
276- return [self reachabilityWithAddress: &zeroAddress];
277-}
278-
279-+ (Reachability*) reachabilityForLocalWiFi;
280-{
281- //[super init];
282- struct sockaddr_in localWifiAddress;
283- bzero(&localWifiAddress, sizeof(localWifiAddress));
284- localWifiAddress.sin_len = sizeof(localWifiAddress);
285- localWifiAddress.sin_family = AF_INET;
286- // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
287- localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
288- Reachability* retVal = [self reachabilityWithAddress: &localWifiAddress];
289- if(retVal!= NULL)
290- {
291- retVal->localWiFiRef = YES;
292- }
293- return retVal;
294-}
295-
296-#pragma mark Network Flag Handling
297-
298-- (NetworkStatus) localWiFiStatusForFlags: (SCNetworkReachabilityFlags) flags
299-{
300- PrintReachabilityFlags(flags, "localWiFiStatusForFlags");
301-
302- BOOL retVal = NotReachable;
303- if((flags & kSCNetworkReachabilityFlagsReachable) && (flags & kSCNetworkReachabilityFlagsIsDirect))
304- {
305- retVal = ReachableViaWiFi;
306- }
307- return retVal;
308-}
309-
310-- (NetworkStatus) networkStatusForFlags: (SCNetworkReachabilityFlags) flags
311-{
312- PrintReachabilityFlags(flags, "networkStatusForFlags");
313- if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
314- {
315- // if target host is not reachable
316- return NotReachable;
317- }
318-
319- BOOL retVal = NotReachable;
320-
321- if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
322- {
323- // if target host is reachable and no connection is required
324- // then we'll assume (for now) that your on Wi-Fi
325- retVal = ReachableViaWiFi;
326- }
327-
328-
329- if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
330- (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
331- {
332- // ... and the connection is on-demand (or on-traffic) if the
333- // calling application is using the CFSocketStream or higher APIs
334-
335- if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
336- {
337- // ... and no [user] intervention is needed
338- retVal = ReachableViaWiFi;
339- }
340- }
341-
342- if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
343- {
344- // ... but WWAN connections are OK if the calling application
345- // is using the CFNetwork (CFSocketStream?) APIs.
346- retVal = ReachableViaWWAN;
347- }
348- return retVal;
349-}
350-
351-- (BOOL) connectionRequired;
352-{
353- NSAssert(reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
354- SCNetworkReachabilityFlags flags;
355- if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
356- {
357- return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
358- }
359- return NO;
360-}
361-
362-- (NetworkStatus) currentReachabilityStatus
363-{
364- NSAssert(reachabilityRef != NULL, @"currentNetworkStatus called with NULL reachabilityRef");
365- NetworkStatus retVal = NotReachable;
366- SCNetworkReachabilityFlags flags;
367- if (SCNetworkReachabilityGetFlags(reachabilityRef, &flags))
368- {
369- if(localWiFiRef)
370- {
371- retVal = [self localWiFiStatusForFlags: flags];
372- }
373- else
374- {
375- retVal = [self networkStatusForFlags: flags];
376- }
377- }
378- return retVal;
379-}
380-@end
381
382=== removed file 'SFHFKeychainUtils.h'
383--- SFHFKeychainUtils.h 2012-09-17 03:30:01 +0000
384+++ SFHFKeychainUtils.h 1970-01-01 00:00:00 +0000
385@@ -1,41 +0,0 @@
386-//
387-// SFHFKeychainUtils.h
388-//
389-// Created by Buzz Andersen on 10/20/08.
390-// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone.
391-// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved.
392-//
393-// Permission is hereby granted, free of charge, to any person
394-// obtaining a copy of this software and associated documentation
395-// files (the "Software"), to deal in the Software without
396-// restriction, including without limitation the rights to use,
397-// copy, modify, merge, publish, distribute, sublicense, and/or sell
398-// copies of the Software, and to permit persons to whom the
399-// Software is furnished to do so, subject to the following
400-// conditions:
401-//
402-// The above copyright notice and this permission notice shall be
403-// included in all copies or substantial portions of the Software.
404-//
405-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
406-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
407-// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
408-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
409-// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
410-// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
411-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
412-// OTHER DEALINGS IN THE SOFTWARE.
413-//
414-
415-#import <UIKit/UIKit.h>
416-
417-
418-@interface SFHFKeychainUtils : NSObject {
419-
420-}
421-
422-+ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;
423-+ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error;
424-+ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;
425-
426-@end
427\ No newline at end of file
428
429=== removed file 'SFHFKeychainUtils.m'
430--- SFHFKeychainUtils.m 2012-09-17 03:30:01 +0000
431+++ SFHFKeychainUtils.m 1970-01-01 00:00:00 +0000
432@@ -1,272 +0,0 @@
433-//
434-// SFHFKeychainUtils.m
435-//
436-// Created by Buzz Andersen on 10/20/08.
437-// Based partly on code by Jonathan Wight, Jon Crosby, and Mike Malone.
438-// Copyright 2008 Sci-Fi Hi-Fi. All rights reserved.
439-//
440-// Permission is hereby granted, free of charge, to any person
441-// obtaining a copy of this software and associated documentation
442-// files (the "Software"), to deal in the Software without
443-// restriction, including without limitation the rights to use,
444-// copy, modify, merge, publish, distribute, sublicense, and/or sell
445-// copies of the Software, and to permit persons to whom the
446-// Software is furnished to do so, subject to the following
447-// conditions:
448-//
449-// The above copyright notice and this permission notice shall be
450-// included in all copies or substantial portions of the Software.
451-//
452-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
453-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
454-// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
455-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
456-// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
457-// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
458-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
459-// OTHER DEALINGS IN THE SOFTWARE.
460-//
461-
462-#import "SFHFKeychainUtils.h"
463-#import <Security/Security.h>
464-
465-static NSString *SFHFKeychainUtilsErrorDomain = @"SFHFKeychainUtilsErrorDomain";
466-
467-@implementation SFHFKeychainUtils
468-
469-
470-+ (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {
471- if (!username || !serviceName) {
472- if (error != nil) {
473- *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
474- }
475- return nil;
476- }
477-
478- if (error != nil) {
479- *error = nil;
480- }
481-
482- // Set up a query dictionary with the base query attributes: item type (generic), username, and service
483-
484- NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrService, nil] autorelease];
485- NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, username, serviceName, nil] autorelease];
486-
487- NSMutableDictionary *query = [[[NSMutableDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
488-
489- // First do a query for attributes, in case we already have a Keychain item with no password data set.
490- // One likely way such an incorrect item could have come about is due to the previous (incorrect)
491- // version of this code (which set the password as a generic attribute instead of password data).
492-
493- NSDictionary *attributeResult = NULL;
494- NSMutableDictionary *attributeQuery = [query mutableCopy];
495- [attributeQuery setObject: (id) kCFBooleanTrue forKey:(id) kSecReturnAttributes];
496- OSStatus status = SecItemCopyMatching((CFDictionaryRef) attributeQuery, (CFTypeRef *) &attributeResult);
497-
498- [attributeResult release];
499- [attributeQuery release];
500-
501- if (status != noErr) {
502- // No existing item found--simply return nil for the password
503- if (error != nil && status != errSecItemNotFound) {
504- //Only return an error if a real exception happened--not simply for "not found."
505- *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
506- }
507-
508- return nil;
509- }
510-
511- // We have an existing item, now query for the password data associated with it.
512-
513- NSData *resultData = nil;
514- NSMutableDictionary *passwordQuery = [query mutableCopy];
515- [passwordQuery setObject: (id) kCFBooleanTrue forKey: (id) kSecReturnData];
516-
517- status = SecItemCopyMatching((CFDictionaryRef) passwordQuery, (CFTypeRef *) &resultData);
518-
519- [resultData autorelease];
520- [passwordQuery release];
521-
522- if (status != noErr) {
523- if (status == errSecItemNotFound) {
524- // We found attributes for the item previously, but no password now, so return a special error.
525- // Users of this API will probably want to detect this error and prompt the user to
526- // re-enter their credentials. When you attempt to store the re-entered credentials
527- // using storeUsername:andPassword:forServiceName:updateExisting:error
528- // the old, incorrect entry will be deleted and a new one with a properly encrypted
529- // password will be added.
530- if (error != nil) {
531- *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil];
532- }
533- }
534- else {
535- // Something else went wrong. Simply return the normal Keychain API error code.
536- if (error != nil) {
537- *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
538- }
539- }
540-
541- return nil;
542- }
543-
544- NSString *password = nil;
545-
546- if (resultData) {
547- password = [[NSString alloc] initWithData: resultData encoding: NSUTF8StringEncoding];
548- }
549- else {
550- // There is an existing item, but we weren't able to get password data for it for some reason,
551- // Possibly as a result of an item being incorrectly entered by the previous code.
552- // Set the -1999 error so the code above us can prompt the user again.
553- if (error != nil) {
554- *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -1999 userInfo: nil];
555- }
556- }
557-
558- return [password autorelease];
559-}
560-
561-+ (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error
562-{
563- if (!username || !password || !serviceName)
564- {
565- if (error != nil)
566- {
567- *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
568- }
569- return NO;
570- }
571-
572- // See if we already have a password entered for these credentials.
573- NSError *getError = nil;
574- NSString *existingPassword = [SFHFKeychainUtils getPasswordForUsername: username andServiceName: serviceName error:&getError];
575-
576- if ([getError code] == -1999)
577- {
578- // There is an existing entry without a password properly stored (possibly as a result of the previous incorrect version of this code.
579- // Delete the existing item before moving on entering a correct one.
580-
581- getError = nil;
582-
583- [self deleteItemForUsername: username andServiceName: serviceName error: &getError];
584-
585- if ([getError code] != noErr)
586- {
587- if (error != nil)
588- {
589- *error = getError;
590- }
591- return NO;
592- }
593- }
594- else if ([getError code] != noErr)
595- {
596- if (error != nil)
597- {
598- *error = getError;
599- }
600- return NO;
601- }
602-
603- if (error != nil)
604- {
605- *error = nil;
606- }
607-
608- OSStatus status = noErr;
609-
610- if (existingPassword)
611- {
612- // We have an existing, properly entered item with a password.
613- // Update the existing item.
614-
615- if (![existingPassword isEqualToString:password] && updateExisting)
616- {
617- //Only update if we're allowed to update existing. If not, simply do nothing.
618-
619- NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass,
620- kSecAttrService,
621- kSecAttrLabel,
622- kSecAttrAccount,
623- nil] autorelease];
624-
625- NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword,
626- serviceName,
627- serviceName,
628- username,
629- nil] autorelease];
630-
631- NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
632-
633- status = SecItemUpdate((CFDictionaryRef) query, (CFDictionaryRef) [NSDictionary dictionaryWithObject: [password dataUsingEncoding: NSUTF8StringEncoding] forKey: (NSString *) kSecValueData]);
634- }
635- }
636- else
637- {
638- // No existing entry (or an existing, improperly entered, and therefore now
639- // deleted, entry). Create a new entry.
640-
641- NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass,
642- kSecAttrService,
643- kSecAttrLabel,
644- kSecAttrAccount,
645- kSecValueData,
646- nil] autorelease];
647-
648- NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword,
649- serviceName,
650- serviceName,
651- username,
652- [password dataUsingEncoding: NSUTF8StringEncoding],
653- nil] autorelease];
654-
655- NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
656-
657- status = SecItemAdd((CFDictionaryRef) query, NULL);
658- }
659-
660- if (error != nil && status != noErr)
661- {
662- // Something went wrong with adding the new item. Return the Keychain error code.
663- *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
664-
665- return NO;
666- }
667-
668- return YES;
669-}
670-
671-+ (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error
672-{
673- if (!username || !serviceName)
674- {
675- if (error != nil)
676- {
677- *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];
678- }
679- return NO;
680- }
681-
682- if (error != nil)
683- {
684- *error = nil;
685- }
686-
687- NSArray *keys = [[[NSArray alloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrService, kSecReturnAttributes, nil] autorelease];
688- NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, username, serviceName, kCFBooleanTrue, nil] autorelease];
689-
690- NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];
691-
692- OSStatus status = SecItemDelete((CFDictionaryRef) query);
693-
694- if (error != nil && status != noErr)
695- {
696- *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];
697-
698- return NO;
699- }
700-
701- return YES;
702-}
703-
704-@end
705\ No newline at end of file
706
707=== removed file 'Subsonic.h'
708--- Subsonic.h 2012-09-17 03:30:01 +0000
709+++ Subsonic.h 1970-01-01 00:00:00 +0000
710@@ -1,51 +0,0 @@
711-//
712-// Subsonic.h
713-// iSub
714-//
715-// Created by Aaron Brethorst on 9/23/10.
716-// Copyright 2010 Canonical Ltd.
717-//
718-// This program is free software: you can redistribute it and/or modify it
719-// under the terms of the GNU Affero General Public License version 3,
720-// as published by the Free Software Foundation.
721-//
722-// This program is distributed in the hope that it will be useful, but
723-// WITHOUT ANY WARRANTY; without even the implied warranties of
724-// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
725-// PURPOSE. See the GNU Affero General Public License for more details.
726-//
727-// You should have received a copy of the GNU Affero General Public License
728-// along with this program. If not, see <http://www.gnu.org/licenses/>.
729-
730-#import <Foundation/Foundation.h>
731-
732-@class Reachability;
733-
734-
735-@interface Subsonic : NSObject
736-{
737- NSString *credsURL;
738- NSString *defaultURL;
739- NSString *defaultUserName;
740- NSString *defaultPassword;
741- NSString *cachedIP;
742- NSInteger cachedIPHour;
743-}
744-@property BOOL hasCredentials;
745-@property(nonatomic,retain) NSString *credsURL;
746-@property(nonatomic,retain) NSString *metadataURL;
747-@property(nonatomic,retain) NSString *streamingURL;
748-@property(nonatomic,retain) NSString *defaultUserName;
749-@property(nonatomic,retain) NSString *defaultPassword;
750-@property(nonatomic,retain) NSString *cachedIP;
751-@property(nonatomic,assign) NSInteger cachedIPHour;
752-@property (readonly, retain) Reachability *reachability;
753-+ (Subsonic *)sharedSubsonic;
754-- (NSURL *)getCredsURL;
755-- (NSURL *)getMetadataURL:(NSString *)action;
756-- (NSURL *)getMetadataURL:(NSString *)action parameters:(NSArray *)extraParameters;
757-- (NSURL *)getStreamingURLForSongId:(NSString*)songId;
758-- (NSURL *)buildURLWithBase:(NSString *)baseURL action:(NSString *)action parameters:(NSArray *)extraParameters;
759-- (void)removeCredentials;
760-- (void)storeUsername:(NSString*)username password:(NSString*)password;
761-@end
762
763=== removed file 'Subsonic.m'
764--- Subsonic.m 2012-09-17 03:30:01 +0000
765+++ Subsonic.m 1970-01-01 00:00:00 +0000
766@@ -1,148 +0,0 @@
767-//
768-// Subsonic.m
769-// iSub
770-//
771-// Created by Aaron Brethorst on 9/23/10.
772-// Copyright 2010 Canonical Ltd.
773-//
774-// This program is free software: you can redistribute it and/or modify it
775-// under the terms of the GNU Affero General Public License version 3,
776-// as published by the Free Software Foundation.
777-//
778-// This program is distributed in the hope that it will be useful, but
779-// WITHOUT ANY WARRANTY; without even the implied warranties of
780-// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
781-// PURPOSE. See the GNU Affero General Public License for more details.
782-//
783-// You should have received a copy of the GNU Affero General Public License
784-// along with this program. If not, see <http://www.gnu.org/licenses/>.
785-
786-#import "Subsonic.h"
787-#import "SynthesizeSingleton.h"
788-#include <netinet/in.h>
789-#include <netdb.h>
790-#include <arpa/inet.h>
791-#import "NSMutableArray+Extras.h"
792-#import "Reachability.h"
793-
794-/* Added after the fact */
795-#import "SFHFKeychainUtils.h"
796-#define UBUNTU_ONE_SERVICE_NAME @"com.ubuntu.one"
797-#define UBUNTU_ONE_DUMMY_USER_NAME @"_UBUNTU_ONE_USER_NAME"
798-/* Done */
799-
800-
801-@interface Subsonic ()
802-@property (readwrite, retain) Reachability *reachability;
803-@end
804-
805-
806-@implementation Subsonic
807-@synthesize credsURL, metadataURL, streamingURL, defaultUserName, defaultPassword, cachedIP, cachedIPHour;
808-@synthesize reachability;
809-@dynamic hasCredentials;
810-
811-SYNTHESIZE_SINGLETON_FOR_CLASS(Subsonic);
812-
813-- (id)init
814-{
815- if ((self = [super init]))
816- {
817- self.streamingURL = @"https://streaming.one.ubuntu.com/rest";
818- self.metadataURL = @"https://one.ubuntu.com/music/api/1.0";
819- self.credsURL = @"https://one.ubuntu.com/phones/creds/ios?scheme=x-ubuntuone-music";
820- self.reachability = [Reachability reachabilityWithHostName:[[NSURL URLWithString:self.metadataURL] host]];
821- [self.reachability startNotifer];
822- }
823- return self;
824-}
825-
826-- (void)dealloc;
827-{
828- self.metadataURL = nil;
829- self.streamingURL = nil;
830- self.credsURL = nil;
831- [self.reachability stopNotifer];
832- self.reachability = nil;
833- [super dealloc];
834-}
835-
836-- (BOOL)hasCredentials
837-{
838- NSString *username = [SFHFKeychainUtils getPasswordForUsername:UBUNTU_ONE_DUMMY_USER_NAME andServiceName:UBUNTU_ONE_SERVICE_NAME error:nil];
839- if (username)
840- {
841- NSString *password = [SFHFKeychainUtils getPasswordForUsername:username andServiceName:UBUNTU_ONE_SERVICE_NAME error:nil];
842- return (password != nil);
843- }
844- else
845- {
846- return NO;
847- }
848-}
849-
850-- (void)removeCredentials
851-{
852- NSString *username = [[SFHFKeychainUtils getPasswordForUsername:UBUNTU_ONE_DUMMY_USER_NAME andServiceName:UBUNTU_ONE_SERVICE_NAME error:nil] retain];
853-
854- if (username)
855- {
856- [SFHFKeychainUtils deleteItemForUsername:UBUNTU_ONE_DUMMY_USER_NAME andServiceName:UBUNTU_ONE_SERVICE_NAME error:nil];
857- [SFHFKeychainUtils deleteItemForUsername:username andServiceName:UBUNTU_ONE_SERVICE_NAME error:nil];
858- }
859-
860- [username release];
861-}
862-
863-- (void)storeUsername:(NSString*)username password:(NSString*)password
864-{
865- [SFHFKeychainUtils storeUsername:UBUNTU_ONE_DUMMY_USER_NAME andPassword:username forServiceName:UBUNTU_ONE_SERVICE_NAME updateExisting:YES error:nil];
866- [SFHFKeychainUtils storeUsername:username andPassword:password forServiceName:UBUNTU_ONE_SERVICE_NAME updateExisting:YES error:nil];
867-
868- self.defaultUserName = username;
869- self.defaultPassword = password;
870-}
871-
872-- (NSURL *)getStreamingURLForSongId:(NSString*)songId
873-{
874- NSMutableArray *parameters = [NSMutableArray array];
875- [parameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"id", songId, nil]];
876- return [self buildURLWithBase:self.streamingURL action:@"stream.view" parameters:parameters];
877-}
878-
879-- (NSURL *)getCredsURL
880-{
881- return [NSURL URLWithString:self.credsURL];
882-}
883-
884-- (NSURL *)getMetadataURL:(NSString *)action;
885-{
886- return [self buildURLWithBase:self.metadataURL action:action parameters:nil];
887-}
888-
889-- (NSURL *)getMetadataURL:(NSString *)action parameters:(NSArray *)extraParameters;
890-{
891- return [self buildURLWithBase:self.metadataURL action:action parameters:extraParameters];
892-}
893-
894-- (NSURL *)buildURLWithBase:(NSString *)baseURL action:(NSString *)action parameters:(NSArray *)extraParameters;
895-{
896- if (self.defaultUserName && self.defaultPassword)
897- {
898- NSMutableArray *params = [NSMutableArray arrayWithArray:extraParameters];
899-
900- [params addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"u", self.defaultUserName, nil]];
901- [params addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"p", self.defaultPassword, nil]];
902- [params addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"v", @"1.1.0", nil]];
903- [params addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"c", @"Ubuntu One Music iOS", nil]];
904-
905- NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/%@?%@", baseURL, action, [params urlEncodedString]]];
906- return url;
907- }
908- else
909- {
910- return nil;
911- }
912-}
913-
914-@end
915
916=== removed file 'SynthesizeSingleton.h'
917--- SynthesizeSingleton.h 2012-09-17 03:30:01 +0000
918+++ SynthesizeSingleton.h 1970-01-01 00:00:00 +0000
919@@ -1,68 +0,0 @@
920-//
921-// SynthesizeSingleton.h
922-// CocoaWithLove
923-//
924-// Created by Matt Gallagher on 20/10/08.
925-// Copyright 2009 Matt Gallagher. All rights reserved.
926-//
927-// Permission is given to use this source code file without charge in any
928-// project, commercial or otherwise, entirely at your risk, with the condition
929-// that any redistribution (in part or whole) of source code must retain
930-// this copyright and permission notice. Attribution in compiled projects is
931-// appreciated but not required.
932-//
933-
934-#define SYNTHESIZE_SINGLETON_FOR_CLASS(classname) \
935- \
936-static classname *shared##classname = nil; \
937- \
938-+ (classname *)shared##classname \
939-{ \
940- @synchronized(self) \
941- { \
942- if (shared##classname == nil) \
943- { \
944- shared##classname = [[self alloc] init]; \
945- } \
946- } \
947- \
948- return shared##classname; \
949-} \
950- \
951-+ (id)allocWithZone:(NSZone *)zone \
952-{ \
953- @synchronized(self) \
954- { \
955- if (shared##classname == nil) \
956- { \
957- shared##classname = [super allocWithZone:zone]; \
958- return shared##classname; \
959- } \
960- } \
961- \
962- return nil; \
963-} \
964- \
965-- (id)copyWithZone:(NSZone *)zone \
966-{ \
967- return self; \
968-} \
969- \
970-- (id)retain \
971-{ \
972- return self; \
973-} \
974- \
975-- (NSUInteger)retainCount \
976-{ \
977- return NSUIntegerMax; \
978-} \
979- \
980-- (oneway void)release \
981-{ \
982-} \
983- \
984-- (id)autorelease \
985-{ \
986- return self; \
987-}
988
989=== modified file 'UbuntuOneAuthKit.xcodeproj/project.pbxproj'
990--- UbuntuOneAuthKit.xcodeproj/project.pbxproj 2012-09-17 03:30:01 +0000
991+++ UbuntuOneAuthKit.xcodeproj/project.pbxproj 2012-09-25 21:23:23 +0000
992@@ -7,6 +7,11 @@
993 objects = {
994
995 /* Begin PBXBuildFile section */
996+ 523CC106160B6B7000B36474 /* UOKeyManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 523CC104160B6B7000B36474 /* UOKeyManager.h */; };
997+ 523CC107160B6B7000B36474 /* UOKeyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 523CC105160B6B7000B36474 /* UOKeyManager.m */; };
998+ 523CC10C160B81DC00B36474 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CC10B160B81DC00B36474 /* Security.framework */; };
999+ 523CC10E160B81F000B36474 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 523CC10B160B81DC00B36474 /* Security.framework */; };
1000+ 523CC1191612424000B36474 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52B57D92160525AF0031E95C /* UIKit.framework */; };
1001 52527AFF16050BA7000F9A90 /* UONetworkStatusCoordinator.h in Headers */ = {isa = PBXBuildFile; fileRef = 52527AFD16050BA7000F9A90 /* UONetworkStatusCoordinator.h */; };
1002 52527B0016050BA7000F9A90 /* UONetworkStatusCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = 52527AFE16050BA7000F9A90 /* UONetworkStatusCoordinator.m */; };
1003 528515671604F16B004A1F7C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 528515661604F16B004A1F7C /* Foundation.framework */; };
1004@@ -68,15 +73,8 @@
1005 52B57DF016057DD80031E95C /* UOSSOMusicCredsFetchOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B57DEE16057DD80031E95C /* UOSSOMusicCredsFetchOperation.m */; };
1006 52B57DF316057F590031E95C /* UOURLQueryStringParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B57DF116057F590031E95C /* UOURLQueryStringParser.h */; };
1007 52B57DF416057F590031E95C /* UOURLQueryStringParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B57DF216057F590031E95C /* UOURLQueryStringParser.m */; };
1008- 52B57DF7160583000031E95C /* Subsonic.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B57DF5160583000031E95C /* Subsonic.h */; };
1009- 52B57DF8160583000031E95C /* Subsonic.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B57DF6160583000031E95C /* Subsonic.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
1010- 52B57DFA1605854D0031E95C /* SynthesizeSingleton.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B57DF91605854D0031E95C /* SynthesizeSingleton.h */; };
1011 52B57DFD160585880031E95C /* NSMutableArray+Extras.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B57DFB160585880031E95C /* NSMutableArray+Extras.h */; };
1012 52B57DFE160585880031E95C /* NSMutableArray+Extras.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B57DFC160585880031E95C /* NSMutableArray+Extras.m */; };
1013- 52B57E011605882C0031E95C /* Reachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B57DFF1605882C0031E95C /* Reachability.h */; };
1014- 52B57E021605882C0031E95C /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B57E001605882C0031E95C /* Reachability.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
1015- 52B57E05160631C70031E95C /* SFHFKeychainUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B57E03160631C60031E95C /* SFHFKeychainUtils.h */; };
1016- 52B57E06160631C70031E95C /* SFHFKeychainUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 52B57E04160631C60031E95C /* SFHFKeychainUtils.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
1017 /* End PBXBuildFile section */
1018
1019 /* Begin PBXContainerItemProxy section */
1020@@ -90,6 +88,9 @@
1021 /* End PBXContainerItemProxy section */
1022
1023 /* Begin PBXFileReference section */
1024+ 523CC104160B6B7000B36474 /* UOKeyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UOKeyManager.h; sourceTree = "<group>"; };
1025+ 523CC105160B6B7000B36474 /* UOKeyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UOKeyManager.m; sourceTree = "<group>"; };
1026+ 523CC10B160B81DC00B36474 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
1027 52527AFD16050BA7000F9A90 /* UONetworkStatusCoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UONetworkStatusCoordinator.h; sourceTree = "<group>"; };
1028 52527AFE16050BA7000F9A90 /* UONetworkStatusCoordinator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UONetworkStatusCoordinator.m; sourceTree = "<group>"; };
1029 528515631604F16B004A1F7C /* UbuntuOneAuthKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = UbuntuOneAuthKit.a; sourceTree = BUILT_PRODUCTS_DIR; };
1030@@ -156,15 +157,8 @@
1031 52B57DEE16057DD80031E95C /* UOSSOMusicCredsFetchOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UOSSOMusicCredsFetchOperation.m; sourceTree = "<group>"; };
1032 52B57DF116057F590031E95C /* UOURLQueryStringParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UOURLQueryStringParser.h; sourceTree = "<group>"; };
1033 52B57DF216057F590031E95C /* UOURLQueryStringParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UOURLQueryStringParser.m; sourceTree = "<group>"; };
1034- 52B57DF5160583000031E95C /* Subsonic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Subsonic.h; sourceTree = "<group>"; };
1035- 52B57DF6160583000031E95C /* Subsonic.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Subsonic.m; sourceTree = "<group>"; };
1036- 52B57DF91605854D0031E95C /* SynthesizeSingleton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SynthesizeSingleton.h; sourceTree = "<group>"; };
1037 52B57DFB160585880031E95C /* NSMutableArray+Extras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray+Extras.h"; sourceTree = "<group>"; };
1038 52B57DFC160585880031E95C /* NSMutableArray+Extras.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray+Extras.m"; sourceTree = "<group>"; };
1039- 52B57DFF1605882C0031E95C /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = "<group>"; };
1040- 52B57E001605882C0031E95C /* Reachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Reachability.m; sourceTree = "<group>"; };
1041- 52B57E03160631C60031E95C /* SFHFKeychainUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SFHFKeychainUtils.h; sourceTree = "<group>"; };
1042- 52B57E04160631C60031E95C /* SFHFKeychainUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SFHFKeychainUtils.m; sourceTree = "<group>"; };
1043 /* End PBXFileReference section */
1044
1045 /* Begin PBXFrameworksBuildPhase section */
1046@@ -172,6 +166,7 @@
1047 isa = PBXFrameworksBuildPhase;
1048 buildActionMask = 2147483647;
1049 files = (
1050+ 523CC10C160B81DC00B36474 /* Security.framework in Frameworks */,
1051 52B57D93160525AF0031E95C /* UIKit.framework in Frameworks */,
1052 528515671604F16B004A1F7C /* Foundation.framework in Frameworks */,
1053 );
1054@@ -181,6 +176,8 @@
1055 isa = PBXFrameworksBuildPhase;
1056 buildActionMask = 2147483647;
1057 files = (
1058+ 523CC1191612424000B36474 /* UIKit.framework in Frameworks */,
1059+ 523CC10E160B81F000B36474 /* Security.framework in Frameworks */,
1060 528515761604F16B004A1F7C /* SenTestingKit.framework in Frameworks */,
1061 528515791604F16B004A1F7C /* Foundation.framework in Frameworks */,
1062 5285157C1604F16B004A1F7C /* UbuntuOneAuthKit.a in Frameworks */,
1063@@ -190,16 +187,18 @@
1064 /* End PBXFrameworksBuildPhase section */
1065
1066 /* Begin PBXGroup section */
1067+ 523CC0FE160B697E00B36474 /* Utilities */ = {
1068+ isa = PBXGroup;
1069+ children = (
1070+ 523CC104160B6B7000B36474 /* UOKeyManager.h */,
1071+ 523CC105160B6B7000B36474 /* UOKeyManager.m */,
1072+ );
1073+ name = Utilities;
1074+ sourceTree = "<group>";
1075+ };
1076 52527B0216052179000F9A90 /* Dependencies */ = {
1077 isa = PBXGroup;
1078 children = (
1079- 52B57DFF1605882C0031E95C /* Reachability.h */,
1080- 52B57E001605882C0031E95C /* Reachability.m */,
1081- 52B57E03160631C60031E95C /* SFHFKeychainUtils.h */,
1082- 52B57E04160631C60031E95C /* SFHFKeychainUtils.m */,
1083- 52B57DF5160583000031E95C /* Subsonic.h */,
1084- 52B57DF6160583000031E95C /* Subsonic.m */,
1085- 52B57DF91605854D0031E95C /* SynthesizeSingleton.h */,
1086 52527B0316052194000F9A90 /* Categories */,
1087 52B57D98160528FF0031E95C /* oauthconsumer */,
1088 );
1089@@ -220,6 +219,7 @@
1090 528515581604F16B004A1F7C = {
1091 isa = PBXGroup;
1092 children = (
1093+ 523CC10B160B81DC00B36474 /* Security.framework */,
1094 528515681604F16B004A1F7C /* UbuntuOneAuthKit */,
1095 52527B0216052179000F9A90 /* Dependencies */,
1096 528515651604F16B004A1F7C /* Frameworks */,
1097@@ -250,6 +250,7 @@
1098 528515681604F16B004A1F7C /* UbuntuOneAuthKit */ = {
1099 isa = PBXGroup;
1100 children = (
1101+ 523CC0FE160B697E00B36474 /* Utilities */,
1102 528515AE1605034A004A1F7C /* UOAbstractNetworkOperation.h */,
1103 528515AF1605034A004A1F7C /* UOAbstractNetworkOperation.m */,
1104 5285159A1604F473004A1F7C /* UOAuthManager.h */,
1105@@ -394,11 +395,8 @@
1106 52B57DEB16052C710031E95C /* UOHTTPFetchOperation.h in Headers */,
1107 52B57DEF16057DD80031E95C /* UOSSOMusicCredsFetchOperation.h in Headers */,
1108 52B57DF316057F590031E95C /* UOURLQueryStringParser.h in Headers */,
1109- 52B57DF7160583000031E95C /* Subsonic.h in Headers */,
1110- 52B57DFA1605854D0031E95C /* SynthesizeSingleton.h in Headers */,
1111 52B57DFD160585880031E95C /* NSMutableArray+Extras.h in Headers */,
1112- 52B57E011605882C0031E95C /* Reachability.h in Headers */,
1113- 52B57E05160631C70031E95C /* SFHFKeychainUtils.h in Headers */,
1114+ 523CC106160B6B7000B36474 /* UOKeyManager.h in Headers */,
1115 );
1116 runOnlyForDeploymentPostprocessing = 0;
1117 };
1118@@ -526,10 +524,8 @@
1119 52B57DEC16052C710031E95C /* UOHTTPFetchOperation.m in Sources */,
1120 52B57DF016057DD80031E95C /* UOSSOMusicCredsFetchOperation.m in Sources */,
1121 52B57DF416057F590031E95C /* UOURLQueryStringParser.m in Sources */,
1122- 52B57DF8160583000031E95C /* Subsonic.m in Sources */,
1123 52B57DFE160585880031E95C /* NSMutableArray+Extras.m in Sources */,
1124- 52B57E021605882C0031E95C /* Reachability.m in Sources */,
1125- 52B57E06160631C70031E95C /* SFHFKeychainUtils.m in Sources */,
1126+ 523CC107160B6B7000B36474 /* UOKeyManager.m in Sources */,
1127 );
1128 runOnlyForDeploymentPostprocessing = 0;
1129 };
1130
1131=== modified file 'UbuntuOneAuthKit/UOAuthManager.h'
1132--- UbuntuOneAuthKit/UOAuthManager.h 2012-09-19 16:42:39 +0000
1133+++ UbuntuOneAuthKit/UOAuthManager.h 2012-09-25 21:23:23 +0000
1134@@ -8,6 +8,11 @@
1135
1136 #import <Foundation/Foundation.h>
1137
1138+static NSString *UOSubsonicUsernameKey = @"UOSubsonicUsername";
1139+static NSString *UOSubsonicPasswordKey = @"UOSubsonicPassword";
1140+
1141+static const NSString *UOSingleSignOnBaseURL = @"https://login.ubuntu.com/api/1.0/";
1142+
1143 @interface UOAuthManager : NSObject
1144 + (UOAuthManager *)sharedAuthManager;
1145 - (void)loginWithUsername:(NSString *)username andPassword:(NSString *)password tokenName:(NSString *)tokenName completionBlock:(void(^)())completionBlock errorBlock:(void(^)(NSError *))errorBlock;
1146
1147=== modified file 'UbuntuOneAuthKit/UOAuthManager.m'
1148--- UbuntuOneAuthKit/UOAuthManager.m 2012-09-19 16:42:39 +0000
1149+++ UbuntuOneAuthKit/UOAuthManager.m 2012-09-25 21:23:23 +0000
1150@@ -10,15 +10,14 @@
1151 #import "UOJSONFetchOperation.h"
1152 #import "UOHTTPFetchOperation.h"
1153 #import "UOSSOMusicCredsFetchOperation.h"
1154+#import "UOKeyManager.h"
1155
1156 #import "NSString+Extras.h"
1157 #import "OAConsumer.h"
1158 #import "OAToken.h"
1159 #import "OAPlaintextSignatureProvider.h"
1160 #import "OAMutableURLRequest.h"
1161-#import "Subsonic.h"
1162
1163-static NSString *const UOSingleSignOnBaseURL = @"https://login.ubuntu.com/api/1.0/";
1164 static NSString *UOSSOEncodedStringFromParametersDictionary(NSDictionary *arguments) {
1165 NSMutableArray *encodedArguments = [NSMutableArray array];
1166 [arguments enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
1167@@ -32,8 +31,6 @@
1168 }
1169
1170 @interface UOAuthManager () {
1171- NSString *subsonicUsername;
1172- NSString *subsonicPassword;
1173 NSOperationQueue *operationQueue;
1174
1175 /* rockstar (16 Sept 2012) - I don't like this interface. It does not persist,
1176@@ -64,7 +61,6 @@
1177 }
1178
1179 -(void)loginWithUsername:(NSString *)username andPassword:(NSString *)password tokenName:(NSString *)tokenName completionBlock:(void (^)())completionBlock errorBlock:(void (^)(NSError *))errorBlock {
1180- if (consumer || token || signatureProvider) { return; }
1181
1182 NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:@"authenticate", @"ws.op", tokenName, @"token_name", nil];
1183 NSString *paramsString = UOSSOEncodedStringFromParametersDictionary(params);
1184@@ -116,7 +112,6 @@
1185 #pragma mark Subsonic specific methods
1186
1187 -(void)fetchSubsonicCredentials:(void (^)(NSString *))completionBlock errorBlock:(void (^)(NSError *))errorBlock {
1188- if (consumer == nil) { return; }
1189
1190 NSURL *credsURL = [NSURL URLWithString:@"https://one.ubuntu.com/phones/creds/ios?scheme=x-ubuntuone-music"];
1191 OAMutableURLRequest *credsRequest = [[OAMutableURLRequest alloc] initWithURL:credsURL consumer:consumer token:token realm:nil signatureProvider:signatureProvider];
1192@@ -132,13 +127,22 @@
1193 return;
1194 }
1195
1196- subsonicUsername = credsOperation.username;
1197- subsonicPassword = credsOperation.password;
1198+ NSString *subsonicUsername = credsOperation.username;
1199+ NSString *subsonicPassword = credsOperation.password;
1200
1201 if (subsonicUsername && subsonicPassword) {
1202- [[Subsonic sharedSubsonic] storeUsername:subsonicUsername password:subsonicPassword];
1203- if (completionBlock) {
1204- completionBlock(subsonicUsername);
1205+ UOKeyManager *manager = [UOKeyManager sharedManager];
1206+ if ([manager createKey:UOSubsonicUsernameKey withValue:subsonicUsername] &&
1207+ [manager createKey:UOSubsonicPasswordKey withValue:subsonicPassword]) {
1208+ if (completionBlock) {
1209+ completionBlock(subsonicUsername);
1210+ }
1211+ } else {
1212+ NSString *message = NSLocalizedString(@"An error occurred storing credentials", nil);
1213+ NSError *error = [NSError errorWithDomain:@"UOAuthManagerErrorDomain"
1214+ code:-2
1215+ userInfo:[NSDictionary dictionaryWithObjectsAndKeys:message, NSLocalizedDescriptionKey, nil]];
1216+ errorBlock(error);
1217 }
1218 } else {
1219 if (errorBlock) {
1220@@ -154,21 +158,17 @@
1221 }
1222
1223 -(NSString *)subsonicUsername {
1224- if (!subsonicUsername) {
1225- subsonicUsername = [[Subsonic sharedSubsonic] defaultUserName];
1226- }
1227- return subsonicUsername;
1228+ return [[UOKeyManager sharedManager] readKey:UOSubsonicUsernameKey];
1229 }
1230
1231 -(NSString *)subsonicPassword {
1232- if (!subsonicPassword) {
1233- subsonicPassword = [[Subsonic sharedSubsonic] defaultPassword];
1234- }
1235- return subsonicPassword;
1236+ return [[UOKeyManager sharedManager] readKey:UOSubsonicPasswordKey];
1237 }
1238
1239 -(void)clearSubsonicCredentials {
1240- [[Subsonic sharedSubsonic] removeCredentials];
1241+ UOKeyManager *manager = [UOKeyManager sharedManager];
1242+ [manager deleteKey:UOSubsonicUsernameKey];
1243+ [manager deleteKey:UOSubsonicPasswordKey];
1244 }
1245
1246 @end
1247
1248=== added file 'UbuntuOneAuthKit/UOKeyManager.h'
1249--- UbuntuOneAuthKit/UOKeyManager.h 1970-01-01 00:00:00 +0000
1250+++ UbuntuOneAuthKit/UOKeyManager.h 2012-09-25 21:23:23 +0000
1251@@ -0,0 +1,16 @@
1252+//
1253+// UOKeyManager.h
1254+// UbuntuOneAuthKit
1255+//
1256+// Created by Paul Hummer on 9/20/12.
1257+// Copyright (c) 2012 Canonical, Ltd. All rights reserved.
1258+//
1259+
1260+#import <Foundation/Foundation.h>
1261+
1262+@interface UOKeyManager : NSObject
1263++(UOKeyManager *)sharedManager;
1264+-(BOOL)createKey:(NSString *)identifier withValue:(NSString *)value;
1265+-(NSString *)readKey:(NSString *)identifier;
1266+-(BOOL)deleteKey:(NSString *)identifier;
1267+@end
1268
1269=== added file 'UbuntuOneAuthKit/UOKeyManager.m'
1270--- UbuntuOneAuthKit/UOKeyManager.m 1970-01-01 00:00:00 +0000
1271+++ UbuntuOneAuthKit/UOKeyManager.m 2012-09-25 21:23:23 +0000
1272@@ -0,0 +1,92 @@
1273+//
1274+// UOKeyManager.m
1275+// UbuntuOneAuthKit
1276+//
1277+// Created by Paul Hummer on 9/20/12.
1278+// Copyright (c) 2012 Canonical, Ltd. All rights reserved.
1279+//
1280+
1281+#import "UOKeyManager.h"
1282+#import <Security/Security.h>
1283+
1284+static NSString *serviceName = @"[Ubuntu One Keychain]";
1285+
1286+@implementation UOKeyManager
1287+
1288++(UOKeyManager *)sharedManager {
1289+ static UOKeyManager *sharedInstance = nil;
1290+ static dispatch_once_t once;
1291+ dispatch_once(&once, ^{
1292+ sharedInstance = [[UOKeyManager alloc] init];
1293+ });
1294+ return sharedInstance;
1295+}
1296+
1297+-(NSMutableDictionary *)serviceDictionary:(NSString *)identifier {
1298+ NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
1299+ [dictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
1300+
1301+ [dictionary setObject:identifier forKey:(__bridge id)kSecAttrAccount];
1302+ [dictionary setObject:serviceName forKey:(__bridge id)kSecAttrService];
1303+ [dictionary setObject:serviceName forKey:(__bridge id)kSecAttrLabel];
1304+
1305+ return dictionary;
1306+}
1307+
1308+-(BOOL)createKey:(NSString *)identifier withValue:(NSString *)value {
1309+
1310+ NSString *existing = [self readKey:identifier];
1311+ if (existing) {
1312+ [self deleteKey:identifier];
1313+ }
1314+
1315+ NSMutableDictionary *dictionary = [self serviceDictionary:identifier];
1316+#if TARGET_IPHONE_SIMULATOR
1317+ /* This isn't required, but the example app does it, and we may want to add the access group
1318+ later on, and I don't want to have to go figure this obscure thing out.
1319+ */
1320+ [dictionary removeObjectForKey:(__bridge id)kSecAttrAccessGroup];
1321+#endif
1322+
1323+ [dictionary setObject:[value dataUsingEncoding:NSUTF8StringEncoding] forKey:(__bridge id)kSecValueData];
1324+
1325+ OSStatus status = SecItemAdd((__bridge CFDictionaryRef)dictionary, NULL);
1326+ if (status == errSecSuccess) { // -25299 means duplicate item
1327+ return YES;
1328+ }
1329+ return NO;
1330+}
1331+
1332+-(BOOL)deleteKey:(NSString *)identifier {
1333+ NSMutableDictionary *dictionary = [self serviceDictionary:identifier];
1334+
1335+ OSStatus status = SecItemDelete((__bridge CFDictionaryRef)dictionary);
1336+ if (status == errSecSuccess) {
1337+ return YES;
1338+ }
1339+ return NO;
1340+}
1341+
1342+-(NSString *)readKey:(NSString *)identifier {
1343+ NSMutableDictionary *dictionary = [self serviceDictionary:identifier];
1344+
1345+ [dictionary setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
1346+ [dictionary setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
1347+
1348+ CFDataRef resultData = NULL;
1349+ OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)dictionary, (CFTypeRef *)&resultData);
1350+
1351+ if (status != errSecSuccess) {
1352+ /* We should really be handling the error here */
1353+ return nil;
1354+ }
1355+
1356+ NSData *result = (__bridge_transfer NSData *)resultData;
1357+ if (result) {
1358+ NSString *resultString = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
1359+ return resultString;
1360+ }
1361+ return nil;
1362+}
1363+
1364+@end
1365
1366=== modified file 'UbuntuOneAuthKitTests/UbuntuOneAuthKitTests.m'
1367--- UbuntuOneAuthKitTests/UbuntuOneAuthKitTests.m 2012-09-15 17:33:52 +0000
1368+++ UbuntuOneAuthKitTests/UbuntuOneAuthKitTests.m 2012-09-25 21:23:23 +0000
1369@@ -8,6 +8,12 @@
1370
1371 #import "UbuntuOneAuthKitTests.h"
1372
1373+#import "UOAuthManager.h"
1374+#import "UOKeyManager.h"
1375+
1376+static NSString *TestKey = @"Ubuntu One Test Key";
1377+static NSString *TestValue = @"Super Cool Wrist Bands";
1378+
1379 @implementation UbuntuOneAuthKitTests
1380
1381 - (void)setUp
1382@@ -19,14 +25,60 @@
1383
1384 - (void)tearDown
1385 {
1386- // Tear-down code here.
1387+ UOKeyManager *manager = [UOKeyManager sharedManager];
1388+ NSArray *keys = [NSArray arrayWithObjects:TestKey, UOSubsonicUsernameKey, UOSubsonicPasswordKey, nil];
1389+ for (NSString *key in keys) {
1390+ [manager deleteKey:key];
1391+ }
1392
1393 [super tearDown];
1394 }
1395
1396-- (void)testExample
1397-{
1398- STFail(@"Unit tests are not implemented yet in UbuntuOneAuthKitTests");
1399+#pragma mark
1400+#pragma mark UOKeyManager Tests
1401+
1402+- (void)testUOKeyManagerCreateKey {
1403+ STAssertTrue([[UOKeyManager sharedManager] createKey:TestKey withValue:TestValue], nil);
1404+}
1405+
1406+- (void)testUOKeyManagerDeleteKey {
1407+ [[UOKeyManager sharedManager] createKey:TestKey withValue:TestValue];
1408+
1409+ STAssertTrue([[UOKeyManager sharedManager] deleteKey:TestKey], nil);
1410+}
1411+
1412+- (void)testUOKeyManagerGetKey {
1413+ [[UOKeyManager sharedManager] createKey:TestKey withValue:TestValue];
1414+ STAssertEqualObjects([[UOKeyManager sharedManager] readKey:TestKey], TestValue, nil);
1415+}
1416+
1417+#pragma mark
1418+#pragma mark UOAuthManager Tests
1419+
1420+- (void)testUOAuthManagerSubsonicUsername {
1421+ NSString *username = @"Test User";
1422+ [[UOKeyManager sharedManager] createKey:UOSubsonicUsernameKey withValue:username];
1423+
1424+ STAssertEqualObjects([[UOAuthManager sharedAuthManager] subsonicUsername], username, nil);
1425+}
1426+
1427+- (void)testUOAuthManagerSubsonicPassword {
1428+ NSString *password = @"password1234";
1429+ [[UOKeyManager sharedManager] createKey:UOSubsonicPasswordKey withValue:password];
1430+
1431+ STAssertEqualObjects([[UOAuthManager sharedAuthManager] subsonicPassword], password, nil);
1432+}
1433+
1434+- (void)testUOAuthManagerClearCredentials {
1435+ NSString *username = @"Test User";
1436+ NSString *password = @"password1234";
1437+ [[UOKeyManager sharedManager] createKey:UOSubsonicUsernameKey withValue:username];
1438+ [[UOKeyManager sharedManager] createKey:UOSubsonicPasswordKey withValue:password];
1439+
1440+ [[UOAuthManager sharedAuthManager] clearSubsonicCredentials];
1441+
1442+ STAssertNil([[UOKeyManager sharedManager] readKey:UOSubsonicUsernameKey], nil);
1443+ STAssertNil([[UOKeyManager sharedManager] readKey:UOSubsonicPasswordKey], nil);
1444 }
1445
1446 @end

Subscribers

People subscribed via source and target branches