From baaf13974a1e36994df4f904e11c674544d286d6 Mon Sep 17 00:00:00 2001 From: Miltiadis Vasilakis Date: Tue, 2 Jul 2013 18:18:24 +0300 Subject: [PATCH] Use service catalog Support tokens mechanism to retrieve service catalog, for account creation or change. Allow fallback for older server versions. Add option for ignoring SSL errors. Migrate providers from older versions. Improve preferences UI. Support full URL in X-Object-Public header. Other minor changes. --- pithos-apple-common | 2 +- pithos-macos.xcodeproj/project.pbxproj | 12 +- pithos-macos/PithosAccount.h | 74 +- pithos-macos/PithosAccount.m | 350 +-- pithos-macos/PithosAccountNode.m | 6 +- pithos-macos/PithosBrowserController.m | 7 +- pithos-macos/PithosObjectNode.m | 6 +- pithos-macos/PithosPreferencesController.h | 31 +- pithos-macos/PithosPreferencesController.m | 208 +- pithos-macos/PithosPreferencesController.xib | 3243 ++++++++++++++++---------- pithos-macos/PithosSharingAccountsNode.m | 4 +- pithos-macos/PithosSubdirNode.m | 8 +- pithos-macos/PithosSyncDaemon.m | 18 +- pithos-macos/PublicURLTransformer.m | 7 +- pithos-macos/pithos_macosAppDelegate.m | 59 +- 15 files changed, 2490 insertions(+), 1545 deletions(-) diff --git a/pithos-apple-common b/pithos-apple-common index ca7626d..8fb25a1 160000 --- a/pithos-apple-common +++ b/pithos-apple-common @@ -1 +1 @@ -Subproject commit ca7626d763435ba5416f009de1f9a55dd20eacde +Subproject commit 8fb25a1bf3c5e88def03d59bbae18dfbbc967567 diff --git a/pithos-macos.xcodeproj/project.pbxproj b/pithos-macos.xcodeproj/project.pbxproj index c8bbe7d..3f1f0c2 100644 --- a/pithos-macos.xcodeproj/project.pbxproj +++ b/pithos-macos.xcodeproj/project.pbxproj @@ -673,7 +673,7 @@ 610DD2E813E6BB2000ED982F /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0450; + LastUpgradeCheck = 0460; ORGANIZATIONNAME = koomasi; }; buildConfigurationList = 610DD2EB13E6BB2000ED982F /* Build configuration list for PBXProject "pithos-macos" */; @@ -830,6 +830,10 @@ isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = DEBUG; @@ -837,6 +841,7 @@ GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; @@ -848,10 +853,15 @@ isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.6; SDKROOT = macosx; diff --git a/pithos-macos/PithosAccount.h b/pithos-macos/PithosAccount.h index dea922f..2972271 100644 --- a/pithos-macos/PithosAccount.h +++ b/pithos-macos/PithosAccount.h @@ -54,31 +54,19 @@ BOOL syncSkipHidden; NSDate *syncLastCompleted; PithosSyncDaemon *syncDaemon; - - // Base for all necessary URLs, default "https://pithos.okeanos.grnet.gr" - NSString *serverURL; - // Appended to serverURL to get storageURLPrefix and authURL, default "v1" - // Can be overriden by setting directly storageURLPrefix and authURL - NSString *versionResource; - // Appended to serverURL to get loginURLPrefix, default "login" - // Can be overriden by setting directly loginURLPrefix - NSString *loginResource; - // Appended to serverURL to get publicURLPrefix, default nil - // Can be overriden by setting directly publicURLPrefix - NSString *publicResource; - // Appended to serverURL to get userCatalogURL, default "user_catalogs" - // Can be overriden by setting directly userCatalogURL - NSString *userCatalogResource; - - NSString *authUser; + + NSString *authURLString; + NSString *pithosObjectStoreURLString; + NSString *astakosAccountURLString; + NSString *astakosWebloginURLString; + BOOL manual; + NSString *authToken; - NSString *storageURLPrefix; - NSString *authURL; - NSString *publicURLPrefix; - NSString *loginURLPrefix; - NSString *userCatalogURL; + NSString *authUser; NSMutableDictionary *userCatalog; + BOOL ignoreSSLErrors; + ASIPithos *pithos; PithosAccountNode *accountNode; PithosSharingAccountsNode *sharingAccountsNode; @@ -99,35 +87,45 @@ @property (nonatomic, strong) NSDate *syncLastCompleted; @property (nonatomic, strong) PithosSyncDaemon *syncDaemon; -@property (nonatomic, strong) NSString *serverURL; -@property (nonatomic, strong) NSString *versionResource; -@property (nonatomic, strong) NSString *loginResource; -@property (strong) NSString *publicResource; -@property (nonatomic, strong) NSString *userCatalogResource; +@property (nonatomic, strong) NSString *authURLString; +@property (nonatomic, strong) NSString *pithosObjectStoreURLString; +@property (nonatomic, strong) NSString *astakosAccountURLString; +@property (nonatomic, strong) NSString *astakosWebloginURLString; +@property (nonatomic, assign) BOOL manual; -@property (nonatomic, strong) NSString *authUser; @property (nonatomic, strong) NSString *authToken; -@property (nonatomic, strong) NSString *storageURLPrefix; -@property (nonatomic, strong) NSString *authURL; -@property (nonatomic, strong) NSString *publicURLPrefix; -@property (nonatomic, strong) NSString *loginURLPrefix; -@property (nonatomic, strong) NSString *userCatalogURL; +@property (nonatomic, strong) NSString *authUser; @property (nonatomic, strong) NSMutableDictionary *userCatalog; +@property (nonatomic, assign) BOOL ignoreSSLErrors; + @property (strong, readonly) ASIPithos *pithos; @property (readonly) PithosAccountNode *accountNode; @property (readonly) PithosSharingAccountsNode *sharingAccountsNode; +@property (nonatomic, readonly) NSString *tokensURL; +@property (nonatomic, readonly) NSString *storageURLPrefix; +@property (nonatomic, readonly) NSString *loginURL; +@property (nonatomic, readonly) NSString *userCatalogURL; +@property (nonatomic, readonly) NSString *publicURLPrefix; + + (id)pithosAccount; -- (BOOL)urlIsValid:(NSString *)urlString; -- (void)authenticateWithServerURL:(NSString *)aServerURL authUser:(NSString *)anAuthUser authToken:(NSString *)anAuthToken; -- (void)loginWithServerURL:(NSString *)aServerURL; -- (void)updateSyncWithSyncActive:(BOOL)aSyncActive +- (void)updateWithAuthURLString:(NSString *)anAuthURLString + pithosObjectStoreURLString:(NSString *)aPithosObjectStoreURLString + astakosAccountURLString:(NSString *)anAstakosAccountURLString + astakosWebloginURLString:(NSString *)anAstakosWebloginURLString + manual:(BOOL)aManual + authToken:(NSString *)anAuthToken + authUser:(NSString *)anAuthUser + ignoreSSLErrors:(BOOL)anIgnoreSSLErrors; +- (void)updateSyncWithSyncActive:(BOOL)aSyncActive syncDirectoryPath:(NSString *)aSyncDirectoryPath syncAccountsDictionary:(NSMutableDictionary *)aSyncAccountsDictionary syncSkipHidden:(BOOL)aSyncSkipHidden; -- (ASIPithosRequest *)updateUserCatalogForForDisplaynames:(NSArray *)displaynames UUIDs:(NSArray *)UUIDs; +- (NSMutableDictionary *)servicesFromServiceCatalogRequest:(ASIPithosRequest *)serviceCatalogRequest; +- (void)updateServicesFromServiceCatalogRequest:(ASIPithosRequest *)serviceCatalogRequest; +- (ASIPithosRequest *)updateUserCatalogForDisplaynames:(NSArray *)displaynames UUIDs:(NSArray *)UUIDs; - (NSString *)displaynameForUUID:(NSString *)UUID safe:(BOOL)safe; - (NSString *)displaynameForUUID:(NSString *)UUID; diff --git a/pithos-macos/PithosAccount.m b/pithos-macos/PithosAccount.m index 7a597bc..35348f9 100644 --- a/pithos-macos/PithosAccount.m +++ b/pithos-macos/PithosAccount.m @@ -44,16 +44,37 @@ #import "PithosUtilities.h" #import "pithos_macosAppDelegate.h" -@interface PithosAccount (Internal) -- (BOOL)urlIsValid:(NSString *)urlString; +static NSString *defaultAuthURLString = @"https://accounts.okeanos.grnet.gr/identity/v2.0"; +static NSString *defaultManualURLString = @"https://pithos.okeanos.grnet.gr"; + +@interface NSString(Additions) +- (BOOL)isValidURL; +- (NSString *)stringByRemovingTrailingSlashes; +@end + +@implementation NSString(Additions) +- (BOOL)isValidURL { + NSURL *URL = [NSURL URLWithString:self]; + return (URL && URL.scheme && URL.host); +} + +- (NSString *)stringByRemovingTrailingSlashes { + NSString *stringWithRemovedTrailingSlashes = [self copy]; + while ([stringWithRemovedTrailingSlashes hasSuffix:@"/"]) { + stringWithRemovedTrailingSlashes = [stringWithRemovedTrailingSlashes substringToIndex:(stringWithRemovedTrailingSlashes.length - 1)]; + } + return stringWithRemovedTrailingSlashes; +} @end @implementation PithosAccount @synthesize uniqueName, active, name, clientVersion; @synthesize syncActive, syncDirectoryPath, syncAccountsDictionary, syncSkipHidden, syncLastCompleted, syncDaemon; -@synthesize serverURL, versionResource, loginResource, publicResource, userCatalogResource; -@synthesize authUser, authToken, storageURLPrefix, authURL, loginURLPrefix, publicURLPrefix, userCatalogURL, userCatalog; +@synthesize authURLString, pithosObjectStoreURLString, astakosAccountURLString, astakosWebloginURLString, manual; +@synthesize authToken, authUser, userCatalog; +@synthesize ignoreSSLErrors; @synthesize pithos, accountNode, sharingAccountsNode; +@synthesize tokensURL, storageURLPrefix, loginURL, userCatalogURL, publicURLPrefix; #pragma mark - #pragma mark Object Lifecycle @@ -63,25 +84,13 @@ pithosAccount.uniqueName = [NSString stringWithFormat:@"pithosAccount-%f", [NSDate timeIntervalSinceReferenceDate]]; pithosAccount.clientVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; pithosAccount.syncSkipHidden = YES; + pithosAccount.authURLString = defaultAuthURLString; return pithosAccount; } - - (NSString *)description { - return [NSString stringWithFormat:@"uniqueName: %@, active: %d, name: %@, clientVersion: %@, syncActive: %d, syncDirectoryPath: %@, syncAccountsDictionary: %@, syncSkipHidden: %d, syncLastCompleted: %@, serverURL: %@, versionResource: %@, loginResource: %@, publicResource: %@, userCatalogResource: %@, authUser: %@, authToken: %@, storageURLPrefix: %@, authURL: %@, loginURLPrefix: %@, publicURLPrefix: %@", - uniqueName, active, name, clientVersion, syncActive, syncDirectoryPath, syncAccountsDictionary, syncSkipHidden, syncLastCompleted, serverURL, versionResource, loginResource, publicResource, userCatalogResource, authUser, authToken, storageURLPrefix, authURL, loginURLPrefix, publicURLPrefix]; -} - -#pragma mark - -#pragma mark Internal - -- (BOOL)urlIsValid:(NSString *)urlString { - if (urlString) { - NSURL *url = [NSURL URLWithString:urlString]; - if (url && url.scheme && url.host) - return YES; - } - return NO; + return [NSString stringWithFormat:@"uniqueName: %@, active: %d, name: %@, clientVersion: %@, syncActive: %d, syncDirectoryPath: %@, syncAccountsDictionary: %@, syncSkipHidden: %d, syncLastCompleted: %@, authURLString: %@, pithosObjectStoreURLString:%@ , astakosAccountURLString: %@, astakosWebloginURLString: %@, manual: %d, authToken: %@, authUser: %@", + uniqueName, active, name, clientVersion, syncActive, syncDirectoryPath, syncAccountsDictionary, syncSkipHidden, syncLastCompleted, authURLString, pithosObjectStoreURLString, astakosAccountURLString, astakosWebloginURLString, manual, authToken, authUser]; } #pragma mark - @@ -200,53 +209,60 @@ return syncDaemon; } -- (NSString *)serverURL { - if (![self urlIsValid:serverURL]) { - serverURL = @"https://pithos.okeanos.grnet.gr"; +- (void)setAuthURLString:(NSString *)anAuthURLString { + NSString *tmpURLString = [anAuthURLString stringByRemovingTrailingSlashes]; + if (![authURLString isEqualToString:tmpURLString]) { + authURLString = tmpURLString; + + @synchronized(self) { + updatePithos = YES; + resetSyncDaemonLocalState = YES; + syncLastCompleted = nil; + } } - return serverURL; } -- (void)setServerURL:(NSString *)aServerURL { - if (![self.serverURL isEqualToString:aServerURL] && [self urlIsValid:aServerURL]) { - serverURL = aServerURL; - storageURLPrefix = nil; - authURL = nil; - publicURLPrefix = nil; - loginURLPrefix = nil; - userCatalogURL = nil; +- (void)setPithosObjectStoreURLString:(NSString *)aPithosObjectStoreURLString { + NSString *tmpURLString = [aPithosObjectStoreURLString stringByRemovingTrailingSlashes]; + if (![pithosObjectStoreURLString isEqualToString:tmpURLString]) { + pithosObjectStoreURLString = tmpURLString; @synchronized(self) { updatePithos = YES; - resetSyncDaemonLocalState = YES; - syncLastCompleted = nil; } } } -- (NSString *)versionResource { - if (!versionResource) { - versionResource = @"v1"; +- (void)setAstakosAccountURLString:(NSString *)anAstakosAccountURLString { + NSString *tmpURLString = [anAstakosAccountURLString stringByRemovingTrailingSlashes]; + if (![astakosAccountURLString isEqualToString:tmpURLString]) { + astakosAccountURLString = tmpURLString; + + @synchronized(self) { + updatePithos = YES; + } } - return versionResource; } -- (NSString *)loginResource { - if (!loginResource) { - loginResource = @"login"; +- (void)setAstakosWebloginURLString:(NSString *)anAstakosWebloginURLString { + NSString *tmpURLString = [anAstakosWebloginURLString stringByRemovingTrailingSlashes]; + if (![astakosWebloginURLString isEqualToString:tmpURLString]) { + astakosWebloginURLString = tmpURLString; } - return loginResource; } -- (NSString *)userCatalogResource { - if (!userCatalogResource) { - userCatalogResource = @"user_catalogs"; +- (void)setAuthToken:(NSString *)anAuthToken { + if (anAuthToken.length && ![anAuthToken isEqualToString:authToken]) { + authToken = anAuthToken; + + @synchronized(self) { + updatePithos = YES; + } } - return userCatalogResource; } - (void)setAuthUser:(NSString *)anAuthUser { - if ([anAuthUser length] && ![anAuthUser isEqualToString:authUser]) { + if (anAuthUser.length && ![anAuthUser isEqualToString:authUser]) { authUser = anAuthUser; @synchronized(self) { @@ -258,9 +274,9 @@ } } -- (void)setAuthToken:(NSString *)anAuthToken { - if ([anAuthToken length] && ![anAuthToken isEqualToString:authToken]) { - authToken = anAuthToken; +- (void)setIgnoreSSLErrors:(BOOL)anIgnoreSSLErrors { + if (anIgnoreSSLErrors != ignoreSSLErrors) { + ignoreSSLErrors = anIgnoreSSLErrors; @synchronized(self) { updatePithos = YES; @@ -268,74 +284,6 @@ } } -- (NSString *)storageURLPrefix { - if (![self urlIsValid:storageURLPrefix]) { - storageURLPrefix = [self.serverURL stringByAppendingFormat:@"/%@", self.versionResource]; - } - return storageURLPrefix; -} - -- (void)setStorageURLPrefix:(NSString *)aStorageURLPrefix { - if (![self.storageURLPrefix isEqualToString:aStorageURLPrefix] && [self urlIsValid:aStorageURLPrefix]) { - storageURLPrefix = aStorageURLPrefix; - } -} - -- (NSString *)authURL { - if (![self urlIsValid:authURL]) { - authURL = [self.serverURL stringByAppendingFormat:@"/%@", self.versionResource]; - } - return authURL; -} - -- (void)setAuthURL:(NSString *)anAuthURL { - if (![self.authURL isEqualToString:anAuthURL] && [self urlIsValid:anAuthURL]) { - authURL = anAuthURL; - } -} - -- (NSString *)publicURLPrefix { - if (![self urlIsValid:publicURLPrefix]) { - if (publicResource) - publicURLPrefix = [self.serverURL stringByAppendingFormat:@"/%@", publicResource]; - else - publicURLPrefix = [self.serverURL copy]; - } - return publicURLPrefix; -} - -- (void)setPublicURLPrefix:(NSString *)aPublicURLPrefix { - if (![self.publicURLPrefix isEqualToString:aPublicURLPrefix] && [self urlIsValid:aPublicURLPrefix]) { - publicURLPrefix = aPublicURLPrefix; - } -} - -- (NSString *)loginURLPrefix { - if (![self urlIsValid:loginURLPrefix]) { - loginURLPrefix = [self.serverURL stringByAppendingFormat:@"/%@", self.loginResource]; - } - return loginURLPrefix; -} - -- (void)setLoginURLPrefix:(NSString *)aLoginURLPrefix { - if (![self.loginURLPrefix isEqualToString:aLoginURLPrefix] && [self urlIsValid:aLoginURLPrefix]) { - loginURLPrefix = aLoginURLPrefix; - } -} - -- (NSString *)userCatalogURL { - if (![self urlIsValid:userCatalogURL]) { - userCatalogURL = [self.serverURL stringByAppendingFormat:@"/%@", self.userCatalogResource]; - } - return userCatalogURL; -} - -- (void)setUserCatalogURL:(NSString *)aUserCatalogURL { - if (![self.userCatalogURL isEqualToString:aUserCatalogURL] && [self urlIsValid:aUserCatalogURL]) { - userCatalogURL = aUserCatalogURL; - } -} - - (NSMutableDictionary *)userCatalog { if (!userCatalog) { userCatalog = [NSMutableDictionary dictionary]; @@ -347,12 +295,15 @@ @synchronized(self) { if (!pithos || updatePithos) { pithos = [ASIPithos pithos]; - pithos.authUser = authUser; pithos.authToken = authToken; + pithos.authUser = authUser; + + pithos.ignoreSSLErrors = ignoreSSLErrors; + + pithos.tokensURL = self.tokensURL; pithos.storageURLPrefix = self.storageURLPrefix; - pithos.authURL = self.authURL; - pithos.publicURLPrefix = self.publicURLPrefix; pithos.userCatalogURL = self.userCatalogURL; + pithos.publicURLPrefix = self.publicURLPrefix; updatePithos = NO; } } @@ -377,21 +328,52 @@ return sharingAccountsNode; } +- (NSString *)tokensURL { + return [authURLString stringByAppendingString:@"/tokens"]; +} + +- (NSString *)storageURLPrefix { + return [pithosObjectStoreURLString copy]; +} + +- (NSString *)loginURL { + return [astakosWebloginURLString stringByAppendingString:@"/login"]; +} + +- (NSString *)publicURLPrefix { + return [pithosObjectStoreURLString copy]; +} + +- (NSString *)userCatalogURL { + return [astakosAccountURLString stringByAppendingString:@"/user_catalogs"]; +} + #pragma mark - #pragma mark Actions -- (void)authenticateWithServerURL:(NSString *)aServerURL authUser:(NSString *)anAuthUser authToken:(NSString *)anAuthToken { - self.serverURL = aServerURL; - self.authUser = anAuthUser; +- (void)updateWithAuthURLString:(NSString *)anAuthURLString + pithosObjectStoreURLString:(NSString *)aPithosObjectStoreURLString + astakosAccountURLString:(NSString *)anAstakosAccountURLString + astakosWebloginURLString:(NSString *)anAstakosWebloginURLString + manual:(BOOL)aManual + authToken:(NSString *)anAuthToken + authUser:(NSString *)anAuthUser + ignoreSSLErrors:(BOOL)anIgnoreSSLErrors { + self.authURLString = anAuthURLString; + self.pithosObjectStoreURLString = aPithosObjectStoreURLString; + self.astakosAccountURLString = anAstakosAccountURLString; + self.astakosWebloginURLString = anAstakosWebloginURLString; + self.manual = aManual; self.authToken = anAuthToken; - DLog(@"Account: %@\nauthentication", self); - if (![authUser length] || ![authToken length]) { + self.authUser = anAuthUser; + self.ignoreSSLErrors = anIgnoreSSLErrors; + DLog(@"Account updated: %@", self); + if (!authToken.length || !authUser.length) { self.active = NO; self.syncActive = NO; - // XXX Show preferences with self as the selected account? } else { - [self updateUserCatalogForForDisplaynames:nil UUIDs:[NSArray arrayWithObject:authUser]]; - + [self updateUserCatalogForDisplaynames:nil UUIDs:[NSArray arrayWithObject:authUser]]; + self.active = YES; if (syncDaemon) { self.syncDaemon.pithos = self.pithos; @@ -412,15 +394,6 @@ } } -- (void)loginWithServerURL:(NSString *)aServerURL { - self.serverURL = aServerURL; - NSProcessInfo *processInfo = [NSProcessInfo processInfo]; - NSString *loginURL = [NSString stringWithFormat:@"%@?next=pithos://%d/%@&force=", - self.loginURLPrefix, [processInfo processIdentifier], [ASIPithosRequest encodeToPercentEscape:self.name]]; - DLog(@"Account: %@\nloginURL: %@", self, loginURL); - [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:loginURL]]; -} - - (void)updateSyncWithSyncActive:(BOOL)aSyncActive syncDirectoryPath:(NSString *)aSyncDirectoryPath syncAccountsDictionary:(NSMutableDictionary *)aSyncAccountsDictionary @@ -438,7 +411,57 @@ } } -- (ASIPithosRequest *)updateUserCatalogForForDisplaynames:(NSArray *)displaynames UUIDs:(NSArray *)UUIDs { +- (NSMutableDictionary *)servicesFromServiceCatalogRequest:(ASIPithosRequest *)serviceCatalogRequest { + NSMutableDictionary *services = [NSMutableDictionary dictionary]; + if (serviceCatalogRequest.responseStatusCode == 200) { + BOOL pithosObjectStoreFound = NO; + BOOL astakosAccountFound = NO; + BOOL astakosWebloginFound = NO; + NSArray *serviceCatalog = [serviceCatalogRequest serviceCatalog]; + for (NSDictionary *service in serviceCatalog) { + NSString *serviceName = [service objectForKey:@"name"]; + if (!pithosObjectStoreFound && [serviceName isEqualToString:@"pithos_object-store"]) { + [services setObject:[[[service objectForKey:@"endpoints"] objectAtIndex:0] objectForKey:@"publicURL"] + forKey:@"PithosObjectStoreURLString"]; + pithosObjectStoreFound = YES; + } else if (!astakosAccountFound && [serviceName isEqualToString:@"astakos_account"]) { + [services setObject:[[[service objectForKey:@"endpoints"] objectAtIndex:0] objectForKey:@"publicURL"] + forKey:@"AstakosAccountURLString"]; + astakosAccountFound = YES; + } else if (!astakosWebloginFound && [serviceName isEqualToString:@"astakos_weblogin"]) { + [services setObject:[[[service objectForKey:@"endpoints"] objectAtIndex:0] objectForKey:@"SNF:webloginURL"] + forKey:@"AstakosWebloginURLString"]; + astakosWebloginFound = YES; + } + if (pithosObjectStoreFound && astakosAccountFound && astakosWebloginFound) + break; + } + } + return services; +} + +- (void)updateServicesFromServiceCatalogRequest:(ASIPithosRequest *)serviceCatalogRequest { + if (serviceCatalogRequest.responseStatusCode == 200) { + NSMutableDictionary *services = [self servicesFromServiceCatalogRequest:serviceCatalogRequest]; + self.pithosObjectStoreURLString = [services objectForKey:@"PithosObjectStoreURLString"]; + self.astakosAccountURLString = [services objectForKey:@"AstakosAccountURLString"]; + self.astakosWebloginURLString = [services objectForKey:@"AstakosWebloginURLString"]; + self.manual = NO; + + if (authToken.length) { + NSDictionary *token = [serviceCatalogRequest token]; + self.authToken = [token objectForKey:@"id"]; + self.authUser = [[token objectForKey:@"tenant"] objectForKey:@"id"]; + } + } else if (serviceCatalogRequest.responseStatusCode == 404) { + self.pithosObjectStoreURLString = [[[NSURL URLWithString:authURLString] URLByAppendingPathComponent:@"v1"] description]; + self.astakosAccountURLString = [self.authURLString copy]; + self.astakosWebloginURLString = [self.authURLString copy]; + self.manual = YES; + } +} + +- (ASIPithosRequest *)updateUserCatalogForDisplaynames:(NSArray *)displaynames UUIDs:(NSArray *)UUIDs { ASIPithosRequest *userCatalogRequest = [ASIPithosRequest userCatalogRequestWithPithos:self.pithos displaynames:displaynames UUIDs:UUIDs]; @@ -496,22 +519,32 @@ self.syncSkipHidden = [decoder decodeBoolForKey:@"syncSkipHidden"]; self.syncLastCompleted = [decoder decodeObjectForKey:@"syncLastCompleted"]; - self.serverURL = [decoder decodeObjectForKey:@"serverURL"]; - self.versionResource = [decoder decodeObjectForKey:@"versionResource"]; - self.loginResource = [decoder decodeObjectForKey:@"loginResource"]; - self.publicResource = [decoder decodeObjectForKey:@"publicResource"]; - self.userCatalogResource = [decoder decodeObjectForKey:@"userCatalogResource"]; + self.authURLString = [decoder decodeObjectForKey:@"authURLString"]; + self.pithosObjectStoreURLString = [decoder decodeObjectForKey:@"pithosObjectStoreURLString"]; + self.astakosAccountURLString = [decoder decodeObjectForKey:@"astakosAccountURLString"]; + self.astakosWebloginURLString = [decoder decodeObjectForKey:@"astakosWebloginURLString"]; + self.manual = [decoder decodeBoolForKey:@"manual"]; + + // Support for older versions. + if (!authURLString && !pithosObjectStoreURLString && !astakosAccountURLString && !astakosWebloginURLString) { + NSString *tmpURLString = [decoder decodeObjectForKey:@"serverURL"]; + if (!tmpURLString || + [[[NSURL URLWithString:tmpURLString] URLByAppendingPathComponent:@""] isEqual:[[NSURL URLWithString:defaultManualURLString] URLByAppendingPathComponent:@""]]) { + self.authURLString = defaultAuthURLString; + self.manual = NO; + } else { + self.pithosObjectStoreURLString = [tmpURLString stringByAppendingString:@"/v1"]; + self.astakosAccountURLString = tmpURLString; + self.astakosWebloginURLString = tmpURLString; + self.manual = YES; + } + } - self.authUser = [decoder decodeObjectForKey:@"authUser"]; self.authToken = [decoder decodeObjectForKey:@"authToken"]; - self.storageURLPrefix = [decoder decodeObjectForKey:@"storageURLPrefix"]; - self.authURL = [decoder decodeObjectForKey:@"authURL"]; - self.publicURLPrefix = [decoder decodeObjectForKey:@"publicURLPrefix"]; - self.loginURLPrefix = [decoder decodeObjectForKey:@"loginURLPrefix"]; - self.userCatalogURL = [decoder decodeObjectForKey:@"userCatalogURL"]; + self.authUser = [decoder decodeObjectForKey:@"authUser"]; self.userCatalog = [decoder decodeObjectForKey:@"userCatalog"]; - if (![authUser length] || ![authToken length] || ![self.storageURLPrefix length]) + if (![authUser length] || ![authToken length]) self.active = NO; NSString *currentVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; @@ -537,19 +570,14 @@ [encoder encodeBool:syncSkipHidden forKey:@"syncSkipHidden"]; [encoder encodeObject:self.syncLastCompleted forKey:@"syncLastCompleted"]; - [encoder encodeObject:serverURL forKey:@"serverURL"]; - [encoder encodeObject:versionResource forKey:@"versionResource"]; - [encoder encodeObject:publicResource forKey:@"publicResource"]; - [encoder encodeObject:loginResource forKey:@"loginResource"]; - [encoder encodeObject:userCatalogResource forKey:@"userCatalogResource"]; + [encoder encodeObject:authURLString forKey:@"authURLString"]; + [encoder encodeObject:pithosObjectStoreURLString forKey:@"pithosObjectStoreURLString"]; + [encoder encodeObject:astakosAccountURLString forKey:@"astakosAccountURLString"]; + [encoder encodeObject:astakosWebloginURLString forKey:@"astakosWebloginURLString"]; + [encoder encodeBool:manual forKey:@"manual"]; - [encoder encodeObject:authUser forKey:@"authUser"]; [encoder encodeObject:authToken forKey:@"authToken"]; - [encoder encodeObject:storageURLPrefix forKey:@"storageURLPrefix"]; - [encoder encodeObject:authURL forKey:@"authURL"]; - [encoder encodeObject:publicURLPrefix forKey:@"publicURLPrefix"]; - [encoder encodeObject:loginURLPrefix forKey:@"loginURLPrefix"]; - [encoder encodeObject:userCatalogURL forKey:@"userCatalogURL"]; + [encoder encodeObject:authUser forKey:@"authUser"]; [encoder encodeObject:userCatalog forKey:@"userCatalog"]; } diff --git a/pithos-macos/PithosAccountNode.m b/pithos-macos/PithosAccountNode.m index 4279efc..69029b5 100644 --- a/pithos-macos/PithosAccountNode.m +++ b/pithos-macos/PithosAccountNode.m @@ -86,7 +86,7 @@ static NSImage *sharedIcon = nil; [UUIDs removeObject:@""]; [UUIDs removeObject:@"*"]; if (UUIDs.count) { - [pithosAccountManager updateUserCatalogForForDisplaynames:nil UUIDs:[UUIDs allObjects]]; + [pithosAccountManager updateUserCatalogForDisplaynames:nil UUIDs:[UUIDs allObjects]]; } NSMutableDictionary *newTranslatedGroups = [NSMutableDictionary dictionaryWithCapacity:pithosAccount.groups.count]; @@ -130,7 +130,7 @@ static NSImage *sharedIcon = nil; - (NSString *)url { if (url == nil) url = [[NSString alloc] initWithFormat:@"%@%@", - (sharingAccount ? [pithos storageURLWithAuthUser:sharingAccount] : pithos.storageURL), + (sharingAccount ? [pithos storageURLWithAuthUser:sharingAccount] : pithos.storageURL), (shared ? @"?shared" : @"")]; return url; } @@ -412,7 +412,7 @@ static NSImage *sharedIcon = nil; [allGroupUsers removeObject:@""]; [allGroupUsers removeObject:@"*"]; if (allGroupUsers.count) { - ASIPithosRequest *userCatalogRequest = [pithosAccountManager updateUserCatalogForForDisplaynames:[allGroupUsers allObjects] + ASIPithosRequest *userCatalogRequest = [pithosAccountManager updateUserCatalogForDisplaynames:[allGroupUsers allObjects] UUIDs:nil]; if (userCatalogRequest.error || ((userCatalogRequest.responseStatusCode != 200) && (userCatalogRequest.responseStatusCode != 404))) { return; diff --git a/pithos-macos/PithosBrowserController.m b/pithos-macos/PithosBrowserController.m index e8f0743..d5c4612 100644 --- a/pithos-macos/PithosBrowserController.m +++ b/pithos-macos/PithosBrowserController.m @@ -386,9 +386,10 @@ - (void)setPithos:(ASIPithos *)aPithos { if (aPithos) { if (![aPithos.authUser isEqualToString:pithos.authUser] || - ![aPithos.authToken isEqualToString:pithos.authToken] || - ![aPithos.storageURLPrefix isEqualToString:pithos.storageURLPrefix] || - ![aPithos.publicURLPrefix isEqualToString:pithos.publicURLPrefix]) { + ![aPithos.authToken isEqualToString:pithos.authToken] || + (aPithos.ignoreSSLErrors != pithos.ignoreSSLErrors) || + ![aPithos.storageURLPrefix isEqual:pithos.storageURLPrefix] || + ![aPithos.publicURLPrefix isEqual:pithos.publicURLPrefix]) { [self resetBrowser]; pithos = aPithos; [self startBrowser]; diff --git a/pithos-macos/PithosObjectNode.m b/pithos-macos/PithosObjectNode.m index 7587e6e..973a414 100644 --- a/pithos-macos/PithosObjectNode.m +++ b/pithos-macos/PithosObjectNode.m @@ -84,7 +84,7 @@ if (displayname) { self.translatedModifiedBy = displayname; } else { - [pithosAccountManager updateUserCatalogForForDisplaynames:nil UUIDs:[NSArray arrayWithObject:pithosObject.modifiedBy]]; + [pithosAccountManager updateUserCatalogForDisplaynames:nil UUIDs:[NSArray arrayWithObject:pithosObject.modifiedBy]]; self.translatedModifiedBy = [pithosAccountManager displaynameForUUID:pithosObject.modifiedBy safe:YES]; } } else { @@ -103,7 +103,7 @@ [UUIDs removeObject:@""]; [UUIDs removeObject:@"*"]; if (UUIDs.count) { - [pithosAccountManager updateUserCatalogForForDisplaynames:nil UUIDs:[UUIDs allObjects]]; + [pithosAccountManager updateUserCatalogForDisplaynames:nil UUIDs:[UUIDs allObjects]]; } NSMutableArray *newTranslatedPermissions = [NSMutableArray arrayWithCapacity:pithosObject.permissions.count]; @@ -315,7 +315,7 @@ [allUsers removeObject:@""]; [allUsers removeObject:@"*"]; if (allUsers.count) { - ASIPithosRequest *userCatalogRequest = [pithosAccountManager updateUserCatalogForForDisplaynames:[allUsers allObjects] + ASIPithosRequest *userCatalogRequest = [pithosAccountManager updateUserCatalogForDisplaynames:[allUsers allObjects] UUIDs:nil]; if (userCatalogRequest.error || ((userCatalogRequest.responseStatusCode != 200) && (userCatalogRequest.responseStatusCode != 404))) { return; diff --git a/pithos-macos/PithosPreferencesController.h b/pithos-macos/PithosPreferencesController.h index b97f171..78ac807 100644 --- a/pithos-macos/PithosPreferencesController.h +++ b/pithos-macos/PithosPreferencesController.h @@ -46,13 +46,18 @@ BOOL accountRemoveEnable; - NSString *serverURL; + NSString *authURLString; + BOOL manual; + NSString *pithosObjectStoreURLString; + NSString *astakosAccountURLString; + NSString *astakosWebloginURLString; NSString *authUser; NSString *authToken; NSString *displayname; - BOOL manual; - BOOL loginEnable; - BOOL loginCancelEnable; + BOOL ignoreSSLErrors; + BOOL retrieveTokenEnable; + BOOL authorizationSaveEnable; + BOOL authorizationCancelEnable; BOOL syncActive; BOOL syncSkipHidden; @@ -72,13 +77,18 @@ @property (nonatomic, assign) BOOL accountRemoveEnable; -@property (nonatomic, copy) NSString *serverURL; +@property (nonatomic, copy) NSString *authURLString; +@property (nonatomic, assign) BOOL manual; +@property (nonatomic, copy) NSString *pithosObjectStoreURLString; +@property (nonatomic, copy) NSString *astakosAccountURLString; +@property (nonatomic, copy) NSString *astakosWebloginURLString; @property (nonatomic, copy) NSString *authUser; @property (nonatomic, copy) NSString *authToken; @property (nonatomic, copy) NSString *displayname; -@property (nonatomic, assign) BOOL manual; -@property (nonatomic, assign) BOOL loginEnable; -@property (nonatomic, assign) BOOL loginCancelEnable; +@property (nonatomic, assign) BOOL ignoreSSLErrors; +@property (nonatomic, assign) BOOL retrieveTokenEnable; +@property (nonatomic, assign) BOOL authorizationSaveEnable; +@property (nonatomic, assign) BOOL authorizationCancelEnable; @property (nonatomic, assign) BOOL syncActive; @property (nonatomic, assign) BOOL syncSkipHidden; @@ -92,8 +102,9 @@ - (IBAction)addAccount:(id)sender; - (IBAction)removeAccount:(id)sender; -- (IBAction)login:(id)sender; -- (IBAction)loginCancel:(id)sender; +- (IBAction)retrieveToken:(id)sender; +- (IBAction)authorizationSave:(id)sender; +- (IBAction)authorizationCancel:(id)sender; - (IBAction)syncApply:(id)sender; - (IBAction)syncCancel:(id)sender; - (IBAction)syncRefresh:(id)sender; diff --git a/pithos-macos/PithosPreferencesController.m b/pithos-macos/PithosPreferencesController.m index 71a0ced..4ddbed2 100644 --- a/pithos-macos/PithosPreferencesController.m +++ b/pithos-macos/PithosPreferencesController.m @@ -45,9 +45,23 @@ #import "PithosEmptyNode.h" #import "PithosAccount.h" #import "ASIPithosAccount.h" +#import "ASIPithosRequest.h" +#import "ASIPithosAccountRequest.h" +#import "PithosUtilities.h" #import "pithos_macosAppDelegate.h" - #import "ImageAndTextCell.h" + +@interface NSString(Additions) +- (BOOL)isValidURL; +@end + +@implementation NSString(Additions) +- (BOOL)isValidURL { + NSURL *URL = [NSURL URLWithString:self]; + return (URL && URL.scheme && URL.host); +} +@end + @interface PithosPreferencesSyncOutlineViewCell : ImageAndTextCell {} @end @@ -69,8 +83,9 @@ @implementation PithosPreferencesController @synthesize selectedPithosAccount; @synthesize accountRemoveEnable; -@synthesize serverURL, authUser, authToken, displayname, manual, loginEnable, loginCancelEnable; -@synthesize syncActive, syncSkipHidden, syncDirectoryPath, syncAccountsDictionary, syncApplyEnable, syncCancelEnable, +@synthesize authURLString, manual, pithosObjectStoreURLString, astakosAccountURLString, astakosWebloginURLString, + authUser, authToken, displayname, ignoreSSLErrors, retrieveTokenEnable, authorizationSaveEnable, authorizationCancelEnable; +@synthesize syncActive, syncSkipHidden, syncDirectoryPath, syncAccountsDictionary, syncApplyEnable, syncCancelEnable, syncAccountsRootFilesNodes; #pragma mark - @@ -143,11 +158,22 @@ self.accountRemoveEnable = (delegate.activated && ([delegate.pithosAccounts count] > 1)); } -- (void)updateLogin { - self.loginEnable = ([selectedPithosAccount urlIsValid:serverURL] && (!manual || ([authUser length] && [authToken length]))); - self.loginCancelEnable = (![selectedPithosAccount.serverURL isEqualToString:serverURL] || - (selectedPithosAccount.authUser && ![selectedPithosAccount.authUser isEqualToString:authUser]) || - (selectedPithosAccount.authToken && ![selectedPithosAccount.authToken isEqualToString:authToken])); +- (void)updateAuthorization { + self.retrieveTokenEnable = ((!manual && [authURLString isValidURL]) || + (manual && [astakosWebloginURLString isValidURL])); + self.authorizationSaveEnable = (authToken.length && + ((!manual && [authURLString isValidURL]) || + (manual && authUser.length && [pithosObjectStoreURLString isValidURL] && + [astakosAccountURLString isValidURL] && [astakosWebloginURLString isValidURL]))); + self.authorizationCancelEnable = (selectedPithosAccount.active && + (![selectedPithosAccount.authURLString isEqualToString:authURLString] || + (selectedPithosAccount.manual != manual) || + ![selectedPithosAccount.pithosObjectStoreURLString isEqualToString:pithosObjectStoreURLString] || + ![selectedPithosAccount.astakosAccountURLString isEqualToString:astakosAccountURLString] || + ![selectedPithosAccount.astakosWebloginURLString isEqualToString:astakosWebloginURLString] || + ![selectedPithosAccount.authToken isEqualToString:authToken] || + ![selectedPithosAccount.authUser isEqualToString:authUser] || + (selectedPithosAccount.ignoreSSLErrors != ignoreSSLErrors))); } - (void)updateSync { @@ -178,37 +204,48 @@ selectedPithosAccount.sharingAccountsNode.childrenUpdatedNotificationName = @"SelectedPithosAccountNodeChildrenUpdated"; [self updateAccounts]; - [self loginCancel:self]; + [self authorizationCancel:self]; [self syncCancel:self]; [self groupsRevert:self]; } } -#pragma Login Properties +#pragma Authorization Properties + +- (void)setAuthURLString:(NSString *)anAuthURLString { + authURLString = [anAuthURLString copy]; + [self updateAuthorization]; +} -- (void)setServerURL:(NSString *)aServerURL { - serverURL = [aServerURL copy]; - [self updateLogin]; +- (void)setManual:(BOOL)aManual { + manual = aManual; + [self updateAuthorization]; +} + +- (void)setPithosObjectStoreURLString:(NSString *)aPithosObjectStoreURLString { + pithosObjectStoreURLString = [aPithosObjectStoreURLString copy]; + [self updateAuthorization]; +} + +- (void)setAstakosAccountURLString:(NSString *)aAstakosAccountURLString { + astakosAccountURLString = [aAstakosAccountURLString copy]; + [self updateAuthorization]; +} + +- (void)setAstakosWebloginURLString:(NSString *)aAstakosWebloginURLString { + astakosWebloginURLString = [aAstakosWebloginURLString copy]; + [self updateAuthorization]; } - (void)setAuthUser:(NSString *)anAuthUser { authUser = [anAuthUser copy]; - [self updateLogin]; + [self updateAuthorization]; self.displayname = [self.selectedPithosAccount displaynameForUUID:authUser safe:NO]; } - (void)setAuthToken:(NSString *)anAuthToken { authToken = [anAuthToken copy]; - [self updateLogin]; -} - -- (void)setManual:(BOOL)aManual { - manual = aManual; - [self updateLogin]; - if (!manual) { - self.authUser = selectedPithosAccount.authUser; - self.authToken = selectedPithosAccount.authToken; - } + [self updateAuthorization]; } #pragma Sync Properties @@ -280,32 +317,119 @@ [self updateAccounts]; } -#pragma Login Actions +#pragma Authorization Actions -- (IBAction)login:(id)sender { - self.syncAccountsRootFilesNodes = [NSMutableDictionary dictionary]; +- (IBAction)retrieveToken:(id)sender { + PithosAccount *tmpPithosAccount = [PithosAccount pithosAccount]; + tmpPithosAccount.manual = manual; + tmpPithosAccount.ignoreSSLErrors = ignoreSSLErrors; if (!manual) { - [selectedPithosAccount loginWithServerURL:serverURL]; + tmpPithosAccount.authURLString = authURLString; + ASIPithosRequest *serviceCatalogRequest = [ASIPithosRequest serviceCatalogRequestWithPithos:tmpPithosAccount.pithos]; + [PithosUtilities startAndWaitForRequest:serviceCatalogRequest]; + if (serviceCatalogRequest.error || ((serviceCatalogRequest.responseStatusCode != 200) && (serviceCatalogRequest.responseStatusCode != 404))) { + [PithosUtilities httpRequestErrorAlertWithRequest:serviceCatalogRequest]; + return; + } else { + [tmpPithosAccount updateServicesFromServiceCatalogRequest:serviceCatalogRequest]; + self.manual = tmpPithosAccount.manual; + self.pithosObjectStoreURLString = tmpPithosAccount.pithosObjectStoreURLString; + self.astakosAccountURLString = tmpPithosAccount.astakosAccountURLString; + self.astakosWebloginURLString = tmpPithosAccount.astakosWebloginURLString; + } } else { - [selectedPithosAccount authenticateWithServerURL:serverURL authUser:authUser authToken:authToken]; - self.manual = NO; - self.displayname = [selectedPithosAccount displaynameForUUID:authUser safe:NO]; - pithos_macosAppDelegate *delegate = (pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate]; - [delegate savePithosAccounts:self]; - if (!delegate.activated) { - delegate.activated = YES; - [delegate showPithosBrowser:self]; + tmpPithosAccount.astakosWebloginURLString = astakosWebloginURLString; + } + NSString *protocol = [[[[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"] objectAtIndex:0] objectForKey:@"CFBundleURLSchemes"] objectAtIndex:0]; + NSProcessInfo *processInfo = [NSProcessInfo processInfo]; + NSString *loginURLString = [NSString stringWithFormat:@"%@?next=%@://%d/%@&force=", + tmpPithosAccount.loginURL, + protocol, + [processInfo processIdentifier], + [ASIPithosRequest encodeToPercentEscape:selectedPithosAccount.name]]; + DLog(@"Account: %@\nloginURL: %@", self, loginURLString); + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:loginURLString]]; +} + +- (IBAction)authorizationSave:(id)sender { + if (!manual) { + PithosAccount *tmpPithosAccount = [PithosAccount pithosAccount]; + tmpPithosAccount.authURLString = authURLString; + tmpPithosAccount.manual = manual; + tmpPithosAccount.authToken = authToken; + tmpPithosAccount.authUser = authUser; + tmpPithosAccount.ignoreSSLErrors = ignoreSSLErrors; + ASIPithosRequest *serviceCatalogRequest = [ASIPithosRequest serviceCatalogRequestWithPithos:tmpPithosAccount.pithos]; + [PithosUtilities startAndWaitForRequest:serviceCatalogRequest]; + if (serviceCatalogRequest.error || ((serviceCatalogRequest.responseStatusCode != 200) && (serviceCatalogRequest.responseStatusCode != 404))) { + [PithosUtilities httpRequestErrorAlertWithRequest:serviceCatalogRequest]; + return; + } else { + [tmpPithosAccount updateServicesFromServiceCatalogRequest:serviceCatalogRequest]; + self.manual = tmpPithosAccount.manual; + self.pithosObjectStoreURLString = tmpPithosAccount.pithosObjectStoreURLString; + self.astakosAccountURLString = tmpPithosAccount.astakosAccountURLString; + self.astakosWebloginURLString = tmpPithosAccount.astakosWebloginURLString; + if (serviceCatalogRequest.responseStatusCode == 200) { + if (tmpPithosAccount.authToken) { + self.authToken = tmpPithosAccount.authToken; + self.authUser = tmpPithosAccount.authUser; + } + self.syncAccountsRootFilesNodes = [NSMutableDictionary dictionary]; + [selectedPithosAccount updateWithAuthURLString:authURLString + pithosObjectStoreURLString:pithosObjectStoreURLString + astakosAccountURLString:astakosAccountURLString + astakosWebloginURLString:astakosWebloginURLString + manual:manual + authToken:authToken + authUser:authUser + ignoreSSLErrors:ignoreSSLErrors]; + self.displayname = [selectedPithosAccount displaynameForUUID:authUser safe:NO]; + [self updateAuthorization]; + } else { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Authentication Failure"]; + [alert setInformativeText:@"Please enter also your UUID."]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + return; + } } - if ([selectedPithosAccount isEqualTo:delegate.currentPithosAccount]) - delegate.pithosBrowserController.pithos = selectedPithosAccount.pithos; + } else { + self.syncAccountsRootFilesNodes = [NSMutableDictionary dictionary]; + self.authURLString = nil; + // There is not a proper way to authenticate if the pair of token and UUID is valid. + [selectedPithosAccount updateWithAuthURLString:authURLString + pithosObjectStoreURLString:pithosObjectStoreURLString + astakosAccountURLString:astakosAccountURLString + astakosWebloginURLString:astakosWebloginURLString + manual:manual + authToken:authToken + authUser:authUser + ignoreSSLErrors:ignoreSSLErrors]; + self.displayname = [selectedPithosAccount displaynameForUUID:authUser safe:NO]; + [self updateAuthorization]; + } + + pithos_macosAppDelegate *delegate = (pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate]; + [delegate savePithosAccounts:self]; + if (!delegate.activated) { + delegate.activated = YES; + [delegate showPithosBrowser:self]; } + if ([selectedPithosAccount isEqualTo:delegate.currentPithosAccount]) + delegate.pithosBrowserController.pithos = selectedPithosAccount.pithos; } -- (IBAction)loginCancel:(id)server { - self.serverURL = selectedPithosAccount.serverURL; - self.authUser = selectedPithosAccount.authUser; +- (IBAction)authorizationCancel:(id)server { + self.authURLString = selectedPithosAccount.authURLString; + self.manual = selectedPithosAccount.manual; + self.pithosObjectStoreURLString = selectedPithosAccount.pithosObjectStoreURLString; + self.astakosAccountURLString = selectedPithosAccount.astakosAccountURLString; + self.astakosWebloginURLString = selectedPithosAccount.astakosWebloginURLString; self.authToken = selectedPithosAccount.authToken; - self.manual = NO; + self.authUser = selectedPithosAccount.authUser; + self.ignoreSSLErrors = selectedPithosAccount.ignoreSSLErrors; } #pragma Sync Actions diff --git a/pithos-macos/PithosPreferencesController.xib b/pithos-macos/PithosPreferencesController.xib index 77539b8..0e45060 100644 --- a/pithos-macos/PithosPreferencesController.xib +++ b/pithos-macos/PithosPreferencesController.xib @@ -3,12 +3,12 @@ 1070 11G63 - 2843 + 3084 1138.51 569.00 com.apple.InterfaceBuilder.CocoaPlugin - 2843 + 3084 YES @@ -17,6 +17,7 @@ NSButton NSButtonCell NSCustomObject + NSCustomView NSDictionaryController NSOutlineView NSPathCell @@ -55,13 +56,13 @@ 11 2 - {{403, 468}, {425, 300}} + {{403, 468}, {500, 370}} 1954022400 Pithos+ Preferences NSWindow - {425, 262} + {500, 370} 274 @@ -80,9 +81,11 @@ 256 - {118, 215} + {118, 285} + + 2 _NS:1828 YES @@ -90,7 +93,9 @@ 256 {118, 17} + + 2 _NS:1830 @@ -188,9 +193,11 @@ 1 - {{1, 17}, {118, 215}} + {{1, 17}, {118, 285}} + + 2 _NS:1826 @@ -201,6 +208,7 @@ -2147483392 {{224, 17}, {15, 102}} + _NS:1845 @@ -213,6 +221,7 @@ -2147483392 {{1, 48.325627356767654}, {82.028970718383789, 15}} + _NS:1847 1 @@ -229,16 +238,20 @@ {{1, 0}, {118, 17}} + + 2 _NS:1831 4 - {{20, 47}, {120, 233}} + {{20, 47}, {120, 303}} + + 2 _NS:1824 133682 @@ -250,9 +263,11 @@ 18 - {{147, 37}, {265, 249}} + {{147, 37}, {340, 319}} + + 2 _NS:608 YES @@ -266,14 +281,15 @@ 268 - {{14, 183}, {41, 14}} + {{38, 253}, {57, 14}} + YES 68288064 71304192 - Server: + Auth URL: YES @@ -289,12 +305,13 @@ 266 - {{60, 181}, {168, 19}} + {{100, 251}, {203, 19}} - + + YES - -1804468671 + -1267597759 272761920 @@ -314,161 +331,70 @@ - + 266 - {{60, 123}, {168, 19}} + {{100, 205}, {203, 19}} - + + YES - + -1267597759 272761920 - + YES - + 266 - {{60, 96}, {168, 19}} + {{100, 183}, {203, 19}} - + + YES - + -1267597759 272761920 - + YES - + 266 - {{60, 69}, {168, 19}} + {{100, 161}, {203, 19}} - + + YES - - -1536033215 + + -1267597759 272761920 - + YES - - - 268 - {{14, 125}, {41, 14}} - - - YES - - 68288064 - 71304192 - UUID: - - - YES - - - - - - - 268 - {{14, 71}, {41, 14}} - - - YES - - 68288064 - 71304192 - User: - - - YES - - - - - - - 268 - {{14, 98}, {41, 14}} - - - YES - - 68288064 - 71304192 - Token: - - - YES - - - - - - - 268 - {{14, 150}, {86, 14}} - - - YES - - 68288064 - 4195328 - Authentication: - - - YES - - - - - - - -2147483634 - {{-3, 170}, {251, 5}} - - - {0, 0} - - 67239424 - 0 - Box - - - - 3 - MCAwLjgwMDAwMDAxMTkAA - - - 3 - 2 - 0 - NO - 268 - {{57, 45}, {63, 18}} + {{97, 227}, {63, 18}} - + + YES 67239424 @@ -491,17 +417,42 @@ 25 + + + 268 + {{97, 34}, {113, 18}} + + + + YES + + 67239424 + 131072 + Ignore SSL Errors + + + 1211912703 + 2 + + + + + 200 + 25 + + 289 - {{161, 4}, {72, 28}} + {{236, 4}, {72, 28}} + YES -2080244224 134348800 - Login + Save -2034876161 @@ -517,11 +468,35 @@ 75 + + + 268 + {{95, 54}, {106, 28}} + + + + YES + + -2080244224 + 134348800 + Retrieve Token + + + -2034876161 + 129 + + + + 400 + 75 + + 289 - {{91, 4}, {72, 28}} + {{166, 4}, {72, 28}} + YES @@ -539,130 +514,351 @@ 75 - - {{10, 33}, {245, 203}} - - - _NS:610 - - Info - - - - - 2 - - - 256 - - YES - - - 266 - - YES - - YES - Apple URL pasteboard type - NSFilenamesPboardType - - - {{62, 179}, {169, 22}} - - + + + 268 + {{31, 207}, {64, 14}} + + + YES - - 337772033 - 131072 - - - file://localhost/ - + + 68288064 + 71304192 + Pithos URL: - - - YES - - 67239488 - 1024 - karvouni4 - - - - - - file://localhost// - - - - 67239488 - 1024 - Macintosh HD - - - - - - file://localhost// - - - - 2 - - - YES - public.folder - + + YES + + - - + + 268 - {{14, 183}, {46, 14}} - - + {{21, 185}, {74, 14}} + + + YES - + 68288064 71304192 - Sync to: + Astakos URL: - + YES - - - 289 - {{161, 4}, {72, 28}} - + + + 268 + {{14, 163}, {81, 14}} + + + YES - - -2080244224 - 134348800 - Apply + + 68288064 + 71304192 + Weblogin URL: - - -2034876161 - 129 - - - - 400 - 75 + + YES + + - - - 289 - {{91, 4}, {72, 28}} - - - YES - - -2080244224 + + + -2147483634 + {{-3, 152}, {326, 5}} + + + + {0, 0} + + 67239424 + 0 + Box + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + 3 + 2 + 0 + NO + + + + -2147483634 + {{-3, 50}, {326, 5}} + + + + {0, 0} + + 67239424 + 0 + Box + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + 3 + 2 + 0 + NO + + + + 268 + {{54, 132}, {41, 14}} + + + + YES + + 68288064 + 71304192 + Token: + + + YES + + + + + + + 268 + {{54, 110}, {41, 14}} + + + + YES + + 68288064 + 71304192 + UUID: + + + YES + + + + + + + 268 + {{54, 88}, {41, 14}} + + + + YES + + 68288064 + 71304192 + User: + + + YES + + + + + + + 266 + {{100, 130}, {203, 19}} + + + + YES + + -1804468671 + 272761920 + + + + YES + + + + + + + 266 + {{100, 108}, {203, 19}} + + + + YES + + -1267597759 + 272761920 + + + + YES + + + + + + + 266 + {{100, 86}, {203, 19}} + + + + YES + + -1536033215 + 272761920 + + + + YES + + + + + + {{10, 33}, {320, 273}} + + + + _NS:610 + + Authorization + + + + + 2 + + + 256 + + YES + + + 266 + + YES + + YES + Apple URL pasteboard type + NSFilenamesPboardType + + + {{62, 249}, {244, 22}} + + + YES + + 337772033 + 131072 + + + file://localhost/ + + + + + YES + + 67239488 + 1024 + karvouni4 + + + + + + file://localhost// + + + + 67239488 + 1024 + Macintosh HD + + + + + + file://localhost// + + + + 2 + + + YES + public.folder + + + + + + 268 + {{14, 253}, {46, 14}} + + + YES + + 68288064 + 71304192 + Sync to: + + + YES + + + + + + + 289 + {{236, 4}, {72, 28}} + + + YES + + -2080244224 + 134348800 + Apply + + + -2034876161 + 129 + + + + 400 + 75 + + + + + 289 + {{166, 4}, {72, 28}} + + + YES + + -2080244224 134348800 Cancel @@ -701,7 +897,7 @@ 268 - {{26, 159}, {63, 18}} + {{26, 229}, {63, 18}} YES @@ -724,7 +920,7 @@ 268 - {{108, 159}, {111, 18}} + {{108, 229}, {111, 18}} YES @@ -757,15 +953,15 @@ 256 - {209, 95} + {284, 165} - + _NS:13 YES 256 - {209, 17} + {284, 17} _NS:16 @@ -819,7 +1015,7 @@ path - 171 + 246 42 1000 @@ -862,7 +1058,7 @@ - {{1, 17}, {209, 95}} + {{1, 17}, {284, 165}} _NS:11 @@ -870,438 +1066,479 @@ 4 - - - -2147483392 - {{205, 17}, {15, 13}} - - - _NS:58 - - _doScroller: - 0.68421052631578949 - - - - -2147483392 - {{1, 34}, {78, 15}} - - - _NS:60 - 1 - - _doScroller: - 0.97499999999999998 - - - - 2304 - - YES - - - {{1, 0}, {209, 17}} - - - _NS:15 - - - 4 - - - {{17, 40}, {211, 113}} - - - _NS:9 - 133682 - - - - - QSAAAEEgAABBmAAAQZgAAA - - - {{10, 33}, {245, 203}} - - _NS:620 - - Sync - - - - - 3 - - - 256 - - YES - - - 4374 - - YES - - - 2304 - - YES - - - 4352 - {103, 116} - - - YES - - - 256 - {103, 17} - - - - - - - -2147483392 - {{224, 0}, {16, 17}} - - - YES - - 100 - 40 - 1000 - - 75628096 - 2048 - Name - - - 3 - MC4zMzMzMzI5ODU2AA - - - - - 337772096 - 2048 - Text Cell - - Group - - - - - 3 - YES - YES - - - - 3 - 2 - - - 17 - 1925185536 - - - 1 - 4 - 15 - 0 - YES - 0 - 1 - - - {{1, 17}, {103, 116}} - - - - - 4 - - - - -2147483392 - {{-100, -100}, {15, 102}} - - - - _doScroller: - 0.80769230769230771 - - - - -2147483392 - {{1, 119}, {223, 15}} - - - 1 - - _doScroller: - 0.97590361445783136 - - - - 2304 - - YES - - - {{1, 0}, {103, 17}} - - - - - 4 - - - {{17, 66}, {105, 134}} - - - 133682 - - - - - QSAAAEEgAABBmAAAQZgAAA - - - - 4371 - - YES - - - 2304 - - YES - - - 4352 - {103, 116} - - - YES - - - 256 - {103, 17} - - - - - - - -2147483392 - {{224, 0}, {16, 17}} - - - YES - - 100 - 40 - 1000 - - 75628096 - 2048 - Members - - - 3 - MC4zMzMzMzI5ODU2AA - - - - - 337772096 - 2048 - Text Cell - - User - - - - - 3 - YES - YES - - - - 3 - 2 - - - 17 - 1925185536 - - - 1 - 4 - 15 - 0 - YES - 0 - 1 - - - {{1, 17}, {103, 116}} - - - - - 4 - - - + + -2147483392 - {{-100, -100}, {15, 102}} - - - + {{205, 17}, {15, 13}} + + + _NS:58 + _doScroller: - 0.80769230769230771 + 0.68421052631578949 - - + + -2147483392 - {{1, 119}, {223, 15}} - - + {{1, 34}, {78, 15}} + + + _NS:60 1 - + _doScroller: - 0.97590361445783136 + 0.97499999999999998 - - + + 2304 YES - + - {{1, 0}, {103, 17}} - - - + {{1, 0}, {284, 17}} + + + _NS:15 + 4 - {{123, 66}, {105, 134}} - - + {{17, 40}, {286, 183}} + + + _NS:9 133682 - - - - + + + + QSAAAEEgAABBmAAAQZgAAA - + + {{10, 33}, {320, 273}} + + _NS:620 + + Sync + + + + + 3 + + + 256 + + YES + - 292 - {{17, 41}, {18, 18}} - - - YES - - -2080244224 - 134217728 - - - - -2033434369 - 162 - - NSImage - NSAddTemplate + 4374 + + YES + + + 292 + {{17, -1}, {18, 18}} + + + 2 + YES + + -2080244224 + 134217728 + + + + -2033434369 + 162 + + NSImage + NSRemoveTemplate + + + + 400 + 75 + - - - 400 - 75 - - - - - 292 - {{34, 41}, {18, 18}} - - - YES - - -2080244224 - 134217728 - - - - -2033434369 - 162 - - NSImage - NSRemoveTemplate + + + 292 + {{0, -1}, {18, 18}} + + + 2 + YES + + -2080244224 + 134217728 + + + + -2033434369 + 162 + + NSImage + NSAddTemplate + + + + 400 + 75 + + + + + 4370 + + YES + + + 2304 + + YES + + + 4352 + {140, 186} + + + 2 + YES + + + 256 + {140, 17} + + + 2 + + + + + -2147483392 + {{224, 0}, {16, 17}} + + + YES + + 137 + 40 + 1000 + + 75628096 + 2048 + Name + + + 3 + MC4zMzMzMzI5ODU2AA + + + + + 337772096 + 2048 + Text Cell + + Group + + + + + 3 + YES + YES + + + + 3 + 2 + + + 17 + 1925185536 + + + 1 + 4 + 15 + 0 + YES + 0 + 1 + + + {{1, 17}, {140, 186}} + + + 2 + + + 4 + + + + -2147483392 + {{-100, -100}, {15, 102}} + + + + _doScroller: + 0.80769230769230771 + + + + -2147483392 + {{1, 119}, {223, 15}} + + + 1 + + _doScroller: + 0.97590361445783136 + + + + 2304 + + YES + + + {{1, 0}, {140, 17}} + + + 2 + + + 4 + + + {{0, 24}, {142, 204}} + + + 2 + 133682 + + + + + QSAAAEEgAABBmAAAQZgAAA - - - 400 - 75 - - - - 289 - {{193, 41}, {18, 18}} + {{17, 42}, {142, 228}} - - YES - - -2080244224 - 134217728 - - - - -2033434369 - 162 - - - - 400 - 75 - + + 2 + _NS:9 + NSView - + - 289 - {{210, 41}, {18, 18}} - - - YES - - -2080244224 - 134217728 - - - - -2033434369 - 162 - - - - 400 - 75 + 4371 + + YES + + + 292 + {{17, -1}, {18, 18}} + + + 2 + YES + + -2080244224 + 134217728 + + + + -2033434369 + 162 + + + + 400 + 75 + + + + + 292 + {{0, -1}, {18, 18}} + + + 2 + YES + + -2080244224 + 134217728 + + + + -2033434369 + 162 + + + + 400 + 75 + + + + + 4370 + + YES + + + 2304 + + YES + + + 4352 + {140, 186} + + + 2 + YES + + + 256 + {140, 17} + + + 2 + + + + + -2147483392 + {{224, 0}, {16, 17}} + + + YES + + 137 + 40 + 1000 + + 75628096 + 2048 + Members + + + 3 + MC4zMzMzMzI5ODU2AA + + + + + 337772096 + 2048 + Text Cell + + User + + + + + 3 + YES + YES + + + + 3 + 2 + + + 17 + 1925185536 + + + 1 + 4 + 15 + 0 + YES + 0 + 1 + + + {{1, 17}, {140, 186}} + + + 2 + + + 4 + + + + -2147483392 + {{-100, -100}, {15, 102}} + + + + _doScroller: + 0.80769230769230771 + + + + -2147483392 + {{1, 119}, {223, 15}} + + + 1 + + _doScroller: + 0.97590361445783136 + + + + 2304 + + YES + + + {{1, 0}, {140, 17}} + + + 2 + + + 4 + + + {{0, 24}, {142, 204}} + + + 2 + 133682 + + + + + QSAAAEEgAABBmAAAQZgAAA + + {{161, 42}, {142, 228}} + + + 2 + _NS:9 + NSView 289 - {{161, 4}, {72, 28}} + {{236, 4}, {72, 28}} + 2 YES -2080244224 @@ -1321,9 +1558,10 @@ 289 - {{91, 4}, {72, 28}} + {{166, 4}, {72, 28}} + 2 YES -2080244224 @@ -1341,8 +1579,10 @@ - {{10, 33}, {245, 203}} - + {{10, 33}, {320, 273}} + + YES + 2 Groups @@ -1364,7 +1604,9 @@ 292 {{20, 19}, {20, 20}} + + 2 _NS:2510 YES @@ -1388,7 +1630,9 @@ 292 {{39, 19}, {20, 20}} + + 2 _NS:2510 YES @@ -1408,12 +1652,14 @@ - {425, 300} + {500, 370} + + 2 {{0, 0}, {1280, 778}} - {425, 284} + {500, 392} {10000000000000, 10000000000000} YES @@ -1501,22 +1747,6 @@ - login: - - - - 664 - - - - loginCancel: - - - - 685 - - - syncApply: @@ -1581,19 +1811,27 @@ - add: - - + retrieveToken: + + - 776 + 943 - remove: - - + authorizationCancel: + + - 777 + 944 + + + + authorizationSave: + + + + 945 @@ -1612,6 +1850,22 @@ 908 + + add: + + + + 776 + + + + remove: + + + + 777 + + contentDictionary: selection.value @@ -1785,26 +2039,24 @@ - value: serverURL + value: authURLString - value: serverURL + value: authURLString value - serverURL + authURLString YES YES - NSConditionallySetsEditable NSContinuouslyUpdatesValue NSValidatesImmediately YES - @@ -1812,7 +2064,27 @@ 2 - 679 + 1012 + + + + enabled: manual + + + + + + enabled: manual + enabled + manual + + NSValueTransformerName + NSNegateBoolean + + 2 + + + 1054 @@ -1828,7 +2100,7 @@ 2 - 598 + 1000 @@ -1857,23 +2129,7 @@ 2 - 674 - - - - enabled: manual - - - - - - enabled: manual - enabled - manual - 2 - - - 600 + 1017 @@ -1890,11 +2146,13 @@ YES YES + NSConditionallySetsEditable NSContinuouslyUpdatesValue NSValidatesImmediately YES + @@ -1902,7 +2160,7 @@ 2 - 675 + 1016 @@ -1916,29 +2174,38 @@ value manual - NSValidatesImmediately - + YES + + YES + NSConditionallySetsEnabled + NSValidatesImmediately + + + YES + + + 2 - 558 + 1019 - enabled: loginEnable + enabled: authorizationSaveEnable - enabled: loginEnable + enabled: authorizationSaveEnable enabled - loginEnable + authorizationSaveEnable 2 - 678 + 1006 @@ -1958,19 +2225,19 @@ - enabled: loginCancelEnable + enabled: authorizationCancelEnable - enabled: loginCancelEnable + enabled: authorizationCancelEnable enabled - loginCancelEnable + authorizationCancelEnable 2 - 688 + 1003 @@ -2076,64 +2343,47 @@ - - enabled: selection.active - enabled - selection.active - 2 - - - 853 - - - - content: arrangedObjects - - - - - - content: arrangedObjects - content - arrangedObjects + + enabled: selection.active + enabled + selection.active 2 - 791 + 853 - selectionIndexes: selectionIndexes + sortDescriptors: sortDescriptors - + - selectionIndexes: selectionIndexes - selectionIndexes - selectionIndexes - + sortDescriptors: sortDescriptors + sortDescriptors + sortDescriptors + 2 - 793 + 795 - sortDescriptors: sortDescriptors + content: arrangedObjects - + - sortDescriptors: sortDescriptors - sortDescriptors - sortDescriptors - + content: arrangedObjects + content + arrangedObjects 2 - 795 + 791 @@ -2153,6 +2403,23 @@ + selectionIndexes: selectionIndexes + + + + + + selectionIndexes: selectionIndexes + selectionIndexes + selectionIndexes + + 2 + + + 793 + + + value: arrangedObjects.key @@ -2182,22 +2449,6 @@ - content: arrangedObjects - - - - - - content: arrangedObjects - content - arrangedObjects - 2 - - - 781 - - - selectionIndexes: selectionIndexes @@ -2232,6 +2483,22 @@ + content: arrangedObjects + + + + + + content: arrangedObjects + content + arrangedObjects + 2 + + + 781 + + + enabled: selection.active @@ -2359,22 +2626,6 @@ - enabled: selection.active - - - - - - enabled: selection.active - enabled - selection.active - 2 - - - 834 - - - enabled2: canRemove @@ -2410,6 +2661,22 @@ enabled: selection.active + + + + + + enabled: selection.active + enabled + selection.active + 2 + + + 834 + + + + enabled: selection.active @@ -2525,317 +2792,795 @@ value: displayname value - displayname + displayname + + YES + + YES + NSContinuouslyUpdatesValue + NSValidatesImmediately + + + YES + + + + + 2 + + + 1018 + + + + enabled: manual + + + + + + enabled: manual + enabled + manual + 2 + + + 994 + + + + value: pithosObjectStoreURLString + + + + + + value: pithosObjectStoreURLString + value + pithosObjectStoreURLString + + YES + + YES + NSContinuouslyUpdatesValue + NSValidatesImmediately + + + YES + + + + + 2 + + + 1013 + + + + enabled: manual + + + + + + enabled: manual + enabled + manual + 2 + + + 996 + + + + value: astakosAccountURLString + + + + + + value: astakosAccountURLString + value + astakosAccountURLString + + YES + + YES + NSContinuouslyUpdatesValue + NSValidatesImmediately + + + YES + + + + + 2 + + + 1014 + + + + enabled: manual + + + + + + enabled: manual + enabled + manual + 2 + + + 1008 + + + + value: astakosWebloginURLString + + + + + + value: astakosWebloginURLString + value + astakosWebloginURLString + + YES + + YES + NSContinuouslyUpdatesValue + NSValidatesImmediately + + + YES + + + + + 2 + + + 1015 + + + + enabled: retrieveTokenEnable + + + + + + enabled: retrieveTokenEnable + enabled + retrieveTokenEnable + 2 + + + 987 + + + + value: ignoreSSLErrors + + + + + + value: ignoreSSLErrors + value + ignoreSSLErrors YES YES - NSConditionallySetsEditable - NSContinuouslyUpdatesValue + NSConditionallySetsEnabled NSValidatesImmediately YES - - + 2 - 905 + 1024 YES - 0 - + 0 + + YES + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 3 + + + YES + + + + + + 5 + + + YES + + + + + + + + + 505 + + + YES + + + + + + + + + 506 + + + YES + + + + + + 507 + + + + + 508 + + + + + 509 + + + + + 510 + + + YES + + + + + + 513 + + + + + 524 + + + YES + + + + + + + + 525 + + + YES + + + + + + 526 + + + YES + + + + + + 527 + + + YES + + + + + + + + + + + + + 528 + + + YES + + + + + + + + + + + + + + + + + + + + + + + + + + 529 + + + YES + + + + + + 530 + + + + + 531 + + + YES + + + + + + 532 + + + + + 533 + + + YES + + + + + + 534 + + + YES + + + + + + + + + 543 + + + YES + + + + Auth URL + + + 544 + + + + + 547 + + + YES + + + + + + 548 + + + + + 556 + + + YES + + + + + + 557 + + + + + 559 + + YES + - - + - -2 - + 560 + + + + + 433 + - File's Owner + Dictionary Controller (Selected Group Members) - -1 - + 396 + - First Responder + Dictionary Controller (Groups) - -3 - + 625 + - Application + Array Controller (Accounts) - 3 - + 680 + YES - + - + - 5 - + 681 + + + + + 689 + YES - - - - + - + - 505 - + 690 + + + + + 691 + YES - - - - + - + - 506 - + 692 + + + + + 702 + YES - + - + - 507 - - + 703 + + + YES + + + - 508 - - + 704 + + - 509 - - + 705 + + - 510 - + 719 + YES - + - + - 513 - - + 720 + + - 524 - + 768 + YES - - - + - + - 525 - + 769 + YES - + - + - 526 - + 770 + + + + + 771 + + + + + 866 + YES - + + + + - + - 527 - + 867 + + + + + 868 + + + + + 869 + + + + + 870 + YES - - - - - - - - + + - + - 528 - + 871 + YES - - - - - - - - - - - - - + - + - 529 - + 872 + YES - + - + - 530 - - + 873 + + - 531 - + 874 + + + + + 880 + YES - + - + - 532 - - + 881 + + + + + 888 + + + YES + + + + + + 889 + + - 533 - + 915 + YES - + - + - 534 - - - YES - - - - - - - - - - + 916 + + - 543 - + 917 + YES - + - Server - 544 - - + 918 + + - 547 - + 919 + YES - + - 548 - - + 920 + + - 323 - + 921 + YES - + + Pithos URL - 338 - - + 922 + + - 324 - + 924 + YES - + + Astakos URL - 337 - - + 925 + + - 326 - + 926 + YES - + + Weblogin URL - 335 - - + 927 + + 551 @@ -2843,237 +3588,156 @@ - 552 - + 324 + YES - + - User - 553 - - + 337 + + - 554 - + 323 + YES - + - Token - 555 - - + 338 + + - 556 - + 898 + YES - + - 557 - - + 899 + + - 559 - + 554 + YES - + + Token - 560 - - - - - 433 - - - Dictionary Controller (Selected Group Members) - - - 396 - - - Dictionary Controller (Groups) - - - 625 - - - Array Controller (Accounts) + 555 + + - 680 - + 552 + YES - + + UUID - 681 - - + 553 + + - 689 - + 894 + YES - + - + + User - 690 - - + 895 + + - 691 - + 928 + YES - + - + - 692 - - + 929 + + - 702 - - - YES - - - + 932 + + - 703 - + 933 + YES - + - - - - 704 - - + - 705 - - + 934 + + - 719 - + 1025 + YES - + + + - - - - 720 - - + 722 YES - - - + + + - - Scroll View - Table View - Metadata - - - 723 - - - YES - - - - - - + Scroll View - Table View - Metadata - 724 - - - YES - - - - - - 725 - - - - - 726 - - - - - 727 - - - - - 728 - + 733 + YES - + - - - - 729 - - - - - 730 - - - - - 731 - @@ -3082,12 +3746,13 @@ - 733 - - - YES - - + 731 + + + + + 730 + @@ -3111,7 +3776,12 @@ YES - + + + + 743 + + 737 @@ -3120,35 +3790,7 @@ YES - - - - 738 - - - YES - - - - - - 739 - - - YES - - - - - - 740 - - - - - 741 - - + 742 @@ -3156,159 +3798,94 @@ - 743 - - - - - 768 - - - YES - - - - - - 769 - + 1048 + YES - + + + - 770 - - - - - 771 - - - - - 866 - - - YES - - - - - - - - - 867 - - - - - 868 - - - - - 869 - - - - - 870 - - - YES - - - - - - - 871 - + 723 + YES - + + + + - + + Scroll View - Table View - Metadata - 872 - - - YES - - - + 727 + + - 873 - - + 726 + + - 874 - - + 725 + + - 880 - + 724 + YES - + - - - - 881 - - + - 888 - + 728 + YES - + - + - 889 - - + 729 + + - 894 - + 738 + YES - + - - Token + - 895 - - + 741 + + - 898 - + 739 + YES - + - + - 899 - - + 740 + + @@ -3319,13 +3896,17 @@ -1.IBPluginDependency -2.IBPluginDependency -3.IBPluginDependency + 1025.IBPluginDependency + 1025.IBViewIntegration.shadowBlurRadius + 1025.IBViewIntegration.shadowColor + 1025.IBViewIntegration.shadowOffsetHeight + 1025.IBViewIntegration.shadowOffsetWidth + 1048.IBPluginDependency 3.IBPluginDependency 3.IBWindowTemplateEditedContentRect 3.NSWindowTemplate.visibleAtLaunch 323.IBPluginDependency 324.IBPluginDependency - 326.IBPluginDependency - 335.IBPluginDependency 337.IBPluginDependency 338.IBPluginDependency 396.IBPluginDependency @@ -3419,6 +4000,23 @@ 895.IBPluginDependency 898.IBPluginDependency 899.IBPluginDependency + 915.IBPluginDependency + 916.IBPluginDependency + 917.IBPluginDependency + 918.IBPluginDependency + 919.IBPluginDependency + 920.IBPluginDependency + 921.IBPluginDependency + 922.IBPluginDependency + 924.IBPluginDependency + 925.IBPluginDependency + 926.IBPluginDependency + 927.IBPluginDependency + 928.IBPluginDependency + 929.IBPluginDependency + 932.IBPluginDependency + 933.IBPluginDependency + 934.IBPluginDependency YES @@ -3426,6 +4024,12 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin {{438, 560}, {520, 345}} com.apple.InterfaceBuilder.CocoaPlugin @@ -3470,9 +4074,24 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -3539,9 +4158,155 @@ - 914 + 1054 + + + + YES + + PithosPreferencesController + NSWindowController + + YES + + YES + addAccount: + authorizationCancel: + authorizationSave: + groupsApply: + groupsRevert: + removeAccount: + retrieveToken: + syncApply: + syncCancel: + syncRefresh: + + + YES + id + id + id + id + id + id + id + id + id + id + + + + YES + + YES + addAccount: + authorizationCancel: + authorizationSave: + groupsApply: + groupsRevert: + removeAccount: + retrieveToken: + syncApply: + syncCancel: + syncRefresh: + + + YES + + addAccount: + id + + + authorizationCancel: + id + + + authorizationSave: + id + + + groupsApply: + id + + + groupsRevert: + id + + + removeAccount: + id + + + retrieveToken: + id + + + syncApply: + id + + + syncCancel: + id + + + syncRefresh: + id + + + + + YES + + YES + accountsArrayController + groupsDictionaryController + selectedGroupMembersDictionaryController + syncAccountsOutlineView + + + YES + NSArrayController + NSDictionaryController + NSDictionaryController + NSOutlineView + + + + YES + + YES + accountsArrayController + groupsDictionaryController + selectedGroupMembersDictionaryController + syncAccountsOutlineView + + + YES + + accountsArrayController + NSArrayController + + + groupsDictionaryController + NSDictionaryController + + + selectedGroupMembersDictionaryController + NSDictionaryController + + + syncAccountsOutlineView + NSOutlineView + + + + + IBProjectSource + ./Classes/PithosPreferencesController.h + + + - 0 IBCocoaFramework diff --git a/pithos-macos/PithosSharingAccountsNode.m b/pithos-macos/PithosSharingAccountsNode.m index 76352d0..d5062e0 100644 --- a/pithos-macos/PithosSharingAccountsNode.m +++ b/pithos-macos/PithosSharingAccountsNode.m @@ -78,7 +78,7 @@ - (NSString *)url { if (url == nil) - url = [pithos.storageURLPrefix copy]; + url = [[pithos.storageURLPrefix description] copy]; return url; } @@ -217,7 +217,7 @@ for (ASIPithosAccount *account in sharingAccounts) { [sharingAccountsNames addObject:account.name]; } - [pithosAccountManager updateUserCatalogForForDisplaynames:nil UUIDs:sharingAccountsNames]; + [pithosAccountManager updateUserCatalogForDisplaynames:nil UUIDs:sharingAccountsNames]; self.sharingAccountsRequest = nil; forcedRefresh = NO; @synchronized(self) { diff --git a/pithos-macos/PithosSubdirNode.m b/pithos-macos/PithosSubdirNode.m index 7c3d513..378199f 100644 --- a/pithos-macos/PithosSubdirNode.m +++ b/pithos-macos/PithosSubdirNode.m @@ -92,7 +92,7 @@ static NSImage *sharedIcon = nil; if (displayname) { self.translatedModifiedBy = displayname; } else { - [pithosAccountManager updateUserCatalogForForDisplaynames:nil UUIDs:[NSArray arrayWithObject:pithosObject.modifiedBy]]; + [pithosAccountManager updateUserCatalogForDisplaynames:nil UUIDs:[NSArray arrayWithObject:pithosObject.modifiedBy]]; self.translatedModifiedBy = [pithosAccountManager displaynameForUUID:pithosObject.modifiedBy safe:YES]; } } else { @@ -111,7 +111,7 @@ static NSImage *sharedIcon = nil; [UUIDs removeObject:@""]; [UUIDs removeObject:@"*"]; if (UUIDs.count) { - [pithosAccountManager updateUserCatalogForForDisplaynames:nil UUIDs:[UUIDs allObjects]]; + [pithosAccountManager updateUserCatalogForDisplaynames:nil UUIDs:[UUIDs allObjects]]; } NSMutableArray *newTranslatedPermissions = [NSMutableArray arrayWithCapacity:pithosObject.permissions.count]; @@ -359,7 +359,7 @@ static NSImage *sharedIcon = nil; [allUsers removeObject:@""]; [allUsers removeObject:@"*"]; if (allUsers.count) { - ASIPithosRequest *userCatalogRequest = [pithosAccountManager updateUserCatalogForForDisplaynames:[allUsers allObjects] + ASIPithosRequest *userCatalogRequest = [pithosAccountManager updateUserCatalogForDisplaynames:[allUsers allObjects] UUIDs:nil]; if (userCatalogRequest.error || ((userCatalogRequest.responseStatusCode != 200) && (userCatalogRequest.responseStatusCode != 404))) { return; @@ -516,7 +516,7 @@ static NSImage *sharedIcon = nil; [allUsers removeObject:@""]; [allUsers removeObject:@"*"]; if (allUsers.count) { - ASIPithosRequest *userCatalogRequest = [pithosAccountManager updateUserCatalogForForDisplaynames:[allUsers allObjects] + ASIPithosRequest *userCatalogRequest = [pithosAccountManager updateUserCatalogForDisplaynames:[allUsers allObjects] UUIDs:nil]; if (userCatalogRequest.error || ((userCatalogRequest.responseStatusCode != 200) && (userCatalogRequest.responseStatusCode != 404))) { return; diff --git a/pithos-macos/PithosSyncDaemon.m b/pithos-macos/PithosSyncDaemon.m index 35675d7..937a48c 100644 --- a/pithos-macos/PithosSyncDaemon.m +++ b/pithos-macos/PithosSyncDaemon.m @@ -411,25 +411,27 @@ - (void)setPithos:(ASIPithos *)aPithos { if (!pithos) { pithos = [ASIPithos pithos]; - pithos.authUser = [aPithos.authUser copy]; pithos.authToken = [aPithos.authToken copy]; + pithos.authUser = [aPithos.authUser copy]; + pithos.ignoreSSLErrors = aPithos.ignoreSSLErrors; + pithos.tokensURL = [aPithos.tokensURL copy]; pithos.storageURLPrefix = [aPithos.storageURLPrefix copy]; - pithos.authURL = [aPithos.authURL copy]; pithos.publicURLPrefix = [aPithos.publicURLPrefix copy]; pithos.userCatalogURL = [aPithos.userCatalogURL copy]; } if (aPithos && (![aPithos.authUser isEqualToString:pithos.authUser] || - ![aPithos.authToken isEqualToString:pithos.authToken] || - ![aPithos.storageURLPrefix isEqualToString:pithos.storageURLPrefix])) { + ![aPithos.authToken isEqualToString:pithos.authToken] || + ![aPithos.storageURLPrefix isEqual:pithos.storageURLPrefix])) { [self resetDaemon]; if (![aPithos.authUser isEqualToString:pithos.authUser] || - ![aPithos.storageURLPrefix isEqualToString:pithos.storageURLPrefix]) + ![aPithos.storageURLPrefix isEqual:pithos.storageURLPrefix]) [self resetLocalStateWithAll:YES]; - pithos.authUser = [aPithos.authUser copy]; pithos.authToken = [aPithos.authToken copy]; + pithos.authUser = [aPithos.authUser copy]; + pithos.ignoreSSLErrors = aPithos.ignoreSSLErrors; + pithos.tokensURL = [aPithos.tokensURL copy]; pithos.storageURLPrefix = [aPithos.storageURLPrefix copy]; - pithos.authURL = [aPithos.authURL copy]; pithos.publicURLPrefix = [aPithos.publicURLPrefix copy]; pithos.userCatalogURL = [aPithos.userCatalogURL copy]; } @@ -552,7 +554,7 @@ return; } // Update user catalog for accountsNames. - ASIPithosRequest *userCatalogRequest = [pithosAccount updateUserCatalogForForDisplaynames:nil UUIDs:accountsNames]; + ASIPithosRequest *userCatalogRequest = [pithosAccount updateUserCatalogForDisplaynames:nil UUIDs:accountsNames]; if (userCatalogRequest.error || ((userCatalogRequest.responseStatusCode != 200) && (userCatalogRequest.responseStatusCode != 404))) { // Update failed try sync again later. [self syncOperationFinishedWithSuccess:NO]; diff --git a/pithos-macos/PublicURLTransformer.m b/pithos-macos/PublicURLTransformer.m index 6dc78fa..3838d40 100644 --- a/pithos-macos/PublicURLTransformer.m +++ b/pithos-macos/PublicURLTransformer.m @@ -54,8 +54,11 @@ - (id)transformedValue:(id)value { if (value == nil) return nil; - return [[[[(pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate] currentPithosAccount] pithos] publicURLPrefix] - stringByAppendingString:(NSString *)value]; + NSString *publicURLString = (NSString *)value; + if ([publicURLString hasPrefix:@"https://"] || [publicURLString hasPrefix:@"http://"]) + return publicURLString; + return [[[[(pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate] currentPithosAccount] pithos] publicURLPrefix] + stringByAppendingString:publicURLString]; } + (void)initialize { diff --git a/pithos-macos/pithos_macosAppDelegate.m b/pithos-macos/pithos_macosAppDelegate.m index 95d22ae..14b5370 100644 --- a/pithos-macos/pithos_macosAppDelegate.m +++ b/pithos-macos/pithos_macosAppDelegate.m @@ -42,6 +42,7 @@ #import "PithosSyncDaemon.h" #import "ASIPithosRequest.h" #import "ASIPithos.h" +#import "PithosUtilities.h" #import "LastCompletedSyncTransformer.h" @implementation pithos_macosAppDelegate @@ -96,8 +97,15 @@ currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccoun pithosAccountsDictionary = [[NSMutableDictionary alloc] initWithCapacity:[pithosAccounts count]]; for (PithosAccount *pithosAccount in pithosAccounts) { [pithosAccountsDictionary setObject:pithosAccount forKey:pithosAccount.name]; - if (!currentPithosAccount && pithosAccount.active) - self.currentPithosAccount = pithosAccount; + if (pithosAccount.active) { + if (!pithosAccount.manual) { + ASIPithosRequest *serviceCatalogRequest = [ASIPithosRequest serviceCatalogRequestWithPithos:pithosAccount.pithos]; + [PithosUtilities startAndWaitForRequest:serviceCatalogRequest]; + [pithosAccount updateServicesFromServiceCatalogRequest:serviceCatalogRequest]; + } + if (!currentPithosAccount) + self.currentPithosAccount = pithosAccount; + } } if (!currentPithosAccount) self.currentPithosAccount = [pithosAccounts objectAtIndex:0]; @@ -153,30 +161,31 @@ currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccoun NSProcessInfo *processInfo = [NSProcessInfo processInfo]; if ([host isEqualToString:[NSString stringWithFormat:@"%d", [processInfo processIdentifier]]] && pithosAccount && query) { // user= - NSString *authUser; + // optional + NSString *authUser = nil; NSRange userRange = [query rangeOfString:@"user=" options:NSCaseInsensitiveSearch]; - if (userRange.length == 0) - // XXX maybe show an error message? - return; - NSUInteger authUserStartLocation = userRange.location + userRange.length; - NSRange userEndRange = [query rangeOfString:@"&" options:NSCaseInsensitiveSearch - range:NSMakeRange(authUserStartLocation, [query length] - authUserStartLocation)]; - if (userEndRange.length) { - authUser = [[query substringWithRange:NSMakeRange(authUserStartLocation, userEndRange.location - authUserStartLocation)] - stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - } else { - authUser = [[query substringFromIndex:authUserStartLocation] - stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + if (userRange.length) { + NSUInteger authUserStartLocation = userRange.location + userRange.length; + NSRange userEndRange = [query rangeOfString:@"&" options:NSCaseInsensitiveSearch + range:NSMakeRange(authUserStartLocation, [query length] - authUserStartLocation)]; + if (userEndRange.length) { + authUser = [[query substringWithRange:NSMakeRange(authUserStartLocation, userEndRange.location - authUserStartLocation)] + stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + } else { + authUser = [[query substringFromIndex:authUserStartLocation] + stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + } } // token= - NSString *authToken; + // required + NSString *authToken = nil; NSRange tokenRange = [query rangeOfString:@"token=" options:NSCaseInsensitiveSearch]; if (tokenRange.length == 0) // XXX maybe show an error message? return; NSUInteger authTokenStartLocation = tokenRange.location + tokenRange.length; - NSRange tokenEndRange = [query rangeOfString:@"&" options:NSCaseInsensitiveSearch - range:NSMakeRange(authTokenStartLocation, [query length] - authTokenStartLocation)]; + NSRange tokenEndRange = [query rangeOfString:@"&" options:NSCaseInsensitiveSearch + range:NSMakeRange(authTokenStartLocation, [query length] - authTokenStartLocation)]; if (tokenEndRange.length) { authToken = [[query substringWithRange:NSMakeRange(authTokenStartLocation, tokenEndRange.location - authTokenStartLocation)] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; @@ -186,17 +195,11 @@ currentPithosAccount, pithosAccounts, pithosAccountsDictionary, syncPithosAccoun } DLog(@"query authUser: '%@', authToken: '%@'", authUser, authToken); - if ([authUser length] && [authToken length]) { - [pithosAccount authenticateWithServerURL:nil authUser:authUser authToken:authToken]; - [self savePithosAccounts:self]; + if (authToken || authUser) { if (self.pithosPreferencesController && [self.pithosPreferencesController.selectedPithosAccount isEqualTo:pithosAccount]) { - self.pithosPreferencesController.authUser = pithosAccount.authUser; - self.pithosPreferencesController.authToken = pithosAccount.authToken; - } - self.activated = YES; - if ([pithosAccount isEqualTo:currentPithosAccount]) { - [self showPithosBrowser:self]; - self.pithosBrowserController.pithos = pithosAccount.pithos; + self.pithosPreferencesController.authToken = authToken; + self.pithosPreferencesController.authUser = authUser; + [self showPithosPreferences:self]; } } // XXX else maybe show an error message? -- 1.7.10.4