Statistics
| Branch: | Tag: | Revision:

root / pithos-macos / PithosAccount.m @ cb6abe72

History | View | Annotate | Download (17.7 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 "PithosAccountNode.h"
42
#import "PithosSharingAccountsNode.h"
43
#import "pithos_macosAppDelegate.h"
44

    
45
@interface PithosAccount (Internal)
46
- (BOOL)urlIsValid:(NSString *)urlString;
47
@end
48

    
49
@implementation PithosAccount
50
@synthesize uniqueName, active, name;
51
@synthesize syncActive, syncDirectoryPath, syncAccountsDictionary, syncSkipHidden, syncLastCompleted, syncDaemon;
52
@synthesize serverURL, versionResource, loginResource, publicResource;
53
@synthesize authUser, authToken, storageURLPrefix, authURL, loginURLPrefix, publicURLPrefix;
54
@synthesize pithos, accountNode, sharingAccountsNode;
55

    
56
#pragma mark -
57
#pragma mark Object Lifecycle
58

    
59
+ (id)pithosAccount {
60
    PithosAccount *pithosAccount = [[self alloc] init];
61
    pithosAccount.uniqueName = [NSString stringWithFormat:@"pithosAccount-%f", [NSDate timeIntervalSinceReferenceDate]];
62
    pithosAccount.syncSkipHidden = YES;
63
    pithosAccount.versionResource = @"v1";
64
    pithosAccount.loginResource = @"login";
65
    return pithosAccount;
66
}
67

    
68

    
69
- (NSString *)description {
70
    return [NSString stringWithFormat:@"uniqueName: %@, active: %d, name: %@, syncActive: %d, syncDirectoryPath: %@, syncAccountsDictionary: %@, syncSkipHidden: %d, syncLastCompleted: %@, serverURL: %@, versionResource: %@, loginResource: %@, publicResource: %@, authUser: %@, authToken: %@, storageURLPrefix: %@, authURL: %@, loginURLPrefix: %@, publicURLPrefix: %@", 
71
            uniqueName, active, name, syncActive, syncDirectoryPath, syncAccountsDictionary, syncSkipHidden, syncLastCompleted, serverURL, versionResource, loginResource, publicResource, authUser, authToken, storageURLPrefix, authURL, loginURLPrefix, publicURLPrefix];
72
}
73

    
74
#pragma mark -
75
#pragma mark Internal
76

    
77
- (BOOL)urlIsValid:(NSString *)urlString {
78
    if (urlString) {
79
        NSURL *url = [NSURL URLWithString:urlString];
80
        if (url && url.scheme && url.host)
81
            return YES;
82
    }
83
    return NO;
84
}
85

    
86
#pragma mark -
87
#pragma mark Properties
88

    
89
- (NSString *)name {
90
    if (![name length]) {
91
        NSDictionary *pithosAccountsDictionary = [(pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate] pithosAccountsDictionary];
92
        NSString *namePrefix = @"okeanos";
93
        NSUInteger nameSuffix = 1;
94
        name = @"okeanos";
95
        NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
96
        NSFileManager *fileManager = [NSFileManager defaultManager];
97
        while ([pithosAccountsDictionary objectForKey:name] || 
98
               [fileManager fileExistsAtPath:[documentsDirectoryPath stringByAppendingPathComponent:name]]) {
99
            name = [NSString stringWithFormat:@"%@%ld", namePrefix, ++nameSuffix];
100
        }
101
    }
102
    return name;
103
}
104

    
105
- (void)setName:(NSString *)aName {
106
    NSMutableDictionary *pithosAccountsDictionary = [(pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate] pithosAccountsDictionary];
107
    if (![self.name isEqualToString:aName] && [aName length] && ![pithosAccountsDictionary objectForKey:aName]) {
108
        [pithosAccountsDictionary setObject:self forKey:aName];
109
        [pithosAccountsDictionary removeObjectForKey:name];
110
        name = aName;
111
    }
112
}
113

    
114
- (BOOL)syncActive {
115
    if (active)
116
        return syncActive;
117
    else
118
        return NO;
119
}
120

    
121
- (void)setSyncActive:(BOOL)aSyncActive {
122
    syncActive = aSyncActive;
123
    if (syncDaemon && !self.syncActive)
124
        [syncDaemon resetDaemon];
125
}
126

    
127
- (NSString *)syncDirectoryPath {
128
    if (![syncDirectoryPath length]) {
129
        syncDirectoryPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] 
130
                              stringByAppendingPathComponent:self.name];
131
    }
132
    return syncDirectoryPath;
133
}
134

    
135
- (void)setSyncDirectoryPath:(NSString *)aSyncDirectoryPath {
136
    if (![self.syncDirectoryPath isEqualToString:aSyncDirectoryPath] && [aSyncDirectoryPath length]) {
137
        BOOL isDirectory;
138
        if (![[NSFileManager defaultManager] fileExistsAtPath:aSyncDirectoryPath isDirectory:&isDirectory] || isDirectory) {
139
            syncDirectoryPath = aSyncDirectoryPath;
140
        } else {
141
            return;
142
        }
143

    
144
        @synchronized(self) {
145
            resetSyncDaemonLocalState = YES;
146
            syncLastCompleted = nil;
147
        }
148
    }
149
}
150

    
151
- (NSMutableDictionary *)syncAccountsDictionary {
152
    if (!syncAccountsDictionary) {
153
        syncAccountsDictionary = [NSMutableDictionary dictionaryWithObject:[NSMutableDictionary dictionaryWithObject:[NSMutableSet set] 
154
                                                                                                               forKey:@"pithos"] 
155
                                                                     forKey:@""];
156
    }        
157
    return syncAccountsDictionary;
158
}
159

    
160
- (void)setSyncAccountsDictionary:(NSMutableDictionary *)aSyncAccountsDictionary {
161
    if (aSyncAccountsDictionary && ![self.syncAccountsDictionary isEqualToDictionary:aSyncAccountsDictionary]) {
162
        syncAccountsDictionary = [[NSMutableDictionary alloc] initWithCapacity:[aSyncAccountsDictionary count]];
163
        for (NSString *accountName in aSyncAccountsDictionary) {
164
            NSDictionary *aSyncContainersDictionary = [aSyncAccountsDictionary objectForKey:accountName];
165
            NSMutableDictionary *syncContainersDictionary = [NSMutableDictionary dictionary];
166
            for (NSString *containerName in aSyncContainersDictionary) {
167
                if (![accountName isEqualToString:@""] || ![[containerName lowercaseString] isEqualToString:@"shared to me"])
168
                    [syncContainersDictionary setObject:[NSMutableSet setWithSet:[aSyncContainersDictionary objectForKey:containerName]] 
169
                                                 forKey:containerName];
170
            }
171
            if ([syncContainersDictionary count])
172
                [syncAccountsDictionary setObject:syncContainersDictionary forKey:accountName];
173
        }
174
        
175
        @synchronized(self) {
176
            resetSyncDaemonLocalState = YES;
177
            syncLastCompleted = nil;
178
        }
179
    }
180
}
181

    
182
- (NSDate *)syncLastCompleted {
183
    if (self.syncDaemon.lastCompletedSync && ![self.syncDaemon.lastCompletedSync isEqualToDate:syncLastCompleted]) {
184
        syncLastCompleted = [self.syncDaemon.lastCompletedSync copy];
185
    }
186
    return syncLastCompleted;
187
}
188

    
189
- (PithosSyncDaemon *)syncDaemon {
190
    @synchronized(self) {
191
        if (self.syncActive && !syncDaemon)
192
            syncDaemon = [[PithosSyncDaemon alloc] initWithDirectoryPath:self.syncDirectoryPath 
193
                                                           pithosAccount:self 
194
                                                      accountsDictionary:self.syncAccountsDictionary 
195
                                                              skipHidden:self.syncSkipHidden 
196
                                                         resetLocalState:resetSyncDaemonLocalState];
197
        resetSyncDaemonLocalState = NO;
198
    }
199
    return syncDaemon;
200
}
201

    
202
- (NSString *)serverURL {
203
    if (![self urlIsValid:serverURL]) {
204
        serverURL = @"https://pithos.okeanos.grnet.gr";
205
    }
206
    return serverURL;
207
}
208

    
209
- (void)setServerURL:(NSString *)aServerURL {
210
    if (![self.serverURL isEqualToString:aServerURL] && [self urlIsValid:aServerURL]) {
211
        serverURL = aServerURL;
212
        storageURLPrefix = nil;
213
        authURL = nil;
214
        publicURLPrefix = nil;
215
        loginURLPrefix = nil;
216

    
217
        @synchronized(self) {
218
            updatePithos = YES;
219
            resetSyncDaemonLocalState = YES;
220
            syncLastCompleted = nil;
221
        }
222
    }
223
}
224

    
225
- (void)setAuthUser:(NSString *)anAuthUser {
226
    if ([anAuthUser length] && ![anAuthUser isEqualToString:authUser]) {
227
        authUser = anAuthUser;
228
        
229
        @synchronized(self) {
230
            updatePithos = YES;
231
            resetSyncDaemonLocalState = YES;
232
            syncLastCompleted = nil;
233

    
234
        }
235
    }
236
}
237

    
238
- (void)setAuthToken:(NSString *)anAuthToken {
239
    if ([anAuthToken length] && ![anAuthToken isEqualToString:authToken]) {
240
        authToken = anAuthToken;
241
        
242
        @synchronized(self) {
243
            updatePithos = YES;
244
        }
245
    }
246
}
247

    
248
- (NSString *)storageURLPrefix {
249
    if (![self urlIsValid:storageURLPrefix]) {
250
        if (versionResource)
251
            storageURLPrefix = [self.serverURL stringByAppendingFormat:@"/%@", versionResource];
252
        else
253
            storageURLPrefix = [self.serverURL copy];
254
    }
255
    return storageURLPrefix;
256
}
257

    
258
- (void)setStorageURLPrefix:(NSString *)aStorageURLPrefix {
259
    if (![self.storageURLPrefix isEqualToString:aStorageURLPrefix] && [self urlIsValid:aStorageURLPrefix]) {
260
        storageURLPrefix = aStorageURLPrefix;
261
    }
262
}
263

    
264
- (NSString *)authURL {
265
    if (![self urlIsValid:authURL]) {
266
        if (versionResource)
267
            authURL = [self.serverURL stringByAppendingFormat:@"/%@", versionResource];
268
        else
269
            authURL = [self.serverURL copy];
270
    }
271
    return authURL;
272
}
273

    
274
- (void)setAuthURL:(NSString *)anAuthURL {
275
    if (![self.authURL isEqualToString:anAuthURL] && [self urlIsValid:anAuthURL]) {
276
        authURL = anAuthURL;
277
    }
278
}
279

    
280
- (NSString *)publicURLPrefix {
281
    if (![self urlIsValid:publicURLPrefix]) {
282
        if (publicResource)
283
            publicURLPrefix = [self.serverURL stringByAppendingFormat:@"/%@", publicResource];
284
        else
285
            publicURLPrefix = [self.serverURL copy];
286
    }
287
    return publicURLPrefix;
288
}
289

    
290
- (void)setPublicURLPrefix:(NSString *)aPublicURLPrefix {
291
    if (![self.publicURLPrefix isEqualToString:aPublicURLPrefix] && [self urlIsValid:aPublicURLPrefix]) {
292
        publicURLPrefix = aPublicURLPrefix;
293
    }
294
}
295

    
296
- (NSString *)loginURLPrefix {
297
    if (![self urlIsValid:loginURLPrefix]) {
298
        if (loginResource)
299
            loginURLPrefix = [self.serverURL stringByAppendingFormat:@"/%@", loginResource];
300
        else
301
            loginURLPrefix = [self.serverURL copy];
302
    }
303
    return loginURLPrefix;
304
}
305

    
306
- (void)setLoginURLPrefix:(NSString *)aLoginURLPrefix {
307
    if (![self.loginURLPrefix isEqualToString:aLoginURLPrefix] && [self urlIsValid:aLoginURLPrefix]) {
308
        loginURLPrefix = aLoginURLPrefix;
309
    }
310
}
311

    
312
- (ASIPithos *)pithos {
313
    @synchronized(self) {
314
        if (!pithos || updatePithos) {
315
            pithos = [ASIPithos pithos];
316
            pithos.authUser = authUser;
317
            pithos.authToken = authToken;
318
            pithos.storageURLPrefix = self.storageURLPrefix;
319
            pithos.authURL = self.authURL;
320
            pithos.publicURLPrefix = self.publicURLPrefix;
321
            updatePithos = NO;
322
        }
323
    }
324
    return pithos;
325
}
326

    
327
- (PithosAccountNode *)accountNode {
328
    if (!accountNode) {
329
        accountNode = [[PithosAccountNode alloc] initWithPithos:self.pithos];
330
        accountNode.childrenUpdatedNotificationName = nil;
331
        accountNode.inheritChildrenUpdatedNotificationName = YES;
332
    }
333
    return accountNode;
334
}
335

    
336
- (PithosSharingAccountsNode *)sharingAccountsNode {
337
    if (!sharingAccountsNode) {
338
        sharingAccountsNode = [[PithosSharingAccountsNode alloc] initWithPithos:self.pithos];
339
        sharingAccountsNode.childrenUpdatedNotificationName = nil;
340
        sharingAccountsNode.inheritChildrenUpdatedNotificationName = YES;
341
    }
342
    return sharingAccountsNode;
343
}
344

    
345
#pragma mark -
346
#pragma mark Actions
347

    
348
- (void)authenticateWithServerURL:(NSString *)aServerURL authUser:(NSString *)anAuthUser authToken:(NSString *)anAuthToken {
349
    self.serverURL = aServerURL;
350
    self.authUser = anAuthUser;
351
    self.authToken = anAuthToken;
352
    DLog(@"Account: %@\nauthentication", self);
353
    if (![authUser length] || ![authToken length]) {
354
        self.active = NO;
355
        self.syncActive = NO;
356
        // XXX Show preferences with self as the selected account?
357
    } else  {
358
        self.active = YES;
359
        if (syncDaemon) {
360
            self.syncDaemon.pithos = self.pithos;
361
            if (self.syncActive)
362
                [self.syncDaemon startDaemon];
363
        }
364
        if (accountNode)
365
            self.accountNode.pithos = self.pithos;
366
        if (sharingAccountsNode)
367
            self.sharingAccountsNode.pithos = self.pithos;
368
        if (accountNode) {
369
            if (self.accountNode.children) {
370
            }
371
            [self.accountNode refreshInfo];
372
        }
373
        if (sharingAccountsNode && self.sharingAccountsNode.children) {
374
        }
375
    }
376
}
377

    
378
- (void)loginWithServerURL:(NSString *)aServerURL {
379
    self.serverURL = aServerURL;
380
    NSProcessInfo *processInfo = [NSProcessInfo processInfo];
381
    NSString *loginURL = [NSString stringWithFormat:@"%@?next=pithos://%d/%@&force=", 
382
                          self.loginURLPrefix, [processInfo processIdentifier], self.name];
383
    DLog(@"Account: %@\nloginURL: %@", self, loginURL);
384
    [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:loginURL]];
385
}
386

    
387
- (void)updateSyncWithSyncActive:(BOOL)aSyncActive 
388
               syncDirectoryPath:(NSString *)aSyncDirectoryPath 
389
          syncAccountsDictionary:(NSMutableDictionary *)aSyncAccountsDictionary 
390
                  syncSkipHidden:(BOOL)aSyncSkipHidden {
391
    self.syncAccountsDictionary = aSyncAccountsDictionary;
392
    self.syncDirectoryPath = aSyncDirectoryPath;
393
    self.syncSkipHidden = aSyncSkipHidden;
394
    self.syncActive = aSyncActive;
395
    if (syncDaemon) {
396
        self.syncDaemon.accountsDictionary = self.syncAccountsDictionary;
397
        self.syncDaemon.directoryPath = self.syncDirectoryPath;
398
        self.syncDaemon.skipHidden = self.syncSkipHidden;
399
        if (self.syncActive)
400
            [self.syncDaemon startDaemon];
401
    }    
402
}
403

    
404
#pragma mark -
405
#pragma mark NSCoding
406

    
407
- (id)initWithCoder:(NSCoder *)decoder {
408
    if ((self = [super init])) {
409
        self.uniqueName = [decoder decodeObjectForKey:@"uniqueName"];
410
        self.active = [decoder decodeBoolForKey:@"active"];
411
        name = [decoder decodeObjectForKey:@"name"];
412

    
413
        self.syncActive = [decoder decodeBoolForKey:@"syncActive"];
414
        self.syncDirectoryPath = [decoder decodeObjectForKey:@"syncDirectoryPath"];
415
        self.syncAccountsDictionary = [decoder decodeObjectForKey:@"syncAccountsDictionary"];
416
        self.syncSkipHidden = [decoder decodeBoolForKey:@"syncSkipHidden"];
417
        self.syncLastCompleted = [decoder decodeObjectForKey:@"syncLastCompleted"];
418
        
419
        self.serverURL = [decoder decodeObjectForKey:@"serverURL"];
420
        self.versionResource = [decoder decodeObjectForKey:@"versionResource"];
421
        self.loginResource = [decoder decodeObjectForKey:@"loginResource"];
422
        self.publicResource = [decoder decodeObjectForKey:@"publicResource"];
423
        
424
        self.authUser = [decoder decodeObjectForKey:@"authUser"];
425
        self.authToken = [decoder decodeObjectForKey:@"authToken"];
426
        self.storageURLPrefix = [decoder decodeObjectForKey:@"storageURLPrefix"];
427
        self.authURL = [decoder decodeObjectForKey:@"authURL"];
428
        self.publicURLPrefix = [decoder decodeObjectForKey:@"publicURLPrefix"];
429
        self.loginURLPrefix = [decoder decodeObjectForKey:@"loginURLPrefix"];
430
        
431
        if (![authUser length] || ![authToken length] || ![self.storageURLPrefix length])
432
            self.active = NO;
433
        
434
        resetSyncDaemonLocalState = NO;
435
    }
436
    return self;
437
}
438

    
439
- (void)encodeWithCoder:(NSCoder *)encoder {
440
    [encoder encodeObject:uniqueName forKey:@"uniqueName"];
441
    [encoder encodeBool:active forKey:@"active"];
442
    [encoder encodeObject:name forKey:@"name"];
443
    
444
    [encoder encodeBool:syncActive forKey:@"syncActive"];
445
    [encoder encodeObject:syncDirectoryPath forKey:@"syncDirectoryPath"];
446
    [encoder encodeObject:syncAccountsDictionary forKey:@"syncAccountsDictionary"];
447
    [encoder encodeBool:syncSkipHidden forKey:@"syncSkipHidden"];
448
    [encoder encodeObject:self.syncLastCompleted forKey:@"syncLastCompleted"];
449

    
450
    [encoder encodeObject:serverURL forKey:@"serverURL"];
451
    [encoder encodeObject:versionResource forKey:@"versionResource"];
452
    [encoder encodeObject:publicResource forKey:@"publicResource"];
453
    [encoder encodeObject:loginResource forKey:@"loginResource"];
454
    
455
    [encoder encodeObject:authUser forKey:@"authUser"];
456
    [encoder encodeObject:authToken forKey:@"authToken"];
457
    [encoder encodeObject:storageURLPrefix forKey:@"storageURLPrefix"];
458
    [encoder encodeObject:authURL forKey:@"authURL"];
459
    [encoder encodeObject:publicURLPrefix forKey:@"publicURLPrefix"];
460
    [encoder encodeObject:loginURLPrefix forKey:@"loginURLPrefix"];
461
}
462

    
463
@end