root / pithos-macos / PithosAccount.m @ baaf1397
History | View | Annotate | Download (24.3 kB)
1 |
// |
---|---|
2 |
// PithosAccount.m |
3 |
// pithos-macos |
4 |
// |
5 |
// Copyright 2012 GRNET S.A. All rights reserved. |
6 |
// |
7 |
// Redistribution and use in source and binary forms, with or |
8 |
// without modification, are permitted provided that the following |
9 |
// conditions are met: |
10 |
// |
11 |
// 1. Redistributions of source code must retain the above |
12 |
// copyright notice, this list of conditions and the following |
13 |
// disclaimer. |
14 |
// |
15 |
// 2. Redistributions in binary form must reproduce the above |
16 |
// copyright notice, this list of conditions and the following |
17 |
// disclaimer in the documentation and/or other materials |
18 |
// provided with the distribution. |
19 |
// |
20 |
// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
21 |
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
22 |
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
23 |
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
24 |
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
25 |
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
26 |
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
27 |
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
28 |
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
29 |
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
30 |
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
31 |
// POSSIBILITY OF SUCH DAMAGE. |
32 |
// |
33 |
// The views and conclusions contained in the software and |
34 |
// documentation are those of the authors and should not be |
35 |
// interpreted as representing official policies, either expressed |
36 |
// or implied, of GRNET S.A. |
37 |
|
38 |
#import "PithosAccount.h" |
39 |
#import "PithosSyncDaemon.h" |
40 |
#import "ASIPithos.h" |
41 |
#import "ASIPithosRequest.h" |
42 |
#import "PithosAccountNode.h" |
43 |
#import "PithosSharingAccountsNode.h" |
44 |
#import "PithosUtilities.h" |
45 |
#import "pithos_macosAppDelegate.h" |
46 |
|
47 |
static NSString *defaultAuthURLString = @"https://accounts.okeanos.grnet.gr/identity/v2.0"; |
48 |
static NSString *defaultManualURLString = @"https://pithos.okeanos.grnet.gr"; |
49 |
|
50 |
@interface NSString(Additions) |
51 |
- (BOOL)isValidURL; |
52 |
- (NSString *)stringByRemovingTrailingSlashes; |
53 |
@end |
54 |
|
55 |
@implementation NSString(Additions) |
56 |
- (BOOL)isValidURL { |
57 |
NSURL *URL = [NSURL URLWithString:self]; |
58 |
return (URL && URL.scheme && URL.host); |
59 |
} |
60 |
|
61 |
- (NSString *)stringByRemovingTrailingSlashes { |
62 |
NSString *stringWithRemovedTrailingSlashes = [self copy]; |
63 |
while ([stringWithRemovedTrailingSlashes hasSuffix:@"/"]) { |
64 |
stringWithRemovedTrailingSlashes = [stringWithRemovedTrailingSlashes substringToIndex:(stringWithRemovedTrailingSlashes.length - 1)]; |
65 |
} |
66 |
return stringWithRemovedTrailingSlashes; |
67 |
} |
68 |
@end |
69 |
|
70 |
@implementation PithosAccount |
71 |
@synthesize uniqueName, active, name, clientVersion; |
72 |
@synthesize syncActive, syncDirectoryPath, syncAccountsDictionary, syncSkipHidden, syncLastCompleted, syncDaemon; |
73 |
@synthesize authURLString, pithosObjectStoreURLString, astakosAccountURLString, astakosWebloginURLString, manual; |
74 |
@synthesize authToken, authUser, userCatalog; |
75 |
@synthesize ignoreSSLErrors; |
76 |
@synthesize pithos, accountNode, sharingAccountsNode; |
77 |
@synthesize tokensURL, storageURLPrefix, loginURL, userCatalogURL, publicURLPrefix; |
78 |
|
79 |
#pragma mark - |
80 |
#pragma mark Object Lifecycle |
81 |
|
82 |
+ (id)pithosAccount { |
83 |
PithosAccount *pithosAccount = [[self alloc] init]; |
84 |
pithosAccount.uniqueName = [NSString stringWithFormat:@"pithosAccount-%f", [NSDate timeIntervalSinceReferenceDate]]; |
85 |
pithosAccount.clientVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; |
86 |
pithosAccount.syncSkipHidden = YES; |
87 |
pithosAccount.authURLString = defaultAuthURLString; |
88 |
return pithosAccount; |
89 |
} |
90 |
|
91 |
- (NSString *)description { |
92 |
return [NSString stringWithFormat:@"uniqueName: %@, active: %d, name: %@, clientVersion: %@, syncActive: %d, syncDirectoryPath: %@, syncAccountsDictionary: %@, syncSkipHidden: %d, syncLastCompleted: %@, authURLString: %@, pithosObjectStoreURLString:%@ , astakosAccountURLString: %@, astakosWebloginURLString: %@, manual: %d, authToken: %@, authUser: %@", |
93 |
uniqueName, active, name, clientVersion, syncActive, syncDirectoryPath, syncAccountsDictionary, syncSkipHidden, syncLastCompleted, authURLString, pithosObjectStoreURLString, astakosAccountURLString, astakosWebloginURLString, manual, authToken, authUser]; |
94 |
} |
95 |
|
96 |
#pragma mark - |
97 |
#pragma mark Properties |
98 |
|
99 |
- (NSString *)name { |
100 |
if (![name length]) { |
101 |
NSDictionary *pithosAccountsDictionary = [(pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate] pithosAccountsDictionary]; |
102 |
NSString *namePrefix = @"okeanos"; |
103 |
NSUInteger nameSuffix = 1; |
104 |
name = @"okeanos"; |
105 |
NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; |
106 |
NSFileManager *fileManager = [NSFileManager defaultManager]; |
107 |
while ([pithosAccountsDictionary objectForKey:name] || |
108 |
[fileManager fileExistsAtPath:[documentsDirectoryPath stringByAppendingPathComponent:name]]) { |
109 |
name = [NSString stringWithFormat:@"%@%ld", namePrefix, ++nameSuffix]; |
110 |
} |
111 |
} |
112 |
return name; |
113 |
} |
114 |
|
115 |
- (void)setName:(NSString *)aName { |
116 |
NSMutableDictionary *pithosAccountsDictionary = [(pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate] pithosAccountsDictionary]; |
117 |
if (![self.name isEqualToString:aName] && [aName length] && ![pithosAccountsDictionary objectForKey:aName]) { |
118 |
[pithosAccountsDictionary setObject:self forKey:aName]; |
119 |
[pithosAccountsDictionary removeObjectForKey:name]; |
120 |
name = aName; |
121 |
} |
122 |
} |
123 |
|
124 |
- (BOOL)syncActive { |
125 |
if (active) |
126 |
return syncActive; |
127 |
else |
128 |
return NO; |
129 |
} |
130 |
|
131 |
- (void)setSyncActive:(BOOL)aSyncActive { |
132 |
syncActive = aSyncActive; |
133 |
if (syncDaemon && !self.syncActive) |
134 |
[syncDaemon resetDaemon]; |
135 |
} |
136 |
|
137 |
- (NSString *)syncDirectoryPath { |
138 |
if (![syncDirectoryPath length]) { |
139 |
syncDirectoryPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] |
140 |
stringByAppendingPathComponent:self.name]; |
141 |
} |
142 |
return syncDirectoryPath; |
143 |
} |
144 |
|
145 |
- (void)setSyncDirectoryPath:(NSString *)aSyncDirectoryPath { |
146 |
if (![self.syncDirectoryPath isEqualToString:aSyncDirectoryPath] && [aSyncDirectoryPath length]) { |
147 |
BOOL isDirectory; |
148 |
if (![[NSFileManager defaultManager] fileExistsAtPath:aSyncDirectoryPath isDirectory:&isDirectory] || isDirectory) { |
149 |
syncDirectoryPath = aSyncDirectoryPath; |
150 |
} else { |
151 |
return; |
152 |
} |
153 |
|
154 |
@synchronized(self) { |
155 |
resetSyncDaemonLocalState = YES; |
156 |
syncLastCompleted = nil; |
157 |
} |
158 |
} |
159 |
} |
160 |
|
161 |
- (NSMutableDictionary *)syncAccountsDictionary { |
162 |
if (!syncAccountsDictionary) { |
163 |
syncAccountsDictionary = [NSMutableDictionary dictionaryWithObject:[NSMutableDictionary dictionaryWithObject:[NSMutableSet set] |
164 |
forKey:@"pithos"] |
165 |
forKey:@""]; |
166 |
} |
167 |
return syncAccountsDictionary; |
168 |
} |
169 |
|
170 |
- (void)setSyncAccountsDictionary:(NSMutableDictionary *)aSyncAccountsDictionary { |
171 |
if (aSyncAccountsDictionary && ![self.syncAccountsDictionary isEqualToDictionary:aSyncAccountsDictionary]) { |
172 |
syncAccountsDictionary = [[NSMutableDictionary alloc] initWithCapacity:[aSyncAccountsDictionary count]]; |
173 |
for (NSString *accountName in aSyncAccountsDictionary) { |
174 |
NSDictionary *aSyncContainersDictionary = [aSyncAccountsDictionary objectForKey:accountName]; |
175 |
NSMutableDictionary *syncContainersDictionary = [NSMutableDictionary dictionary]; |
176 |
for (NSString *containerName in aSyncContainersDictionary) { |
177 |
if (![accountName isEqualToString:@""] || ![[containerName lowercaseString] isEqualToString:@"shared with me"]) |
178 |
[syncContainersDictionary setObject:[NSMutableSet setWithSet:[aSyncContainersDictionary objectForKey:containerName]] |
179 |
forKey:containerName]; |
180 |
} |
181 |
if ([syncContainersDictionary count]) |
182 |
[syncAccountsDictionary setObject:syncContainersDictionary forKey:accountName]; |
183 |
} |
184 |
|
185 |
@synchronized(self) { |
186 |
resetSyncDaemonLocalState = YES; |
187 |
syncLastCompleted = nil; |
188 |
} |
189 |
} |
190 |
} |
191 |
|
192 |
- (NSDate *)syncLastCompleted { |
193 |
if (self.syncDaemon.lastCompletedSync && ![self.syncDaemon.lastCompletedSync isEqualToDate:syncLastCompleted]) { |
194 |
syncLastCompleted = [self.syncDaemon.lastCompletedSync copy]; |
195 |
} |
196 |
return syncLastCompleted; |
197 |
} |
198 |
|
199 |
- (PithosSyncDaemon *)syncDaemon { |
200 |
@synchronized(self) { |
201 |
if (self.syncActive && !syncDaemon) |
202 |
syncDaemon = [[PithosSyncDaemon alloc] initWithDirectoryPath:self.syncDirectoryPath |
203 |
pithosAccount:self |
204 |
accountsDictionary:self.syncAccountsDictionary |
205 |
skipHidden:self.syncSkipHidden |
206 |
resetLocalState:resetSyncDaemonLocalState]; |
207 |
resetSyncDaemonLocalState = NO; |
208 |
} |
209 |
return syncDaemon; |
210 |
} |
211 |
|
212 |
- (void)setAuthURLString:(NSString *)anAuthURLString { |
213 |
NSString *tmpURLString = [anAuthURLString stringByRemovingTrailingSlashes]; |
214 |
if (![authURLString isEqualToString:tmpURLString]) { |
215 |
authURLString = tmpURLString; |
216 |
|
217 |
@synchronized(self) { |
218 |
updatePithos = YES; |
219 |
resetSyncDaemonLocalState = YES; |
220 |
syncLastCompleted = nil; |
221 |
} |
222 |
} |
223 |
} |
224 |
|
225 |
- (void)setPithosObjectStoreURLString:(NSString *)aPithosObjectStoreURLString { |
226 |
NSString *tmpURLString = [aPithosObjectStoreURLString stringByRemovingTrailingSlashes]; |
227 |
if (![pithosObjectStoreURLString isEqualToString:tmpURLString]) { |
228 |
pithosObjectStoreURLString = tmpURLString; |
229 |
|
230 |
@synchronized(self) { |
231 |
updatePithos = YES; |
232 |
} |
233 |
} |
234 |
} |
235 |
|
236 |
- (void)setAstakosAccountURLString:(NSString *)anAstakosAccountURLString { |
237 |
NSString *tmpURLString = [anAstakosAccountURLString stringByRemovingTrailingSlashes]; |
238 |
if (![astakosAccountURLString isEqualToString:tmpURLString]) { |
239 |
astakosAccountURLString = tmpURLString; |
240 |
|
241 |
@synchronized(self) { |
242 |
updatePithos = YES; |
243 |
} |
244 |
} |
245 |
} |
246 |
|
247 |
- (void)setAstakosWebloginURLString:(NSString *)anAstakosWebloginURLString { |
248 |
NSString *tmpURLString = [anAstakosWebloginURLString stringByRemovingTrailingSlashes]; |
249 |
if (![astakosWebloginURLString isEqualToString:tmpURLString]) { |
250 |
astakosWebloginURLString = tmpURLString; |
251 |
} |
252 |
} |
253 |
|
254 |
- (void)setAuthToken:(NSString *)anAuthToken { |
255 |
if (anAuthToken.length && ![anAuthToken isEqualToString:authToken]) { |
256 |
authToken = anAuthToken; |
257 |
|
258 |
@synchronized(self) { |
259 |
updatePithos = YES; |
260 |
} |
261 |
} |
262 |
} |
263 |
|
264 |
- (void)setAuthUser:(NSString *)anAuthUser { |
265 |
if (anAuthUser.length && ![anAuthUser isEqualToString:authUser]) { |
266 |
authUser = anAuthUser; |
267 |
|
268 |
@synchronized(self) { |
269 |
updatePithos = YES; |
270 |
resetSyncDaemonLocalState = YES; |
271 |
syncLastCompleted = nil; |
272 |
|
273 |
} |
274 |
} |
275 |
} |
276 |
|
277 |
- (void)setIgnoreSSLErrors:(BOOL)anIgnoreSSLErrors { |
278 |
if (anIgnoreSSLErrors != ignoreSSLErrors) { |
279 |
ignoreSSLErrors = anIgnoreSSLErrors; |
280 |
|
281 |
@synchronized(self) { |
282 |
updatePithos = YES; |
283 |
} |
284 |
} |
285 |
} |
286 |
|
287 |
- (NSMutableDictionary *)userCatalog { |
288 |
if (!userCatalog) { |
289 |
userCatalog = [NSMutableDictionary dictionary]; |
290 |
} |
291 |
return userCatalog; |
292 |
} |
293 |
|
294 |
- (ASIPithos *)pithos { |
295 |
@synchronized(self) { |
296 |
if (!pithos || updatePithos) { |
297 |
pithos = [ASIPithos pithos]; |
298 |
pithos.authToken = authToken; |
299 |
pithos.authUser = authUser; |
300 |
|
301 |
pithos.ignoreSSLErrors = ignoreSSLErrors; |
302 |
|
303 |
pithos.tokensURL = self.tokensURL; |
304 |
pithos.storageURLPrefix = self.storageURLPrefix; |
305 |
pithos.userCatalogURL = self.userCatalogURL; |
306 |
pithos.publicURLPrefix = self.publicURLPrefix; |
307 |
updatePithos = NO; |
308 |
} |
309 |
} |
310 |
return pithos; |
311 |
} |
312 |
|
313 |
- (PithosAccountNode *)accountNode { |
314 |
if (!accountNode) { |
315 |
accountNode = [[PithosAccountNode alloc] initWithPithosAccountManager:self andPithos:self.pithos]; |
316 |
accountNode.childrenUpdatedNotificationName = nil; |
317 |
accountNode.inheritChildrenUpdatedNotificationName = YES; |
318 |
} |
319 |
return accountNode; |
320 |
} |
321 |
|
322 |
- (PithosSharingAccountsNode *)sharingAccountsNode { |
323 |
if (!sharingAccountsNode) { |
324 |
sharingAccountsNode = [[PithosSharingAccountsNode alloc] initWithPithosAccountManager:self andPithos:self.pithos]; |
325 |
sharingAccountsNode.childrenUpdatedNotificationName = nil; |
326 |
sharingAccountsNode.inheritChildrenUpdatedNotificationName = YES; |
327 |
} |
328 |
return sharingAccountsNode; |
329 |
} |
330 |
|
331 |
- (NSString *)tokensURL { |
332 |
return [authURLString stringByAppendingString:@"/tokens"]; |
333 |
} |
334 |
|
335 |
- (NSString *)storageURLPrefix { |
336 |
return [pithosObjectStoreURLString copy]; |
337 |
} |
338 |
|
339 |
- (NSString *)loginURL { |
340 |
return [astakosWebloginURLString stringByAppendingString:@"/login"]; |
341 |
} |
342 |
|
343 |
- (NSString *)publicURLPrefix { |
344 |
return [pithosObjectStoreURLString copy]; |
345 |
} |
346 |
|
347 |
- (NSString *)userCatalogURL { |
348 |
return [astakosAccountURLString stringByAppendingString:@"/user_catalogs"]; |
349 |
} |
350 |
|
351 |
#pragma mark - |
352 |
#pragma mark Actions |
353 |
|
354 |
- (void)updateWithAuthURLString:(NSString *)anAuthURLString |
355 |
pithosObjectStoreURLString:(NSString *)aPithosObjectStoreURLString |
356 |
astakosAccountURLString:(NSString *)anAstakosAccountURLString |
357 |
astakosWebloginURLString:(NSString *)anAstakosWebloginURLString |
358 |
manual:(BOOL)aManual |
359 |
authToken:(NSString *)anAuthToken |
360 |
authUser:(NSString *)anAuthUser |
361 |
ignoreSSLErrors:(BOOL)anIgnoreSSLErrors { |
362 |
self.authURLString = anAuthURLString; |
363 |
self.pithosObjectStoreURLString = aPithosObjectStoreURLString; |
364 |
self.astakosAccountURLString = anAstakosAccountURLString; |
365 |
self.astakosWebloginURLString = anAstakosWebloginURLString; |
366 |
self.manual = aManual; |
367 |
self.authToken = anAuthToken; |
368 |
self.authUser = anAuthUser; |
369 |
self.ignoreSSLErrors = anIgnoreSSLErrors; |
370 |
DLog(@"Account updated: %@", self); |
371 |
if (!authToken.length || !authUser.length) { |
372 |
self.active = NO; |
373 |
self.syncActive = NO; |
374 |
} else { |
375 |
[self updateUserCatalogForDisplaynames:nil UUIDs:[NSArray arrayWithObject:authUser]]; |
376 |
|
377 |
self.active = YES; |
378 |
if (syncDaemon) { |
379 |
self.syncDaemon.pithos = self.pithos; |
380 |
if (self.syncActive) |
381 |
[self.syncDaemon startDaemon]; |
382 |
} |
383 |
if (accountNode) |
384 |
self.accountNode.pithos = self.pithos; |
385 |
if (sharingAccountsNode) |
386 |
self.sharingAccountsNode.pithos = self.pithos; |
387 |
if (accountNode) { |
388 |
if (self.accountNode.children) { |
389 |
} |
390 |
[self.accountNode refreshInfo]; |
391 |
} |
392 |
if (sharingAccountsNode && self.sharingAccountsNode.children) { |
393 |
} |
394 |
} |
395 |
} |
396 |
|
397 |
- (void)updateSyncWithSyncActive:(BOOL)aSyncActive |
398 |
syncDirectoryPath:(NSString *)aSyncDirectoryPath |
399 |
syncAccountsDictionary:(NSMutableDictionary *)aSyncAccountsDictionary |
400 |
syncSkipHidden:(BOOL)aSyncSkipHidden { |
401 |
self.syncAccountsDictionary = aSyncAccountsDictionary; |
402 |
self.syncDirectoryPath = aSyncDirectoryPath; |
403 |
self.syncSkipHidden = aSyncSkipHidden; |
404 |
self.syncActive = aSyncActive; |
405 |
if (syncDaemon) { |
406 |
self.syncDaemon.accountsDictionary = self.syncAccountsDictionary; |
407 |
self.syncDaemon.directoryPath = self.syncDirectoryPath; |
408 |
self.syncDaemon.skipHidden = self.syncSkipHidden; |
409 |
if (self.syncActive) |
410 |
[self.syncDaemon startDaemon]; |
411 |
} |
412 |
} |
413 |
|
414 |
- (NSMutableDictionary *)servicesFromServiceCatalogRequest:(ASIPithosRequest *)serviceCatalogRequest { |
415 |
NSMutableDictionary *services = [NSMutableDictionary dictionary]; |
416 |
if (serviceCatalogRequest.responseStatusCode == 200) { |
417 |
BOOL pithosObjectStoreFound = NO; |
418 |
BOOL astakosAccountFound = NO; |
419 |
BOOL astakosWebloginFound = NO; |
420 |
NSArray *serviceCatalog = [serviceCatalogRequest serviceCatalog]; |
421 |
for (NSDictionary *service in serviceCatalog) { |
422 |
NSString *serviceName = [service objectForKey:@"name"]; |
423 |
if (!pithosObjectStoreFound && [serviceName isEqualToString:@"pithos_object-store"]) { |
424 |
[services setObject:[[[service objectForKey:@"endpoints"] objectAtIndex:0] objectForKey:@"publicURL"] |
425 |
forKey:@"PithosObjectStoreURLString"]; |
426 |
pithosObjectStoreFound = YES; |
427 |
} else if (!astakosAccountFound && [serviceName isEqualToString:@"astakos_account"]) { |
428 |
[services setObject:[[[service objectForKey:@"endpoints"] objectAtIndex:0] objectForKey:@"publicURL"] |
429 |
forKey:@"AstakosAccountURLString"]; |
430 |
astakosAccountFound = YES; |
431 |
} else if (!astakosWebloginFound && [serviceName isEqualToString:@"astakos_weblogin"]) { |
432 |
[services setObject:[[[service objectForKey:@"endpoints"] objectAtIndex:0] objectForKey:@"SNF:webloginURL"] |
433 |
forKey:@"AstakosWebloginURLString"]; |
434 |
astakosWebloginFound = YES; |
435 |
} |
436 |
if (pithosObjectStoreFound && astakosAccountFound && astakosWebloginFound) |
437 |
break; |
438 |
} |
439 |
} |
440 |
return services; |
441 |
} |
442 |
|
443 |
- (void)updateServicesFromServiceCatalogRequest:(ASIPithosRequest *)serviceCatalogRequest { |
444 |
if (serviceCatalogRequest.responseStatusCode == 200) { |
445 |
NSMutableDictionary *services = [self servicesFromServiceCatalogRequest:serviceCatalogRequest]; |
446 |
self.pithosObjectStoreURLString = [services objectForKey:@"PithosObjectStoreURLString"]; |
447 |
self.astakosAccountURLString = [services objectForKey:@"AstakosAccountURLString"]; |
448 |
self.astakosWebloginURLString = [services objectForKey:@"AstakosWebloginURLString"]; |
449 |
self.manual = NO; |
450 |
|
451 |
if (authToken.length) { |
452 |
NSDictionary *token = [serviceCatalogRequest token]; |
453 |
self.authToken = [token objectForKey:@"id"]; |
454 |
self.authUser = [[token objectForKey:@"tenant"] objectForKey:@"id"]; |
455 |
} |
456 |
} else if (serviceCatalogRequest.responseStatusCode == 404) { |
457 |
self.pithosObjectStoreURLString = [[[NSURL URLWithString:authURLString] URLByAppendingPathComponent:@"v1"] description]; |
458 |
self.astakosAccountURLString = [self.authURLString copy]; |
459 |
self.astakosWebloginURLString = [self.authURLString copy]; |
460 |
self.manual = YES; |
461 |
} |
462 |
} |
463 |
|
464 |
- (ASIPithosRequest *)updateUserCatalogForDisplaynames:(NSArray *)displaynames UUIDs:(NSArray *)UUIDs { |
465 |
ASIPithosRequest *userCatalogRequest = [ASIPithosRequest userCatalogRequestWithPithos:self.pithos |
466 |
displaynames:displaynames |
467 |
UUIDs:UUIDs]; |
468 |
[PithosUtilities startAndWaitForRequest:userCatalogRequest]; |
469 |
if (userCatalogRequest.error || ((userCatalogRequest.responseStatusCode != 200) && (userCatalogRequest.responseStatusCode != 404))) { |
470 |
// Don't show alert on 404, since it can be a pre-UUID server. |
471 |
[PithosUtilities httpRequestErrorAlertWithRequest:userCatalogRequest]; |
472 |
} else if (userCatalogRequest.responseStatusCode == 200) { |
473 |
NSDictionary *catalogs = [userCatalogRequest catalogs]; |
474 |
NSDictionary *displaynameCatalog = [catalogs objectForKey:@"displayname_catalog"]; |
475 |
for (NSString *displayname in displaynameCatalog) { |
476 |
[self.userCatalog setObject:displayname forKey:[displaynameCatalog objectForKey:displayname]]; |
477 |
} |
478 |
if (UUIDs) { |
479 |
NSDictionary *UUIDCatalog = [catalogs objectForKey:@"uuid_catalog"]; |
480 |
for (NSString *UUID in UUIDs) { |
481 |
NSString *displayname = [UUIDCatalog objectForKey:UUID]; |
482 |
if (displayname) { |
483 |
[self.userCatalog setObject:displayname forKey:UUID]; |
484 |
} else { |
485 |
[self.userCatalog removeObjectForKey:UUID]; |
486 |
} |
487 |
} |
488 |
} |
489 |
} |
490 |
return userCatalogRequest; |
491 |
} |
492 |
|
493 |
- (NSString *)displaynameForUUID:(NSString *)UUID safe:(BOOL)safe { |
494 |
NSString *displayName = [userCatalog objectForKey:UUID]; |
495 |
if (safe && !displayName) { |
496 |
return UUID; |
497 |
} else { |
498 |
return displayName; |
499 |
} |
500 |
} |
501 |
|
502 |
- (NSString *)displaynameForUUID:(NSString *)UUID { |
503 |
return [self displaynameForUUID:UUID safe:NO]; |
504 |
} |
505 |
|
506 |
#pragma mark - |
507 |
#pragma mark NSCoding |
508 |
|
509 |
- (id)initWithCoder:(NSCoder *)decoder { |
510 |
if ((self = [super init])) { |
511 |
self.uniqueName = [decoder decodeObjectForKey:@"uniqueName"]; |
512 |
self.active = [decoder decodeBoolForKey:@"active"]; |
513 |
name = [decoder decodeObjectForKey:@"name"]; |
514 |
self.clientVersion = [decoder decodeObjectForKey:@"clientVersion"]; |
515 |
|
516 |
self.syncActive = [decoder decodeBoolForKey:@"syncActive"]; |
517 |
self.syncDirectoryPath = [decoder decodeObjectForKey:@"syncDirectoryPath"]; |
518 |
self.syncAccountsDictionary = [decoder decodeObjectForKey:@"syncAccountsDictionary"]; |
519 |
self.syncSkipHidden = [decoder decodeBoolForKey:@"syncSkipHidden"]; |
520 |
self.syncLastCompleted = [decoder decodeObjectForKey:@"syncLastCompleted"]; |
521 |
|
522 |
self.authURLString = [decoder decodeObjectForKey:@"authURLString"]; |
523 |
self.pithosObjectStoreURLString = [decoder decodeObjectForKey:@"pithosObjectStoreURLString"]; |
524 |
self.astakosAccountURLString = [decoder decodeObjectForKey:@"astakosAccountURLString"]; |
525 |
self.astakosWebloginURLString = [decoder decodeObjectForKey:@"astakosWebloginURLString"]; |
526 |
self.manual = [decoder decodeBoolForKey:@"manual"]; |
527 |
|
528 |
// Support for older versions. |
529 |
if (!authURLString && !pithosObjectStoreURLString && !astakosAccountURLString && !astakosWebloginURLString) { |
530 |
NSString *tmpURLString = [decoder decodeObjectForKey:@"serverURL"]; |
531 |
if (!tmpURLString || |
532 |
[[[NSURL URLWithString:tmpURLString] URLByAppendingPathComponent:@""] isEqual:[[NSURL URLWithString:defaultManualURLString] URLByAppendingPathComponent:@""]]) { |
533 |
self.authURLString = defaultAuthURLString; |
534 |
self.manual = NO; |
535 |
} else { |
536 |
self.pithosObjectStoreURLString = [tmpURLString stringByAppendingString:@"/v1"]; |
537 |
self.astakosAccountURLString = tmpURLString; |
538 |
self.astakosWebloginURLString = tmpURLString; |
539 |
self.manual = YES; |
540 |
} |
541 |
} |
542 |
|
543 |
self.authToken = [decoder decodeObjectForKey:@"authToken"]; |
544 |
self.authUser = [decoder decodeObjectForKey:@"authUser"]; |
545 |
self.userCatalog = [decoder decodeObjectForKey:@"userCatalog"]; |
546 |
|
547 |
if (![authUser length] || ![authToken length]) |
548 |
self.active = NO; |
549 |
|
550 |
NSString *currentVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; |
551 |
if (!clientVersion || ![clientVersion isEqualToString:currentVersion]) { |
552 |
resetSyncDaemonLocalState = YES; |
553 |
self.clientVersion = currentVersion; |
554 |
} else { |
555 |
resetSyncDaemonLocalState = NO; |
556 |
} |
557 |
} |
558 |
return self; |
559 |
} |
560 |
|
561 |
- (void)encodeWithCoder:(NSCoder *)encoder { |
562 |
[encoder encodeObject:uniqueName forKey:@"uniqueName"]; |
563 |
[encoder encodeBool:active forKey:@"active"]; |
564 |
[encoder encodeObject:name forKey:@"name"]; |
565 |
[encoder encodeObject:clientVersion forKey:@"clientVersion"]; |
566 |
|
567 |
[encoder encodeBool:syncActive forKey:@"syncActive"]; |
568 |
[encoder encodeObject:syncDirectoryPath forKey:@"syncDirectoryPath"]; |
569 |
[encoder encodeObject:syncAccountsDictionary forKey:@"syncAccountsDictionary"]; |
570 |
[encoder encodeBool:syncSkipHidden forKey:@"syncSkipHidden"]; |
571 |
[encoder encodeObject:self.syncLastCompleted forKey:@"syncLastCompleted"]; |
572 |
|
573 |
[encoder encodeObject:authURLString forKey:@"authURLString"]; |
574 |
[encoder encodeObject:pithosObjectStoreURLString forKey:@"pithosObjectStoreURLString"]; |
575 |
[encoder encodeObject:astakosAccountURLString forKey:@"astakosAccountURLString"]; |
576 |
[encoder encodeObject:astakosWebloginURLString forKey:@"astakosWebloginURLString"]; |
577 |
[encoder encodeBool:manual forKey:@"manual"]; |
578 |
|
579 |
[encoder encodeObject:authToken forKey:@"authToken"]; |
580 |
[encoder encodeObject:authUser forKey:@"authUser"]; |
581 |
[encoder encodeObject:userCatalog forKey:@"userCatalog"]; |
582 |
} |
583 |
|
584 |
@end |