#import "pithos_macosAppDelegate.h"
#import "PithosBrowserController.h"
+#import "PithosPreferencesController.h"
+#import "PithosSyncDaemon.h"
+#import "ASIPithosRequest.h"
+#import "ASIDownloadCache.h"
@implementation pithos_macosAppDelegate
-@synthesize pithosBrowserController;
+@synthesize storageURLPrefix, publicURLPrefix, loginURLPrefix, aboutURL;
+@synthesize syncContainerName, syncTimeInterval, pithosBrowserController, pithosSyncDaemon, alwaysNo;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
- [pithosBrowserController showWindow:self];
+ NSURL *testURL;
+ storageURLPrefix = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"PithosStorageURLPrefix"];
+ if (!storageURLPrefix) {
+ storageURLPrefix = [NSString stringWithString:@"https://pithos.dev.grnet.gr/v1"];
+ } else {
+ testURL = [NSURL URLWithString:storageURLPrefix];
+ if (!testURL || !testURL.scheme || !testURL.host)
+ storageURLPrefix = [NSString stringWithString:@"https://pithos.dev.grnet.gr/v1"];
+ }
+ [storageURLPrefix retain];
+
+ publicURLPrefix = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"PithosPublicURLPrefix"];
+ if (!publicURLPrefix) {
+ publicURLPrefix = [NSString stringWithString:@"https://pithos.dev.grnet.gr"];
+ } else {
+ testURL = [NSURL URLWithString:publicURLPrefix];
+ if (!testURL || !testURL.scheme || !testURL.host)
+ publicURLPrefix = [NSString stringWithString:@"https://pithos.dev.grnet.gr"];
+ }
+ [publicURLPrefix retain];
+
+ loginURLPrefix = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"PithosLoginURLPrefix"];
+ if (!loginURLPrefix) {
+ loginURLPrefix = [NSString stringWithString:@"https://pithos.dev.grnet.gr/login"];
+ } else {
+ testURL = [NSURL URLWithString:loginURLPrefix];
+ if (!testURL || !testURL.scheme || !testURL.host)
+ loginURLPrefix = [NSString stringWithString:@"https://pithos.dev.grnet.gr/login"];
+ }
+ [loginURLPrefix retain];
+
+ aboutURL = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"PithosAboutURL"];
+ if (!aboutURL) {
+ aboutURL = [NSString stringWithString:@"https://pithos.dev.grnet.gr/docs"];
+ } else {
+ testURL = [NSURL URLWithString:aboutURL];
+ if (!testURL || !testURL.scheme || !testURL.host)
+ aboutURL = [NSString stringWithString:@"https://pithos.dev.grnet.gr/docs"];
+ }
+ [aboutURL retain];
+
+ NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+ NSString *syncDirectoryPath = [userDefaults stringForKey:@"pithosSyncDirectoryPath"];
+ if (!syncDirectoryPath || ![syncDirectoryPath length]) {
+ syncDirectoryPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"Pithos"];
+ } else {
+ NSFileManager *fileManager = [NSFileManager defaultManager];
+ BOOL isDirectory;
+ BOOL fileExists = [fileManager fileExistsAtPath:syncDirectoryPath isDirectory:&isDirectory];
+ NSError *error = nil;
+ if ((fileExists && !isDirectory) ||
+ (!fileExists && (![fileManager createDirectoryAtPath:syncDirectoryPath withIntermediateDirectories:YES attributes:nil error:&error] || error))) {
+ syncDirectoryPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"Pithos"];
+ }
+ }
+ [userDefaults setObject:syncDirectoryPath forKey:@"pithosSyncDirectoryPath"];
+ [userDefaults synchronize];
+
+ syncContainerName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"PithosSyncContainerName"];
+ if (!syncContainerName || ![syncContainerName length] || [syncContainerName isEqualToString:@"trash"]) {
+ syncContainerName = [NSString stringWithString:@"pithos"];
+ }
+ [syncContainerName retain];
+
+ syncTimeInterval = [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"PithosSyncTimeInterval"] doubleValue];
+ if (syncTimeInterval <= 0) {
+ syncTimeInterval = 180.0;
+ }
+
+ [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self
+ andSelector:@selector(handleAppleEvent:withReplyEvent:)
+ forEventClass:kInternetEventClass
+ andEventID:kAEGetURL];
+ [self showPithosBrowser:self];
+
+ [self authenticate];
+}
+
+// Based on: http://cocoatutorial.grapewave.com/2010/01/creating-a-status-bar-application/
+// and: http://www.cocoadev.com/index.pl?ThumbnailImages
+- (void)awakeFromNib {
+ NSImage *sourceImage = [NSImage imageNamed:@"pithos-large.png"];
+
+ NSImage *smallImage = [[[NSImage alloc] initWithSize:NSMakeSize(18, 18)] autorelease];
+ [smallImage lockFocus];
+ [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
+ [sourceImage setSize:NSMakeSize(18, 18)];
+ [sourceImage compositeToPoint:NSZeroPoint operation:NSCompositeCopy];
+ [smallImage unlockFocus];
+
+ statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
+ [statusItem setMenu:statusMenu];
+ [statusItem setImage:sourceImage];
+ [statusItem setHighlightMode:YES];
+
+ self.alwaysNo = NO;
+}
+
+- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent {
+ NSURL *url = [NSURL URLWithString:[[event paramDescriptorForKeyword:keyDirectObject] stringValue]];
+ NSString *host = [url host];
+ NSString *query = [url query];
+ NSLog(@"host : '%@', query: '%@'", host, query);
+ NSProcessInfo *processInfo = [NSProcessInfo processInfo];
+ if ([host isEqualToString:[NSString stringWithFormat:@"%@_%d", [processInfo processName], [processInfo processIdentifier]]] && query) {
+ // user=
+ NSString *authUser;
+ 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];
+ }
+ // token=
+ NSString *authToken;
+ 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)];
+ if (tokenEndRange.length) {
+ authToken = [[query substringWithRange:NSMakeRange(authTokenStartLocation, tokenEndRange.location - authTokenStartLocation)]
+ stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+ } else {
+ authToken = [[query substringFromIndex:authTokenStartLocation]
+ stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+ }
+
+ NSLog(@"query authUser: '%@', authToken: '%@'", authUser, authToken);
+ if ([authUser length] && [authToken length]) {
+ NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+ [userDefaults setObject:authUser forKey:@"authUser"];
+ [userDefaults setObject:authToken forKey:@"authToken"];
+ [userDefaults synchronize];
+
+ [self authenticate];
+ }
+ // XXX else maybe show an error message?
+ }
+ // XXX else maybe show an error message?
+}
+
+#pragma mark -
+#pragma Actions
+
+- (IBAction)showPithosBrowser:(id)sender {
+ [pithosBrowserController showWindow:sender];
+ [[pithosBrowserController window] makeKeyAndOrderFront:sender];
+ [NSApp activateIgnoringOtherApps:YES];
+}
+
+- (IBAction)showPithosPreferences:(id)sender {
+ [pithosPreferencesController showWindow:sender];
+ [[pithosPreferencesController window] makeKeyAndOrderFront:sender];
+ [NSApp activateIgnoringOtherApps:YES];
+}
+
+- (IBAction)aboutPithos:(id)sender {
+ [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:self.aboutURL]];
+}
+
+- (IBAction)syncNow:(id)sender {
+ [pithosSyncDaemon sync];
+}
+
+#pragma mark -
+#pragma Authentication
+
+- (void)authenticate {
+ NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+ NSString *authUser = [userDefaults stringForKey:@"authUser"];
+ NSString *authToken = [userDefaults stringForKey:@"authToken"];
+ NSString *syncDirectoryPath = [userDefaults stringForKey:@"pithosSyncDirectoryPath"];
+ NSLog(@"Authentication - storageURLPrefix:%@, authUser:%@, authToken:%@", storageURLPrefix, authUser, authToken);
+ if (([authUser length] == 0) || ([authToken length] == 0)) {
+ [self showPithosPreferences:self];
+ } else if ([authUser length] && [authToken length] &&
+ (![[ASIPithosRequest authUser] isEqualToString:authUser] || ![[ASIPithosRequest authToken] isEqualToString:authToken])) {
+ [[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
+ [[ASIPithosRequest sharedQueue] cancelAllOperations];
+
+ [ASIPithosRequest setAuthURL:storageURLPrefix];
+ [ASIPithosRequest setStorageURLPrefix:storageURLPrefix];
+ [ASIPithosRequest setAuthUser:authUser];
+ [ASIPithosRequest setAuthToken:authToken];
+ [ASIPithosRequest setPublicURLPrefix:publicURLPrefix];
+
+ self.pithosSyncDaemon = [[[PithosSyncDaemon alloc] initWithDirectoryPath:syncDirectoryPath
+ containerName:syncContainerName
+ timeInterval:syncTimeInterval
+ resetLocalState:NO] autorelease];
+
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"PithosAuthenticationCredentialsUpdated" object:self];
+ } else if (![pithosSyncDaemon.directoryPath isEqualToString:syncDirectoryPath]) {
+ self.pithosSyncDaemon = [[[PithosSyncDaemon alloc] initWithDirectoryPath:syncDirectoryPath
+ containerName:syncContainerName
+ timeInterval:syncTimeInterval
+ resetLocalState:YES] autorelease];
+ }
}
@end