mirror of
https://github.com/zhigang1992/RestKit.git
synced 2026-04-01 22:42:51 +08:00
162 lines
5.8 KiB
Objective-C
162 lines
5.8 KiB
Objective-C
//
|
|
// RKPathUtilities.m
|
|
// RestKit
|
|
//
|
|
// Created by Blake Watters on 12/9/11.
|
|
// Copyright (c) 2009-2012 RestKit. All rights reserved.
|
|
//
|
|
|
|
#if TARGET_OS_IPHONE
|
|
#import <MobileCoreServices/UTType.h>
|
|
#import <UIKit/UIDevice.h>
|
|
#else
|
|
#import <CoreServices/CoreServices.h>
|
|
#endif
|
|
#import <Availability.h>
|
|
#import <sys/xattr.h>
|
|
#import "RKPathUtilities.h"
|
|
#import "RKLog.h"
|
|
#import "RKPathMatcher.h"
|
|
|
|
NSString *RKExecutableName(void);
|
|
|
|
NSString *RKApplicationDataDirectory(void)
|
|
{
|
|
#if TARGET_OS_IPHONE
|
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
|
return ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
|
|
#else
|
|
NSFileManager *sharedFM = [NSFileManager defaultManager];
|
|
|
|
NSArray *possibleURLs = [sharedFM URLsForDirectory:NSApplicationSupportDirectory
|
|
inDomains:NSUserDomainMask];
|
|
NSURL *appSupportDir = nil;
|
|
NSURL *appDirectory = nil;
|
|
|
|
if ([possibleURLs count] >= 1) {
|
|
appSupportDir = [possibleURLs objectAtIndex:0];
|
|
}
|
|
|
|
if (appSupportDir) {
|
|
appDirectory = [appSupportDir URLByAppendingPathComponent:RKExecutableName()];
|
|
return [appDirectory path];
|
|
}
|
|
|
|
return nil;
|
|
#endif
|
|
}
|
|
|
|
NSString *RKExecutableName(void)
|
|
{
|
|
NSString *executableName = [[[NSBundle mainBundle] executablePath] lastPathComponent];
|
|
if (nil == executableName) {
|
|
RKLogWarning(@"Unable to determine CFBundleExecutable: storing data under RestKit directory name.");
|
|
executableName = @"RestKit";
|
|
}
|
|
|
|
return executableName;
|
|
}
|
|
|
|
NSString *RKCachesDirectory(void)
|
|
{
|
|
#if TARGET_OS_IPHONE
|
|
return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
|
|
#else
|
|
NSString *path = nil;
|
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
|
if ([paths count]) {
|
|
path = [[paths objectAtIndex:0] stringByAppendingPathComponent:RKExecutableName()];
|
|
}
|
|
|
|
return path;
|
|
#endif
|
|
}
|
|
|
|
BOOL RKEnsureDirectoryExistsAtPath(NSString *path, NSError **error)
|
|
{
|
|
BOOL isDirectory;
|
|
if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory]) {
|
|
if (isDirectory) {
|
|
// Exists at a path and is a directory, we're good
|
|
if (error) *error = nil;
|
|
return YES;
|
|
}
|
|
}
|
|
|
|
// Create the directory and any intermediates
|
|
NSError *errorReference = (error == nil) ? nil : *error;
|
|
if (! [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&errorReference]) {
|
|
RKLogError(@"Failed to create requested directory at path '%@': %@", path, errorReference);
|
|
return NO;
|
|
}
|
|
|
|
return YES;
|
|
}
|
|
|
|
NSString *RKPathFromPatternWithObject(NSString *pathPattern, id object)
|
|
{
|
|
NSCAssert(object != NULL, @"Object provided is invalid; cannot create a path from a NULL object");
|
|
RKPathMatcher *matcher = [RKPathMatcher pathMatcherWithPattern:pathPattern];
|
|
return [matcher pathFromObject:object addingEscapes:NO];
|
|
}
|
|
|
|
static NSDictionary *RKDictionaryOfFileExtensionsToMIMETypes()
|
|
{
|
|
return @{ @"json": @"application/json" };
|
|
}
|
|
|
|
NSString *RKMIMETypeFromPathExtension(NSString *path)
|
|
{
|
|
NSString *pathExtension = [path pathExtension];
|
|
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)pathExtension, NULL);
|
|
if (uti != NULL) {
|
|
CFStringRef mime = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType);
|
|
CFRelease(uti);
|
|
if (mime != NULL) {
|
|
NSString *type = [NSString stringWithString:(__bridge NSString *)mime];
|
|
CFRelease(mime);
|
|
return type;
|
|
}
|
|
}
|
|
|
|
// Consult our internal dictionary of mappings if not found
|
|
return [RKDictionaryOfFileExtensionsToMIMETypes() valueForKey:pathExtension];
|
|
}
|
|
|
|
void RKSetExcludeFromBackupAttributeForItemAtPath(NSString *path)
|
|
{
|
|
NSCParameterAssert(path);
|
|
NSCAssert([[NSFileManager defaultManager] fileExistsAtPath:path], @"Cannot set Exclude from Backup attribute for non-existant item at path: '%@'", path);
|
|
|
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
|
NSError *error = nil;
|
|
NSURL *URL = [NSURL fileURLWithPath:path];
|
|
|
|
NSComparisonResult order = [[UIDevice currentDevice].systemVersion compare:@"5.1" options:NSNumericSearch];
|
|
if (order == NSOrderedSame || order == NSOrderedDescending) {
|
|
// On iOS >= 5.1, we can use the resource value API's. Note that we probe the iOS version number directly because the `setResourceValue:forKey:` symbol is defined in iOS 4.0 and greater, but performs no operation when invoked until iOS 5.1
|
|
BOOL success = [URL setResourceValue:@(YES) forKey:NSURLIsExcludedFromBackupKey error:&error];
|
|
if (!success) {
|
|
RKLogError(@"Failed to exclude item at path '%@' from Backup: %@", path, error);
|
|
}
|
|
} else {
|
|
order = [[UIDevice currentDevice].systemVersion compare:@"5.0.1" options: NSNumericSearch];
|
|
if (order == NSOrderedSame || order == NSOrderedDescending) {
|
|
// On iOS 5.0.1 we must use the extended attribute API's directly
|
|
const char* filePath = [[URL path] fileSystemRepresentation];
|
|
const char* attrName = "com.apple.MobileBackup";
|
|
u_int8_t attrValue = 1;
|
|
|
|
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
|
|
if (result != 0) {
|
|
RKLogError(@"Failed to exclude item at path '%@' from Backup. setxattr returned result code %d", path, result);
|
|
}
|
|
} else {
|
|
RKLogWarning(@"Unable to exclude item from backup: resource value and extended attribute APIs are only available on iOS 5.0.1 and up");
|
|
}
|
|
}
|
|
#else
|
|
RKLogDebug(@"Not built for iOS -- excluding path from Backup is not possible.");
|
|
#endif
|
|
}
|