Stashing progress
This commit is contained in:
parent
1c85deee36
commit
910811a5e0
2 changed files with 329 additions and 296 deletions
|
|
@ -29,7 +29,6 @@
|
||||||
#import <Availability.h>
|
#import <Availability.h>
|
||||||
|
|
||||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||||
#import <UIKit/UIKit.h>
|
|
||||||
#import <MobileCoreServices/MobileCoreServices.h>
|
#import <MobileCoreServices/MobileCoreServices.h>
|
||||||
#else
|
#else
|
||||||
#import <CoreServices/CoreServices.h>
|
#import <CoreServices/CoreServices.h>
|
||||||
|
|
@ -48,6 +47,7 @@
|
||||||
NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change";
|
NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change";
|
||||||
|
|
||||||
@interface AFStreamingMultipartFormData : NSObject <AFStreamingMultipartFormData>
|
@interface AFStreamingMultipartFormData : NSObject <AFStreamingMultipartFormData>
|
||||||
|
|
||||||
- (id)initWithURLRequest:(NSMutableURLRequest *)request
|
- (id)initWithURLRequest:(NSMutableURLRequest *)request
|
||||||
stringEncoding:(NSStringEncoding)encoding;
|
stringEncoding:(NSStringEncoding)encoding;
|
||||||
|
|
||||||
|
|
@ -57,12 +57,29 @@ NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire
|
||||||
|
|
||||||
@interface AFMultipartBodyStream : NSInputStream <NSStreamDelegate>
|
@interface AFMultipartBodyStream : NSInputStream <NSStreamDelegate>
|
||||||
|
|
||||||
|
@property (readonly) unsigned long long contentLength;
|
||||||
|
@property (readonly, getter = isEmpty) BOOL empty;
|
||||||
|
|
||||||
- (id)initWithStringEncoding:(NSStringEncoding)encoding;
|
- (id)initWithStringEncoding:(NSStringEncoding)encoding;
|
||||||
- (BOOL)addFileFromURL:(NSURL *)fileURL name:(NSString *)name error:(NSError **)error;
|
|
||||||
- (void)addFormData:(NSData *)data name:(NSString *)name;
|
@end
|
||||||
- (BOOL)empty;
|
|
||||||
- (NSUInteger)contentLength;
|
@interface AFHTTPBodyPart : NSObject
|
||||||
|
@property (assign) BOOL hasInitialBoundary;
|
||||||
|
@property (assign) BOOL hasFinalBoundary;
|
||||||
|
|
||||||
|
@property (readonly, getter = hasBytesAvailable) BOOL bytesAvailable;
|
||||||
|
@property (readonly) unsigned long long contentLength;
|
||||||
|
|
||||||
|
+ (AFHTTPBodyPart *)HTTPBodyPartWithStringEncoding:(NSStringEncoding)encoding
|
||||||
|
headers:(NSDictionary *)headers
|
||||||
|
fileURL:(NSURL *)fileURL;
|
||||||
|
|
||||||
|
+ (AFHTTPBodyPart *)HTTPBodyPartWithStringEncoding:(NSStringEncoding)encoding
|
||||||
|
headers:(NSDictionary *)headers
|
||||||
|
formData:(NSData *)formData;
|
||||||
|
|
||||||
|
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)length;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
@ -755,22 +772,65 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
||||||
return [NSString stringWithFormat:@"%@--%@--%@", kAFMultipartFormCRLF, kAFMultipartFormBoundary, kAFMultipartFormCRLF];
|
return [NSString stringWithFormat:@"%@--%@--%@", kAFMultipartFormCRLF, kAFMultipartFormBoundary, kAFMultipartFormCRLF];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark --
|
static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
|
||||||
#pragma mark AFStreamingMultipartFormData
|
CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)extension, NULL);
|
||||||
|
NSString *contentType = (NSString *)UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType);
|
||||||
|
|
||||||
|
CFRelease(UTI);
|
||||||
|
|
||||||
@interface AFStreamingMultipartFormData () {
|
return [contentType autorelease];
|
||||||
AFMultipartBodyStream * bodyStream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - AFStreamingMultipartFormData
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@interface AFStreamingMultipartFormData ()
|
||||||
@property (readwrite, nonatomic, retain) NSMutableURLRequest *request;
|
@property (readwrite, nonatomic, retain) NSMutableURLRequest *request;
|
||||||
|
@property (readwrite, nonatomic, retain) AFMultipartBodyStream *bodyStream;
|
||||||
@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
|
@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
|
||||||
|
@end
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AFEncapsulationBoundaryPhase = 1,
|
||||||
|
AFHeaderPhase = 2,
|
||||||
|
AFBodyPhase = 3,
|
||||||
|
AFFinalBoundaryPhase = 4,
|
||||||
|
} AFHTTPBodyPartReadPhase;
|
||||||
|
|
||||||
|
@interface AFHTTPBodyPart ()
|
||||||
|
@property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
|
||||||
|
@property (readwrite, nonatomic, retain) NSDictionary *headers;
|
||||||
|
@property (readwrite, nonatomic, retain) NSInputStream *inputStream;
|
||||||
|
@property (readwrite, nonatomic, assign) unsigned long long bodyContentLength;
|
||||||
|
|
||||||
|
- (BOOL)transitionToNextPhase;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface AFMultipartBodyStream () {
|
||||||
|
CFReadStreamClientCallBack copiedCallback;
|
||||||
|
CFStreamClientContext copiedContext;
|
||||||
|
CFOptionFlags requestedEvents;
|
||||||
|
NSStreamStatus streamStatus;
|
||||||
|
id <NSStreamDelegate> delegate;
|
||||||
|
|
||||||
|
NSMutableArray *_HTTPBodyParts;
|
||||||
|
NSEnumerator *_HTTPBodyPartEnumerator;
|
||||||
|
AFHTTPBodyPart *_currentHTTPBodyPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSStringEncoding stringEncoding;
|
||||||
|
@property (nonatomic, retain) NSMutableArray *HTTPBodyParts;
|
||||||
|
@property (nonatomic, retain) NSEnumerator *HTTPBodyPartEnumerator;
|
||||||
|
@property (nonatomic, retain) AFHTTPBodyPart *currentHTTPBodyPart;
|
||||||
|
|
||||||
|
- (void)appendHTTPBodyPart:(AFHTTPBodyPart *)bodyPart;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation AFStreamingMultipartFormData
|
@implementation AFStreamingMultipartFormData
|
||||||
|
|
||||||
@synthesize request = _request;
|
@synthesize request = _request;
|
||||||
|
@synthesize bodyStream = _bodyStream;
|
||||||
@synthesize stringEncoding = _stringEncoding;
|
@synthesize stringEncoding = _stringEncoding;
|
||||||
|
|
||||||
- (id)initWithURLRequest:(NSMutableURLRequest *)request
|
- (id)initWithURLRequest:(NSMutableURLRequest *)request
|
||||||
|
|
@ -780,166 +840,124 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
||||||
if (!self) {
|
if (!self) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.request = request;
|
self.request = request;
|
||||||
self.stringEncoding = encoding;
|
self.stringEncoding = encoding;
|
||||||
bodyStream = [[AFMultipartBodyStream alloc] initWithStringEncoding:encoding];
|
self.bodyStream = [[[AFMultipartBodyStream alloc] initWithStringEncoding:encoding] autorelease];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc {
|
- (void)dealloc {
|
||||||
[bodyStream release];
|
[_request release];
|
||||||
|
[_bodyStream release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)appendPartWithFormData:(NSData *)data name:(NSString *)name {
|
- (void)appendPartWithFormData:(NSData *)data name:(NSString *)name {
|
||||||
[bodyStream addFormData:data name:name];
|
NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
|
||||||
|
[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"", name] forKey:@"Content-Disposition"];
|
||||||
|
|
||||||
|
AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init];
|
||||||
|
bodyPart.stringEncoding = self.stringEncoding;
|
||||||
|
bodyPart.headers = mutableHeaders;
|
||||||
|
bodyPart.inputStream = [NSInputStream inputStreamWithData:data];
|
||||||
|
|
||||||
|
bodyPart.bodyContentLength = [data length];
|
||||||
|
|
||||||
|
[self.bodyStream.HTTPBodyParts addObject:bodyPart];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)appendPartWithFileData:(NSData *)data name:(NSString *)name fileName:(NSString *)fileName mimeType:(NSString *)mimeType
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
// NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
|
||||||
|
// [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
|
||||||
|
// [mutableHeaders setValue:mimeType forKey:@"Content-Type"];
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL name:(NSString *)name error:(NSError **)error {
|
- (BOOL)appendPartWithFileURL:(NSURL *)fileURL name:(NSString *)name error:(NSError **)error {
|
||||||
return [bodyStream addFileFromURL:fileURL name:name error:error];
|
if (![fileURL isFileURL]) {
|
||||||
|
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedString(@"Expected URL to be a file URL", nil) forKey:NSLocalizedFailureReasonErrorKey];
|
||||||
|
if (error != NULL) {
|
||||||
|
*error = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadURL userInfo:userInfo] autorelease];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
} else if ([fileURL checkResourceIsReachableAndReturnError:error] == NO) {
|
||||||
|
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedString(@"File URL not reachable.", nil) forKey:NSLocalizedFailureReasonErrorKey];
|
||||||
|
if (error != NULL) {
|
||||||
|
*error = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadURL userInfo:userInfo] autorelease];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
|
||||||
|
[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, [[fileURL URLByDeletingPathExtension] lastPathComponent]] forKey:@"Content-Disposition"];
|
||||||
|
[mutableHeaders setValue:AFContentTypeForPathExtension([fileURL pathExtension]) forKey:@"Content-Type"];
|
||||||
|
|
||||||
|
AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init];
|
||||||
|
bodyPart.stringEncoding = self.stringEncoding;
|
||||||
|
bodyPart.headers = mutableHeaders;
|
||||||
|
bodyPart.inputStream = [NSInputStream inputStreamWithURL:fileURL];
|
||||||
|
|
||||||
|
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[fileURL path] error:nil];
|
||||||
|
bodyPart.bodyContentLength = [[fileAttributes objectForKey:NSFileSize] unsignedLongLongValue];
|
||||||
|
|
||||||
|
[self.bodyStream.HTTPBodyParts addObject:bodyPart];
|
||||||
|
|
||||||
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSMutableURLRequest *)requestByFinalizingMultipartFormData {
|
- (NSMutableURLRequest *)requestByFinalizingMultipartFormData {
|
||||||
//return the original request if no data has been added
|
// Return the original request if no data has been added
|
||||||
if ([bodyStream empty]) {
|
if ([self.bodyStream isEmpty]) {
|
||||||
return self.request;
|
return self.request;
|
||||||
}
|
}
|
||||||
[self.request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", kAFMultipartFormBoundary] forHTTPHeaderField:@"Content-Type"];
|
[self.request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", kAFMultipartFormBoundary] forHTTPHeaderField:@"Content-Type"];
|
||||||
[self.request setValue:[NSString stringWithFormat:@"%d",[bodyStream contentLength]] forHTTPHeaderField:@"Content-Length"];
|
[self.request setValue:[NSString stringWithFormat:@"%llu", [self.bodyStream contentLength]] forHTTPHeaderField:@"Content-Length"];
|
||||||
[self.request setHTTPBodyStream:bodyStream];
|
[self.request setHTTPBodyStream:self.bodyStream];
|
||||||
|
|
||||||
return self.request;
|
return self.request;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)appendData:(NSData *)data {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#pragma mark - AFMultipartBodyStream
|
#pragma mark - AFMultipartBodyStream
|
||||||
|
|
||||||
@interface AFMultipartBodyStream () {
|
|
||||||
CFReadStreamClientCallBack copiedCallback;
|
|
||||||
CFStreamClientContext copiedContext;
|
|
||||||
CFOptionFlags requestedEvents;
|
|
||||||
NSStreamStatus streamStatus;
|
|
||||||
id <NSStreamDelegate> delegate;
|
|
||||||
|
|
||||||
NSMutableArray *fileNames;
|
|
||||||
NSMutableDictionary *fileURLs;
|
|
||||||
NSMutableDictionary *fileHeaders;
|
|
||||||
NSMutableArray *formNames;
|
|
||||||
NSMutableDictionary *formDatas;
|
|
||||||
NSMutableDictionary *formHeaders;
|
|
||||||
NSUInteger readElementCursor;
|
|
||||||
NSUInteger readOffsetCursor;
|
|
||||||
NSUInteger readHeaderOffsetCursor;
|
|
||||||
NSInputStream * currentFileStream;
|
|
||||||
NSStringEncoding stringEncoding;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation AFMultipartBodyStream
|
@implementation AFMultipartBodyStream
|
||||||
|
@synthesize stringEncoding = _stringEncoding;
|
||||||
|
@synthesize HTTPBodyParts = _HTTPBodyParts;
|
||||||
|
@synthesize HTTPBodyPartEnumerator = _HTTPBodyPartEnumerator;
|
||||||
|
@synthesize currentHTTPBodyPart = _currentHTTPBodyPart;
|
||||||
|
|
||||||
|
- (id)initWithStringEncoding:(NSStringEncoding)encoding {
|
||||||
- (id)init {
|
|
||||||
self = [super init];
|
self = [super init];
|
||||||
fileNames = [[NSMutableArray alloc] init];
|
if (!self) {
|
||||||
fileURLs = [[NSMutableDictionary alloc] init];
|
return nil;
|
||||||
fileHeaders = [[NSMutableDictionary alloc] init];
|
}
|
||||||
formNames = [[NSMutableArray alloc] init];
|
|
||||||
formDatas = [[NSMutableDictionary alloc] init];
|
self.stringEncoding = encoding;
|
||||||
formHeaders = [[NSMutableDictionary alloc] init];
|
|
||||||
currentFileStream = NULL;
|
|
||||||
stringEncoding = NSUTF8StringEncoding;
|
|
||||||
streamStatus = NSStreamStatusNotOpen;
|
streamStatus = NSStreamStatusNotOpen;
|
||||||
[self resetCursors];
|
|
||||||
// [self setDelegate:self];
|
// [self setDelegate:self];
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithStringEncoding:(NSStringEncoding)encoding {
|
|
||||||
self = [self init];
|
|
||||||
stringEncoding = encoding;
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)resetCursors {
|
|
||||||
readElementCursor = 0;
|
|
||||||
readOffsetCursor = 0;
|
|
||||||
readHeaderOffsetCursor = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)dealloc {
|
- (void)dealloc {
|
||||||
[fileNames release];
|
[_HTTPBodyParts release];
|
||||||
[fileURLs release];
|
[_HTTPBodyPartEnumerator release];
|
||||||
[fileHeaders release];
|
[_currentHTTPBodyPart release];
|
||||||
[formNames release];
|
|
||||||
[formDatas release];
|
|
||||||
[formHeaders release];
|
|
||||||
if (currentFileStream) {
|
|
||||||
[currentFileStream close];
|
|
||||||
[currentFileStream release];
|
|
||||||
currentFileStream = NULL;
|
|
||||||
}
|
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)empty {
|
- (void)appendHTTPBodyPart:(AFHTTPBodyPart *)bodyPart {
|
||||||
if (([fileURLs count] + [formDatas count]) == 0)
|
|
||||||
return YES;
|
|
||||||
else
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (BOOL)addFileFromURL:(NSURL *)fileURL name:(NSString *)name error:(NSError **)error {
|
|
||||||
assert([self streamStatus] == NSStreamStatusNotOpen);
|
|
||||||
|
|
||||||
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
|
|
||||||
[userInfo setValue:fileURL forKey:NSURLErrorFailingURLErrorKey];
|
|
||||||
|
|
||||||
if (![fileURL isFileURL]) {
|
|
||||||
[userInfo setValue:NSLocalizedString(@"Expected URL to be a file URL", nil) forKey:NSLocalizedFailureReasonErrorKey];
|
|
||||||
if (error != NULL) {
|
|
||||||
*error = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadURL userInfo:userInfo] autorelease];
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([fileURL checkResourceIsReachableAndReturnError:error] == NO) {
|
|
||||||
[userInfo setValue:NSLocalizedString(@"File URL not reachable.", nil) forKey:NSLocalizedFailureReasonErrorKey];
|
|
||||||
if (error != NULL) {
|
|
||||||
*error = [[[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadURL userInfo:userInfo] autorelease];
|
|
||||||
}
|
|
||||||
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
[fileNames addObject:name];
|
|
||||||
[fileURLs setObject:fileURL forKey:name];
|
|
||||||
[self generateHeaders];
|
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)addFormData:(NSData *)data name:(NSString *)name {
|
|
||||||
assert([self streamStatus] == NSStreamStatusNotOpen);
|
|
||||||
[formNames addObject:name];
|
|
||||||
[formDatas setObject:data forKey:name];
|
|
||||||
[self generateHeaders];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)generateHeaders {
|
|
||||||
[formHeaders removeAllObjects];
|
|
||||||
for (NSString * formName in formNames) {
|
|
||||||
[formHeaders setObject:[self headersDataForForm:formName] forKey:formName];
|
|
||||||
}
|
|
||||||
[fileHeaders removeAllObjects];
|
|
||||||
for (NSString * fileName in fileNames) {
|
|
||||||
[fileHeaders setObject:[self headersDataForFile:fileName] forKey:fileName];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)stringForHeaders:(NSDictionary *)headers {
|
- (NSString *)stringForHeaders:(NSDictionary *)headers {
|
||||||
|
|
@ -950,96 +968,29 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
||||||
return [NSString stringWithString:headerString];
|
return [NSString stringWithString:headerString];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSData *)headersDataForDict:(NSDictionary *)headersDict {
|
|
||||||
NSMutableString * headerString = [NSMutableString string];
|
|
||||||
if ([formHeaders count] == 0 && [fileHeaders count] == 0) {
|
|
||||||
[headerString appendString:AFMultipartFormInitialBoundary()];
|
|
||||||
} else {
|
|
||||||
[headerString appendString:AFMultipartFormEncapsulationBoundary()];
|
|
||||||
}
|
|
||||||
[headerString appendString:[self stringForHeaders:headersDict]];
|
|
||||||
[headerString appendString:kAFMultipartFormCRLF];
|
|
||||||
|
|
||||||
return [headerString dataUsingEncoding:stringEncoding];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSData *)headersDataForFile:(NSString *)name {
|
|
||||||
NSURL * fileURL = [fileURLs objectForKey:name];
|
|
||||||
NSString * fileName = [[fileURL pathComponents] objectAtIndex:([[fileURL pathComponents] count] - 1)];
|
|
||||||
NSMutableDictionary * mutableHeaders = [NSMutableDictionary dictionary];
|
|
||||||
[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
|
|
||||||
CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)[fileURL pathExtension], NULL);
|
|
||||||
NSString * MIMEType = [(NSString*) UTTypeCopyPreferredTagWithClass (UTI, kUTTagClassMIMEType) autorelease];
|
|
||||||
CFRelease(UTI);
|
|
||||||
[mutableHeaders setValue:MIMEType forKey:@"Content-Type"];
|
|
||||||
return [self headersDataForDict:mutableHeaders];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSData *)headersDataForForm:(NSString *)name {
|
|
||||||
return [self headersDataForDict:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:@"form-data; name=\"%@\"", name] forKey:@"Content-Disposition"]];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSInteger)readData:(NSData *)data intoBuffer:(uint8_t *)buffer maxLength:(NSUInteger)len offsetCursor:(NSUInteger*)offsetCursorPtr {
|
|
||||||
NSInteger bytesAvailable = [data length] - *offsetCursorPtr;
|
|
||||||
if (len > bytesAvailable) {
|
|
||||||
[data getBytes:buffer range:NSMakeRange(*offsetCursorPtr, bytesAvailable)];
|
|
||||||
*offsetCursorPtr += bytesAvailable;
|
|
||||||
return bytesAvailable;
|
|
||||||
} else {
|
|
||||||
[data getBytes:buffer range:NSMakeRange(*offsetCursorPtr, len)];
|
|
||||||
*offsetCursorPtr += len;
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)nextElement {
|
|
||||||
readOffsetCursor = 0;
|
|
||||||
readHeaderOffsetCursor = 0;
|
|
||||||
readElementCursor += 1;
|
|
||||||
|
|
||||||
if (currentFileStream) {
|
|
||||||
[currentFileStream close];
|
|
||||||
[currentFileStream release];
|
|
||||||
currentFileStream = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSUInteger)contentLength {
|
|
||||||
NSUInteger total = 0;
|
|
||||||
for (NSString * formName in formNames) {
|
|
||||||
total += [[formHeaders objectForKey:formName] length];
|
|
||||||
total += [[formDatas objectForKey:formName] length];
|
|
||||||
}
|
|
||||||
for (NSString * fileName in fileNames) {
|
|
||||||
NSError * error;
|
|
||||||
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[[fileURLs objectForKey:fileName] path] error:&error];
|
|
||||||
total += [[fileHeaders objectForKey:fileName] length];
|
|
||||||
total += [[fileAttributes objectForKey:NSFileSize] longValue];
|
|
||||||
}
|
|
||||||
total += [[self finalBoundaryData] length];
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSUInteger)totalElements {
|
|
||||||
return [formDatas count] + [fileURLs count] + 1; //one extra for final boundary
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSData *)finalBoundaryData {
|
- (NSData *)finalBoundaryData {
|
||||||
return [AFMultipartFormFinalBoundary() dataUsingEncoding:stringEncoding];
|
return [AFMultipartFormFinalBoundary() dataUsingEncoding:_stringEncoding];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - NSStream subclass overrides
|
#pragma mark - NSStream subclass overrides
|
||||||
|
|
||||||
- (void)open {
|
- (void)open {
|
||||||
streamStatus = NSStreamStatusOpen;
|
streamStatus = NSStreamStatusOpen;
|
||||||
|
|
||||||
|
if ([self.HTTPBodyParts count] > 0) {
|
||||||
|
[[self.HTTPBodyParts objectAtIndex:0] setHasInitialBoundary:YES];
|
||||||
|
[[self.HTTPBodyParts lastObject] setHasFinalBoundary:YES];
|
||||||
|
|
||||||
|
self.HTTPBodyPartEnumerator = [self.HTTPBodyParts objectEnumerator];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)close {
|
- (void)close {
|
||||||
streamStatus = NSStreamStatusClosed;
|
streamStatus = NSStreamStatusClosed;
|
||||||
[self resetCursors];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id <NSStreamDelegate> )delegate {
|
- (id <NSStreamDelegate>)delegate {
|
||||||
return delegate;
|
return delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1052,11 +1003,13 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode {
|
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop
|
||||||
}
|
forMode:(NSString *)mode
|
||||||
|
{}
|
||||||
|
|
||||||
- (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode {
|
- (void)removeFromRunLoop:(NSRunLoop *)aRunLoop
|
||||||
}
|
forMode:(NSString *)mode
|
||||||
|
{}
|
||||||
|
|
||||||
- (id)propertyForKey:(NSString *)key {
|
- (id)propertyForKey:(NSString *)key {
|
||||||
return nil;
|
return nil;
|
||||||
|
|
@ -1066,7 +1019,6 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
- (NSStreamStatus)streamStatus {
|
- (NSStreamStatus)streamStatus {
|
||||||
return streamStatus;
|
return streamStatus;
|
||||||
}
|
}
|
||||||
|
|
@ -1077,7 +1029,7 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
||||||
|
|
||||||
#pragma mark - NSInputStream subclass overrides
|
#pragma mark - NSInputStream subclass overrides
|
||||||
|
|
||||||
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len {
|
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)length {
|
||||||
if ([self streamStatus] == NSStreamStatusClosed) {
|
if ([self streamStatus] == NSStreamStatusClosed) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1085,80 +1037,21 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
||||||
assert ([self streamStatus] == NSStreamStatusOpen);
|
assert ([self streamStatus] == NSStreamStatusOpen);
|
||||||
|
|
||||||
NSInteger bytesRead = 0;
|
NSInteger bytesRead = 0;
|
||||||
NSInteger readFileCursor = (readElementCursor - [formNames count]);
|
|
||||||
|
|
||||||
if (readElementCursor < [formNames count]) {
|
if (!self.currentHTTPBodyPart || ![self.currentHTTPBodyPart hasBytesAvailable]) {
|
||||||
//reading from formDatas
|
if (!(self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject])) {
|
||||||
NSString * currentFormName = [formNames objectAtIndex:readElementCursor];
|
NSLog(@"NOTHING TO BE DONE");
|
||||||
NSData * currentData = [formDatas objectForKey:currentFormName];
|
[self close];
|
||||||
NSData * headersData = [formHeaders objectForKey:currentFormName];
|
|
||||||
|
|
||||||
if (readHeaderOffsetCursor < [headersData length]) {
|
|
||||||
bytesRead = [self readData:headersData intoBuffer:buffer maxLength:len offsetCursor:&readHeaderOffsetCursor];
|
|
||||||
} else {
|
|
||||||
bytesRead = [self readData:currentData intoBuffer:buffer maxLength:len offsetCursor:&readOffsetCursor];
|
|
||||||
}
|
}
|
||||||
if (readOffsetCursor == [currentData length]) {
|
|
||||||
[self nextElement];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (readFileCursor >= 0 && readFileCursor < [fileNames count]) {
|
|
||||||
//reading from files
|
|
||||||
NSString * currentFileName = [fileNames objectAtIndex:readFileCursor];
|
|
||||||
NSURL * currentFileURL = [fileURLs objectForKey:currentFileName];
|
|
||||||
NSData * headersData = [fileHeaders objectForKey:currentFileName];
|
|
||||||
|
|
||||||
assert(headersData != NULL);
|
|
||||||
|
|
||||||
if (readHeaderOffsetCursor < [headersData length]) {
|
|
||||||
bytesRead = [self readData:headersData intoBuffer:buffer maxLength:len offsetCursor:&readHeaderOffsetCursor];
|
|
||||||
} else {
|
|
||||||
if (!currentFileStream) {
|
|
||||||
currentFileStream = [[NSInputStream inputStreamWithURL:currentFileURL] retain];
|
|
||||||
// currentFileStream.delegate = self;
|
|
||||||
[currentFileStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
|
|
||||||
[currentFileStream open];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bytesRead = [currentFileStream read:buffer maxLength:len];
|
bytesRead += [self.currentHTTPBodyPart read:buffer maxLength:length];
|
||||||
|
|
||||||
if (![currentFileStream hasBytesAvailable] || bytesRead == 0) {
|
|
||||||
[self nextElement];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (readElementCursor < [self totalElements]) {
|
|
||||||
//add final boundary
|
|
||||||
bytesRead = [self readData:[self finalBoundaryData] intoBuffer:buffer maxLength:len offsetCursor:&readOffsetCursor];
|
|
||||||
if (readOffsetCursor == [[self finalBoundaryData] length]) {
|
|
||||||
[self nextElement];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
[self nextElement];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (readElementCursor <= [self totalElements]) {
|
|
||||||
if (bytesRead < len) {
|
|
||||||
bytesRead += [self read:buffer+bytesRead maxLength:len-bytesRead];
|
|
||||||
} else {
|
|
||||||
// no deeper recursion so call callback if necessary
|
|
||||||
if (copiedCallback && (requestedEvents & kCFStreamEventHasBytesAvailable)) {
|
|
||||||
copiedCallback((CFReadStreamRef)self, kCFStreamEventHasBytesAvailable, &copiedContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)hasBytesAvailable {
|
- (BOOL)hasBytesAvailable {
|
||||||
if ([self streamStatus] != NSStreamStatusOpen) {
|
return [self streamStatus] != NSStreamStatusOpen;
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len {
|
- (BOOL)getBuffer:(uint8_t **)buffer length:(NSUInteger *)len {
|
||||||
|
|
@ -1167,8 +1060,13 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
||||||
|
|
||||||
#pragma mark - Undocumented CFReadStream bridged methods
|
#pragma mark - Undocumented CFReadStream bridged methods
|
||||||
|
|
||||||
- (void)_scheduleInCFRunLoop:(CFRunLoopRef)aRunLoop forMode:(CFStringRef)aMode {
|
- (void)_scheduleInCFRunLoop:(CFRunLoopRef)aRunLoop
|
||||||
}
|
forMode:(CFStringRef)aMode
|
||||||
|
{}
|
||||||
|
|
||||||
|
- (void)_unscheduleFromCFRunLoop:(CFRunLoopRef)aRunLoop
|
||||||
|
forMode:(CFStringRef)aMode
|
||||||
|
{}
|
||||||
|
|
||||||
- (BOOL)_setCFClientFlags:(CFOptionFlags)inFlags
|
- (BOOL)_setCFClientFlags:(CFOptionFlags)inFlags
|
||||||
callback:(CFReadStreamClientCallBack)inCallback
|
callback:(CFReadStreamClientCallBack)inCallback
|
||||||
|
|
@ -1196,10 +1094,147 @@ static inline NSString * AFMultipartFormFinalBoundary() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_unscheduleFromCFRunLoop:(CFRunLoopRef)aRunLoop forMode:(CFStringRef)aMode {
|
@end
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
|
@implementation AFHTTPBodyPart {
|
||||||
|
AFHTTPBodyPartReadPhase _phase;
|
||||||
|
unsigned long long _phaseReadOffset;
|
||||||
|
}
|
||||||
|
@synthesize stringEncoding = _stringEncoding;
|
||||||
|
@synthesize headers = _headers;
|
||||||
|
@synthesize inputStream = _inputStream;
|
||||||
|
@synthesize bodyContentLength = _bodyContentLength;
|
||||||
|
|
||||||
|
- (id)init {
|
||||||
|
self = [super init];
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self transitionToNextPhase];
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
[_headers release];
|
||||||
|
|
||||||
|
if (_inputStream) {
|
||||||
|
[_inputStream close];
|
||||||
|
[_inputStream release];
|
||||||
|
_inputStream = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)transitionToNextPhase {
|
||||||
|
switch (_phase) {
|
||||||
|
case AFEncapsulationBoundaryPhase:
|
||||||
|
_phase = AFHeaderPhase;
|
||||||
|
break;
|
||||||
|
case AFHeaderPhase:
|
||||||
|
_phase = AFBodyPhase;
|
||||||
|
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
|
||||||
|
[self.inputStream open];
|
||||||
|
break;
|
||||||
|
case AFBodyPhase:
|
||||||
|
[self.inputStream close];
|
||||||
|
_phase = AFFinalBoundaryPhase;
|
||||||
|
default:
|
||||||
|
_phase = 0;
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
_phaseReadOffset = 0;
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)stringForHeaders {
|
||||||
|
NSMutableString *headerString = [NSMutableString string];
|
||||||
|
for (NSString *field in [self.headers allKeys]) {
|
||||||
|
[headerString appendString:[NSString stringWithFormat:@"%@: %@%@", field, [self.headers valueForKey:field], kAFMultipartFormCRLF]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [NSString stringWithString:headerString];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSInteger)readData:(NSData *)data
|
||||||
|
intoBuffer:(uint8_t *)buffer
|
||||||
|
maxLength:(NSUInteger)length
|
||||||
|
{
|
||||||
|
NSRange range = NSMakeRange(_phaseReadOffset, MIN([data length], length));
|
||||||
|
[data getBytes:buffer range:range];
|
||||||
|
|
||||||
|
if (range.length >= [data length]) {
|
||||||
|
[self transitionToNextPhase];
|
||||||
|
} else {
|
||||||
|
_phaseReadOffset += range.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return range.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (unsigned long long)contentLength {
|
||||||
|
unsigned long long length = 0;
|
||||||
|
|
||||||
|
NSData *encapsulationBoundaryData = [([self hasInitialBoundary] ? AFMultipartFormInitialBoundary() : AFMultipartFormEncapsulationBoundary()) dataUsingEncoding:self.stringEncoding];
|
||||||
|
length += [encapsulationBoundaryData length];
|
||||||
|
|
||||||
|
NSData *headersData = [[self stringForHeaders] dataUsingEncoding:self.stringEncoding];
|
||||||
|
length += [headersData length];
|
||||||
|
|
||||||
|
length += _bodyContentLength;
|
||||||
|
|
||||||
|
NSData *closingBoundaryData = ([self hasFinalBoundary] ? [AFMultipartFormFinalBoundary() dataUsingEncoding:self.stringEncoding] : [NSData data]);
|
||||||
|
length += [closingBoundaryData length];
|
||||||
|
|
||||||
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)length {
|
||||||
|
NSInteger bytesRead = 0;
|
||||||
|
|
||||||
|
if (_phase == AFEncapsulationBoundaryPhase) {
|
||||||
|
NSData *encapsulationBoundaryData = [([self hasInitialBoundary] ? AFMultipartFormInitialBoundary() : AFMultipartFormEncapsulationBoundary()) dataUsingEncoding:self.stringEncoding];
|
||||||
|
bytesRead += [self readData:encapsulationBoundaryData intoBuffer:buffer maxLength:(length - bytesRead)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_phase == AFHeaderPhase) {
|
||||||
|
NSData *headersData = [[self stringForHeaders] dataUsingEncoding:self.stringEncoding];
|
||||||
|
bytesRead += [self readData:headersData intoBuffer:buffer maxLength:(length - bytesRead)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_phase == AFBodyPhase) {
|
||||||
|
if ([self.inputStream hasBytesAvailable]) {
|
||||||
|
bytesRead += [self.inputStream read:buffer maxLength:(length - bytesRead)];
|
||||||
|
} else {
|
||||||
|
[self transitionToNextPhase];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_phase == AFFinalBoundaryPhase) {
|
||||||
|
NSData *closingBoundaryData = ([self hasFinalBoundary] ? [AFMultipartFormFinalBoundary() dataUsingEncoding:self.stringEncoding] : [NSData data]);
|
||||||
|
bytesRead += [self readData:closingBoundaryData intoBuffer:buffer maxLength:(length - bytesRead)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)hasBytesAvailable {
|
||||||
|
switch (self.inputStream.streamStatus) {
|
||||||
|
case NSStreamStatusAtEnd:
|
||||||
|
case NSStreamStatusClosed:
|
||||||
|
case NSStreamStatusError:
|
||||||
|
return _phase == AFFinalBoundaryPhase;
|
||||||
|
default:
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,9 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
50ABD6ED159FC2CE001BE42C /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50ABD6EC159FC2CE001BE42C /* MobileCoreServices.framework */; };
|
|
||||||
F8129C7415910C37009BFE23 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F8129C7215910C37009BFE23 /* AppDelegate.m */; };
|
F8129C7415910C37009BFE23 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F8129C7215910C37009BFE23 /* AppDelegate.m */; };
|
||||||
|
F818101615E6A0C600EF93C2 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50ABD6EC159FC2CE001BE42C /* MobileCoreServices.framework */; };
|
||||||
F8D0701B14310F4A00653FD3 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469E213957DF700DB05C8 /* SystemConfiguration.framework */; };
|
F8D0701B14310F4A00653FD3 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469E213957DF700DB05C8 /* SystemConfiguration.framework */; };
|
||||||
F8D0701C14310F4F00653FD3 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469E013957DF100DB05C8 /* Security.framework */; };
|
|
||||||
F8DA09E41396AC040057D0CC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F8DA09E31396AC040057D0CC /* main.m */; };
|
F8DA09E41396AC040057D0CC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F8DA09E31396AC040057D0CC /* main.m */; };
|
||||||
F8E469651395739D00DB05C8 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469641395739D00DB05C8 /* UIKit.framework */; };
|
F8E469651395739D00DB05C8 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469641395739D00DB05C8 /* UIKit.framework */; };
|
||||||
F8E469671395739D00DB05C8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469661395739D00DB05C8 /* Foundation.framework */; };
|
F8E469671395739D00DB05C8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469661395739D00DB05C8 /* Foundation.framework */; };
|
||||||
|
|
@ -97,13 +96,12 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
50ABD6ED159FC2CE001BE42C /* MobileCoreServices.framework in Frameworks */,
|
|
||||||
F8E469651395739D00DB05C8 /* UIKit.framework in Frameworks */,
|
F8E469651395739D00DB05C8 /* UIKit.framework in Frameworks */,
|
||||||
F8E469671395739D00DB05C8 /* Foundation.framework in Frameworks */,
|
F8E469671395739D00DB05C8 /* Foundation.framework in Frameworks */,
|
||||||
F8E469691395739D00DB05C8 /* CoreGraphics.framework in Frameworks */,
|
F8E469691395739D00DB05C8 /* CoreGraphics.framework in Frameworks */,
|
||||||
F8E469DF13957DD500DB05C8 /* CoreLocation.framework in Frameworks */,
|
F8E469DF13957DD500DB05C8 /* CoreLocation.framework in Frameworks */,
|
||||||
F8D0701B14310F4A00653FD3 /* SystemConfiguration.framework in Frameworks */,
|
F8D0701B14310F4A00653FD3 /* SystemConfiguration.framework in Frameworks */,
|
||||||
F8D0701C14310F4F00653FD3 /* Security.framework in Frameworks */,
|
F818101615E6A0C600EF93C2 /* MobileCoreServices.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue