X-Git-Url: https://code.grnet.gr/git/pithos-macos/blobdiff_plain/d366080489546209e3b296b8f867404d5c851701..f09ca4182985cad9c54c8290c0dacdee6e5862d8:/pithos-macos/PithosUtilities.m diff --git a/pithos-macos/PithosUtilities.m b/pithos-macos/PithosUtilities.m index da1a2a9..d48928a 100644 --- a/pithos-macos/PithosUtilities.m +++ b/pithos-macos/PithosUtilities.m @@ -70,12 +70,15 @@ NSString *destinationPath = [directoryPath stringByAppendingPathComponent:fileName]; if (ifExists && [fileManager fileExistsAtPath:destinationPath]) { - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"File Exists"]; - [alert setInformativeText:[NSString stringWithFormat:@"A file or directory named '%@' already exists, do you want to replace it?", fileName]]; - [alert addButtonWithTitle:@"OK"]; - [alert addButtonWithTitle:@"Cancel"]; - NSInteger choice = [alert runModal]; + __block NSInteger choice; + dispatch_sync(dispatch_get_main_queue(), ^{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"File Exists"]; + [alert setInformativeText:[NSString stringWithFormat:@"A file or directory named '%@' already exists, do you want to replace it?", fileName]]; + [alert addButtonWithTitle:@"OK"]; + [alert addButtonWithTitle:@"Cancel"]; + choice = [alert runModal]; + }); if (choice == NSAlertSecondButtonReturn) return nil; } @@ -89,12 +92,15 @@ [fileManager removeItemAtPath:directoryPath error:&error]; } if (error) { - NSLog(@"Cannot remove existing file '%@': %@", fileName, error); - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"Removal Error"]; - [alert setInformativeText:[NSString stringWithFormat:@"Cannot remove existing file '%@': %@", fileName, error]]; - [alert addButtonWithTitle:@"OK"]; - [alert runModal]; + DLog(@"Cannot remove existing file '%@': %@", fileName, error); + dispatch_async(dispatch_get_main_queue(), ^{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Removal Error"]; + [alert setInformativeText:[NSString stringWithFormat:@"Cannot remove existing file '%@': %@", + fileName, [error localizedDescription]]]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + }); return nil; } @@ -122,12 +128,15 @@ NSString *subdirName = [objectName lastPathComponent]; NSString *destinationPath = [directoryPath stringByAppendingPathComponent:subdirName]; if (ifExists && [[NSFileManager defaultManager] fileExistsAtPath:destinationPath]) { - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"File exists"]; - [alert setInformativeText:[NSString stringWithFormat:@"A file or directory named '%@' already exists, do you want to replace it?", subdirName]]; - [alert addButtonWithTitle:@"OK"]; - [alert addButtonWithTitle:@"Cancel"]; - NSInteger choice = [alert runModal]; + __block NSInteger choice; + dispatch_sync(dispatch_get_main_queue(), ^{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"File exists"]; + [alert setInformativeText:[NSString stringWithFormat:@"A file or directory named '%@' already exists, do you want to replace it?", subdirName]]; + [alert addButtonWithTitle:@"OK"]; + [alert addButtonWithTitle:@"Cancel"]; + choice = [alert runModal]; + }); if (choice == NSAlertSecondButtonReturn) return nil; } @@ -144,13 +153,15 @@ NSError *error = nil; [fileManager createDirectoryAtPath:[directoryPath stringByAppendingPathComponent:subdirName] withIntermediateDirectories:YES attributes:nil error:&error]; if (error) { - NSLog(@"Cannot create directory at '%@': %@", directoryPath, error); - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"Create Directory Error"]; - [alert setInformativeText:[NSString stringWithFormat:@"Cannot create directory at '%@': %@", - directoryPath, error]]; - [alert addButtonWithTitle:@"OK"]; - [alert runModal]; + DLog(@"Cannot create directory at '%@': %@", directoryPath, error); + dispatch_async(dispatch_get_main_queue(), ^{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Create Directory Error"]; + [alert setInformativeText:[NSString stringWithFormat:@"Cannot create directory at '%@': %@", + directoryPath, [error localizedDescription]]]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + }); } for (ASIPithosObject *object in objects) { @@ -164,24 +175,28 @@ if (!directoryExists) { [fileManager createDirectoryAtPath:subdirDirectoryPath withIntermediateDirectories:YES attributes:nil error:&error]; if (error) { - NSLog(@"Cannot create directory at '%@': %@", subdirDirectoryPath, error); - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"Create Directory Error"]; - [alert setInformativeText:[NSString stringWithFormat:@"Cannot create directory at '%@': %@", - subdirDirectoryPath, error]]; - [alert addButtonWithTitle:@"OK"]; - [alert runModal]; + DLog(@"Cannot create directory at '%@': %@", subdirDirectoryPath, error); + dispatch_async(dispatch_get_main_queue(), ^{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Create Directory Error"]; + [alert setInformativeText:[NSString stringWithFormat:@"Cannot create directory at '%@': %@", + subdirDirectoryPath, [error localizedDescription]]]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + }); } } else if (!directoryIsDirectory) { [fileManager removeItemAtPath:subdirDirectoryPath error:&error]; if (error) { - NSLog(@"Cannot remove existing file at '%@': %@", subdirDirectoryPath, error); - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"Remove File Error"]; - [alert setInformativeText:[NSString stringWithFormat:@"Cannot remove existing file at '%@': %@", - subdirDirectoryPath, error]]; - [alert addButtonWithTitle:@"OK"]; - [alert runModal]; + DLog(@"Cannot remove existing file at '%@': %@", subdirDirectoryPath, error); + dispatch_async(dispatch_get_main_queue(), ^{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Remove File Error"]; + [alert setInformativeText:[NSString stringWithFormat:@"Cannot remove existing file at '%@': %@", + subdirDirectoryPath, [error localizedDescription]]]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + }); } } } else { @@ -321,15 +336,17 @@ strcpy(tempFileNameCString, tempFileTemplateCString); int fileDescriptor = mkstemp(tempFileNameCString); NSString *tempFilePath = [fileManager stringWithFileSystemRepresentation:tempFileNameCString length:strlen(tempFileNameCString)]; + free(tempFileNameCString); if (fileDescriptor == -1) { - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"Create Temporary File Error"]; - [alert setInformativeText:[NSString stringWithFormat:@"Cannot create temporary file at '%@'", tempFilePath]]; - [alert addButtonWithTitle:@"OK"]; - [alert runModal]; + dispatch_async(dispatch_get_main_queue(), ^{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Create Temporary File Error"]; + [alert setInformativeText:[NSString stringWithFormat:@"Cannot create temporary file at '%@'", tempFilePath]]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + }); return nil; } - free(tempFileNameCString); NSFileHandle *tempFileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fileDescriptor closeOnDealloc:YES]; [missingBlocks enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop){ @@ -392,12 +409,14 @@ NSError *error = nil; NSArray *subPaths = [fileManager subpathsOfDirectoryAtPath:directoryPath error:&error]; if (error) { - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"Directory Read Error"]; - [alert setInformativeText:[NSString stringWithFormat:@"Cannot read contents of directory '%@': %@", - [directoryPath lastPathComponent], error]]; - [alert addButtonWithTitle:@"OK"]; - [alert runModal]; + dispatch_async(dispatch_get_main_queue(), ^{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Directory Read Error"]; + [alert setInformativeText:[NSString stringWithFormat:@"Cannot read contents of directory '%@': %@", + [directoryPath lastPathComponent], [error localizedDescription]]]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + }); return nil; } @@ -439,7 +458,7 @@ if (!isDirectory) { hashes = [HashMapHash objectHashMapStrings:filePath withBlockHash:blockHash andBlockSize:blockSize]; if (hashes) { - subObjectName = [objectName stringByAppendingPathComponent:objectNameSuffix]; + subObjectName = [[objectName stringByAppendingPathComponent:objectNameSuffix] precomposedStringWithCanonicalMapping]; fileName = [filePath lastPathComponent]; if ([filePath hasSuffix:@"/"]) fileName = [fileName stringByAppendingString:@"/"]; @@ -448,8 +467,10 @@ contentType = [self contentTypeOfFile:filePath error:&error]; if (contentType == nil) contentType = @"application/octet-stream"; + #if DEBUG_PITHOS if (error) - NSLog(@"contentType detection error: %@", error); + DLog(@"contentType detection error: %@", error); + #endif objectRequest = [ASIPithosObjectRequest writeObjectDataRequestWithPithos:pithos containerName:containerName objectName:subObjectName @@ -478,7 +499,7 @@ } } else { - subObjectName = [objectName stringByAppendingPathComponent:objectNameSuffix]; + subObjectName = [[objectName stringByAppendingPathComponent:objectNameSuffix] precomposedStringWithCanonicalMapping]; fileName = [filePath lastPathComponent]; objectRequest = [ASIPithosObjectRequest writeObjectDataRequestWithPithos:pithos containerName:containerName @@ -545,7 +566,7 @@ #pragma mark - #pragma mark Copy -+ (ASIPithosObjectRequest *)copyObjectRequestWithPithos:(ASIPithos *)pithos ++ (ASIPithosObjectRequest *)cpyObjectRequestWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName destinationContainerName:(NSString *)destinationContainerName @@ -556,7 +577,7 @@ sharingAccount:nil]) return nil; - ASIPithosObjectRequest *objectRequest = [ASIPithosObjectRequest copyObjectDataRequestWithPithos:pithos + ASIPithosObjectRequest *objectRequest = [ASIPithosObjectRequest cpyObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName contentType:nil @@ -581,7 +602,7 @@ return objectRequest; } -+ (NSArray *)copyObjectRequestsForSubdirWithPithos:(ASIPithos *)pithos ++ (NSArray *)cpyObjectRequestsForSubdirWithPithos:(ASIPithos *)pithos containerName:(NSString *)containerName objectName:(NSString *)objectName destinationContainerName:(NSString *)destinationContainerName @@ -601,7 +622,7 @@ ASIPithosObjectRequest *objectRequest; if ([objectName isEqualToString:destinationObjectName]) { if (![objectName hasSuffix:@"/"]) { - objectRequest = [ASIPithosObjectRequest copyObjectDataRequestWithPithos:pithos + objectRequest = [ASIPithosObjectRequest cpyObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName contentType:nil @@ -626,7 +647,7 @@ [objectRequests addObject:objectRequest]; } for (ASIPithosObject *object in objects) { - objectRequest = [ASIPithosObjectRequest copyObjectDataRequestWithPithos:pithos + objectRequest = [ASIPithosObjectRequest cpyObjectDataRequestWithPithos:pithos containerName:containerName objectName:object.name contentType:nil @@ -652,7 +673,7 @@ } } else { if (![objectName hasSuffix:@"/"]) { - objectRequest = [ASIPithosObjectRequest copyObjectDataRequestWithPithos:pithos + objectRequest = [ASIPithosObjectRequest cpyObjectDataRequestWithPithos:pithos containerName:containerName objectName:objectName contentType:nil @@ -683,7 +704,7 @@ withString:destinationObjectName options:NSAnchoredSearch range:prefixRange]; - objectRequest = [ASIPithosObjectRequest copyObjectDataRequestWithPithos:pithos + objectRequest = [ASIPithosObjectRequest cpyObjectDataRequestWithPithos:pithos containerName:containerName objectName:object.name contentType:nil @@ -905,9 +926,11 @@ if (uti != NULL) { CFStringRef MIMEType = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType); CFRelease(uti); - return (NSString *)MIMEType; + CFRelease(url); + return (__bridge_transfer NSString *)MIMEType; } } + CFRelease(url); return nil; } @@ -923,8 +946,8 @@ return YES; } -// Removes contents of a directory -+ (void)removeContentsAtPath:(NSString *)dirPath { +// Removes contents of a directory and the directory itself if selected ++ (void)removeContentsAtPath:(NSString *)dirPath andDirectory:(BOOL)removeDirectory { NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error = nil; BOOL isDirectory; @@ -946,6 +969,11 @@ } error = nil; } + if (removeDirectory && (![fileManager removeItemAtPath:dirPath error:&error] || error)) { + [self fileActionFailedAlertWithTitle:@"Remove Directory Error" + message:[NSString stringWithFormat:@"Cannot remove directory at '%@'", dirPath] + error:error]; + } } else if (![fileManager removeItemAtPath:dirPath error:&error] || error) { [self fileActionFailedAlertWithTitle:@"Remove File Error" message:[NSString stringWithFormat:@"Cannot remove file at '%@'", dirPath] @@ -953,6 +981,11 @@ } } +// Removes contents of a directory ++ (void)removeContentsAtPath:(NSString *)dirPath { + [self removeContentsAtPath:dirPath andDirectory:NO]; +} + // Returns if an object is a directory based on its content type + (BOOL)isContentTypeDirectory:(NSString *)contentType { return ([contentType isEqualToString:@"application/directory"] || @@ -970,16 +1003,16 @@ objectName:objectName]; if (sharingAccount) [objectRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithos]; - ASINetworkQueue *networkQueue = [ASINetworkQueue queue]; - [networkQueue go]; - [networkQueue addOperations:[NSArray arrayWithObject:[self prepareRequest:objectRequest]] waitUntilFinished:YES]; - *error = [objectRequest error]; - if (*error) { - [self httpRequestErrorAlertWithRequest:objectRequest]; - return NO; - } else if (objectRequest.responseStatusCode == 200) { - *isDirectory = [self isContentTypeDirectory:[objectRequest contentType]]; - return YES; + [self startAndWaitForRequest:objectRequest]; + if (error != NULL) { + *error = [objectRequest error]; + if (*error) { + [self httpRequestErrorAlertWithRequest:objectRequest]; + return NO; + } else if (objectRequest.responseStatusCode == 200) { + *isDirectory = [self isContentTypeDirectory:[objectRequest contentType]]; + return YES; + } } return NO; } @@ -995,23 +1028,26 @@ if (error) { return NO; } else if (objectExists) { - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - if (isDirectory) { - [alert setMessageText:@"Directory Exists"]; - if (sharingAccount) - [alert setInformativeText:[NSString stringWithFormat:@"A directory with path '%@' in the container '%@' of user '%@' already exists, do you want to replace it?", objectName, containerName, sharingAccount]]; - else - [alert setInformativeText:[NSString stringWithFormat:@"A directory with path '%@' in the container '%@' already exists, do you want to replace it?", objectName, containerName]]; - } else { - [alert setMessageText:@"Object Exists"]; - if (sharingAccount) - [alert setInformativeText:[NSString stringWithFormat:@"An object with path '%@' in the container '%@' of user '%@' already exists, do you want to replace it?", objectName, containerName, sharingAccount]]; - else - [alert setInformativeText:[NSString stringWithFormat:@"An object with path '%@' in the container '%@' already exists, do you want to replace it?", objectName, containerName]]; - } - [alert addButtonWithTitle:@"OK"]; - [alert addButtonWithTitle:@"Cancel"]; - NSInteger choice = [alert runModal]; + __block NSInteger choice; + dispatch_sync(dispatch_get_main_queue(), ^{ + NSAlert *alert = [[NSAlert alloc] init]; + if (isDirectory) { + [alert setMessageText:@"Directory Exists"]; + if (sharingAccount) + [alert setInformativeText:[NSString stringWithFormat:@"A directory with path '%@' in the container '%@' of user '%@' already exists, do you want to replace it?", objectName, containerName, sharingAccount]]; + else + [alert setInformativeText:[NSString stringWithFormat:@"A directory with path '%@' in the container '%@' already exists, do you want to replace it?", objectName, containerName]]; + } else { + [alert setMessageText:@"Object Exists"]; + if (sharingAccount) + [alert setInformativeText:[NSString stringWithFormat:@"An object with path '%@' in the container '%@' of user '%@' already exists, do you want to replace it?", objectName, containerName, sharingAccount]]; + else + [alert setInformativeText:[NSString stringWithFormat:@"An object with path '%@' in the container '%@' already exists, do you want to replace it?", objectName, containerName]]; + } + [alert addButtonWithTitle:@"OK"]; + [alert addButtonWithTitle:@"Cancel"]; + choice = [alert runModal]; + }); if (choice == NSAlertSecondButtonReturn) return NO; } @@ -1036,9 +1072,7 @@ until:nil]; if (sharingAccount) [containerRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithos]; - ASINetworkQueue *networkQueue = [ASINetworkQueue queue]; - [networkQueue go]; - [networkQueue addOperations:[NSArray arrayWithObject:[self prepareRequest:containerRequest]] waitUntilFinished:YES]; + [self startAndWaitForRequest:containerRequest]; if ([containerRequest error]) { [self httpRequestErrorAlertWithRequest:containerRequest]; return nil; @@ -1077,7 +1111,7 @@ objectNameExtraSuffix = [objectName substringFromIndex:lastDotRange.location]; } else if ([objectName hasSuffix:@"/"]) { objectNamePrefix = [objectName substringToIndex:([objectName length] - 1)]; - objectNameExtraSuffix = [NSString stringWithString:@"/"]; + objectNameExtraSuffix = @"/"; } else { objectNamePrefix = [NSString stringWithString:objectName]; objectNameExtraSuffix = [NSString string]; @@ -1124,7 +1158,7 @@ NSString *subdirNameExtraSuffix; if ([subdirName hasSuffix:@"/"]) { subdirNamePrefix = [subdirName substringToIndex:([subdirName length] - 1)]; - subdirNameExtraSuffix = [NSString stringWithString:@"/"]; + subdirNameExtraSuffix = @"/"; } else { subdirNamePrefix = [NSString stringWithString:subdirName]; subdirNameExtraSuffix = [NSString string]; @@ -1165,24 +1199,36 @@ #pragma mark - #pragma mark Alerts -+ (NSInteger)httpRequestErrorAlertWithRequest:(ASIPithosRequest *)request { ++ (void)httpRequestErrorAlertWithRequest:(ASIPithosRequest *)request { + if (request.responseStatusCode == 401) { + [self httpAuthenticationError]; + return; + } NSString *message = [NSString stringWithFormat: @"HTTP request error: %@\n%@ URL: %@\nRequest Headers: %@\nResponse Headers: %@\nResponse String: %@", - [request error], + [[request error] localizedDescription], request.requestMethod, request.url, [request requestHeaders], [request responseHeaders], [request responseString]]; - NSLog(@"%@", message); - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"HTTP Request Error"]; - [alert setInformativeText:message]; - [alert addButtonWithTitle:@"OK"]; - return [alert runModal]; + DLog(@"%@", message); + dispatch_async(dispatch_get_main_queue(), ^{ + @autoreleasepool { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"HTTP Request Error"]; + [alert setInformativeText:message]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + } + }); } -+ (NSInteger)unexpectedResponseStatusAlertWithRequest:(ASIPithosRequest *)request { ++ (void)unexpectedResponseStatusAlertWithRequest:(ASIPithosRequest *)request { + if (request.responseStatusCode == 401) { + [self httpAuthenticationError]; + return; + } NSString *message = [NSString stringWithFormat: @"Unexpected response status %d: %@\n%@ URL: %@\nRequest Headers: %@\nResponse Headers: %@\nResponse String: %@", request.responseStatusCode, @@ -1192,23 +1238,43 @@ [request requestHeaders], [request responseHeaders], [request responseString]]; - NSLog(@"%@", message); - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:@"Unexpected Response Status"]; - [alert setInformativeText:message]; - [alert addButtonWithTitle:@"OK"]; - return [alert runModal]; + DLog(@"%@", message); + dispatch_async(dispatch_get_main_queue(), ^{ + @autoreleasepool { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Unexpected Response Status"]; + [alert setInformativeText:message]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + } + }); } -+ (NSInteger)fileActionFailedAlertWithTitle:(NSString *)title message:(NSString *)message error:(NSError *)error { - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; - [alert setMessageText:title]; - if (error) - [alert setInformativeText:[NSString stringWithFormat:@"%@: %@", message, error]]; - else - [alert setInformativeText:message]; - [alert addButtonWithTitle:@"OK"]; - return [alert runModal]; ++ (void)httpAuthenticationError { + dispatch_async(dispatch_get_main_queue(), ^{ + @autoreleasepool { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Authentication Error"]; + [alert setInformativeText:@"Authentication error, please check your token or login again"]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + } + }); +} + ++ (void)fileActionFailedAlertWithTitle:(NSString *)title message:(NSString *)message error:(NSError *)error { + dispatch_async(dispatch_get_main_queue(), ^{ + @autoreleasepool { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:title]; + if (error) + [alert setInformativeText:[NSString stringWithFormat:@"%@: %@", message, [error localizedDescription]]]; + else + [alert setInformativeText:message]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + } + }); } #pragma mark - @@ -1226,11 +1292,17 @@ } + (ASIPithosRequest *)copyRequest:(ASIPithosRequest *)request { - NSMutableDictionary *userInfo = (NSMutableDictionary *)[[request.userInfo retain] autorelease]; + NSMutableDictionary *userInfo = (NSMutableDictionary *)request.userInfo; request.userInfo = nil; ASIPithosRequest *newRequest = [request copy]; newRequest.userInfo = userInfo; return newRequest; } ++ (void)startAndWaitForRequest:(ASIPithosRequest *)request { + ASINetworkQueue *networkQueue = [ASINetworkQueue queue]; + [networkQueue go]; + [networkQueue addOperations:[NSArray arrayWithObject:[self prepareRequest:request]] waitUntilFinished:YES]; +} + @end