Merge lp:~rockstar/ubuntuoneauthkit/more-cleanup into lp:ubuntuoneauthkit
- more-cleanup
- Merge into trunk
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 |
Related bugs: |
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.
Zachery Bir (urbanape) : | # |
Preview Diff
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 |