Ben Copsey

First public release

  1 +//
  2 +// ASIHTTPRequest.h
  3 +//
  4 +// Created by Ben Copsey on 04/10/2007.
  5 +// Copyright 2007-2008 All-Seeing Interactive. All rights reserved.
  6 +//
  7 +// Portions are based on the ImageClient example from Apple:
  8 +// See: http://developer.apple.com/samplecode/ImageClient/listing37.html
  9 +
  10 +#import <Cocoa/Cocoa.h>
  11 +#import "ASIProgressDelegate.h"
  12 +
  13 +@interface ASIHTTPRequest : NSOperation {
  14 +
  15 + //The url for this operation, should include get params in the query string where appropriate
  16 + NSURL *url;
  17 +
  18 + //The delegate, you need to manage setting and talking to your delegate in your subclasses
  19 + id delegate;
  20 +
  21 + //Parameters that will be POSTed to the url
  22 + NSMutableDictionary *postData;
  23 +
  24 + //Files that will be POSTed to the url
  25 + NSMutableDictionary *fileData;
  26 +
  27 + //Dictionary for custom request headers
  28 + NSMutableDictionary *requestHeaders;
  29 +
  30 + //If usesKeychain is true, network requests will attempt to read credentials from the keychain, and will save them in the keychain when they are successfully presented
  31 + BOOL usesKeychain;
  32 +
  33 + //When downloadDestinationPath is set, the result of this request will be downloaded to the file at this location
  34 + //If downloadDestinationPath is not set, download data will be stored in memory
  35 + NSString *downloadDestinationPath;
  36 +
  37 + //Used for writing data to a file when downloadDestinationPath is set
  38 + NSOutputStream *outputStream;
  39 +
  40 + //When the request fails or completes successfully, complete will be true
  41 + BOOL complete;
  42 +
  43 + //If an error occurs, error will contain an NSError
  44 + NSError *error;
  45 +
  46 + //If an authentication error occurs, we give the delegate a chance to handle it, ignoreError will be set to true
  47 + BOOL ignoreError;
  48 +
  49 + //Username and password used for authentication
  50 + NSString *username;
  51 + NSString *password;
  52 +
  53 + //Delegate for displaying upload progress (usually an NSProgressIndicator, but you can supply a different object and handle this yourself)
  54 + NSObject <ASIProgressDelegate> *uploadProgressDelegate;
  55 +
  56 + //Delegate for displaying download progress (usually an NSProgressIndicator, but you can supply a different object and handle this yourself)
  57 + NSObject <ASIProgressDelegate> *downloadProgressDelegate;
  58 +
  59 + // Whether we've seen the headers of the response yet
  60 + BOOL haveExaminedHeaders;
  61 +
  62 + //Data we receive will be stored here
  63 + CFMutableDataRef receivedData;
  64 +
  65 + //Used for sending and receiving data
  66 + CFHTTPMessageRef request;
  67 + CFReadStreamRef readStream;
  68 +
  69 + // Authentication currently being used for prompting and resuming
  70 + CFHTTPAuthenticationRef authentication;
  71 +
  72 + // Credentials associated with the authentication (reused until server says no)
  73 + CFMutableDictionaryRef credentials;
  74 +
  75 + //Size of the response
  76 + double contentLength;
  77 +
  78 + //Size of the POST payload
  79 + double postLength;
  80 +
  81 + //Timer used to update the progress delegates
  82 + NSTimer *progressTimer;
  83 +
  84 + //The total amount of downloaded data
  85 + double totalBytesRead;
  86 +
  87 + //Realm for authentication when credentials are required
  88 + NSString *authenticationRealm;
  89 +
  90 + //Called on the delegate when the request completes successfully
  91 + SEL didFinishSelector;
  92 +
  93 + //Called on the delegate when the request fails
  94 + SEL didFailSelector;
  95 +
  96 + //This lock will block the request until the delegate supplies authentication info
  97 + NSConditionLock *authenticationLock;
  98 +}
  99 +
  100 +// Should be an HTTP or HTTPS url, may include username and password if appropriate
  101 +- (id)initWithURL:(NSURL *)newURL;
  102 +
  103 +//Add a POST variable to the request
  104 +- (void)setPostValue:(id)value forKey:(NSString *)key;
  105 +
  106 +//Add the contents of a local file as a POST variable to the request
  107 +- (void)setFile:(NSString *)filePath forKey:(NSString *)key;
  108 +
  109 +//Add a custom header to the request
  110 +- (void)addRequestHeader:(NSString *)header value:(NSString *)value;
  111 +
  112 +//the results of this request will be saved to downloadDestinationPath, if it is set
  113 +- (void)setDownloadDestinationPath:(NSString *)newDestinationPath;
  114 +- (NSString *)downloadDestinationPath;
  115 +
  116 +// When set, username and password will be presented for HTTP authentication
  117 +- (void)setUsername:(NSString *)newUsername andPassword:(NSString *)newPassword;
  118 +
  119 +// Delegate will get messages when the request completes, fails or when authentication is required
  120 +- (void)setDelegate:(id)newDelegate;
  121 +
  122 +// Called on the delegate when the request completes successfully
  123 +- (void)setDidFinishSelector:(SEL)selector;
  124 +
  125 +// Called on the delegate when the request fails
  126 +- (void)setDidFailSelector:(SEL)selector;
  127 +
  128 +// upload progress delegate (usually an NSProgressIndicator) is sent information on upload progress
  129 +- (void)setUploadProgressDelegate:(id)newDelegate;
  130 +
  131 +// download progress delegate (usually an NSProgressIndicator) is sent information on download progress
  132 +- (void)setDownloadProgressDelegate:(id)newDelegate;
  133 +
  134 +// When true, authentication information will automatically be stored in (and re-used from) the keychain
  135 +- (void)setUsesKeychain:(BOOL)shouldUseKeychain;
  136 +
  137 +// Will be true when the request is complete (success or failure)
  138 +- (BOOL)complete;
  139 +
  140 +// Returns the contents of the result as an NSString (not appropriate for binary data!)
  141 +- (NSString *)dataString;
  142 +
  143 +// Accessors for getting information about the request (useful for auth dialogs)
  144 +- (NSString *)authenticationRealm;
  145 +- (NSString *)host;
  146 +
  147 +// Contains a description of the error that occurred if the request failed
  148 +- (NSError *)error;
  149 +
  150 +
  151 +// CFnetwork event handlers
  152 +- (void)handleStreamComplete;
  153 +- (void)handleStreamError;
  154 +- (void)handleBytesAvailable;
  155 +- (void)handleNetworkEvent:(CFStreamEventType)type;
  156 +
  157 +// Start loading the request
  158 +- (void)loadRequest;
  159 +
  160 +// Reads the response headers to find the content length, and returns true if the request needs a username and password (or if those supplied were incorrect)
  161 +- (BOOL)isAuthorizationFailure;
  162 +
  163 +// Apply authentication information and resume the request after an authentication challenge
  164 +- (void)applyCredentialsAndResume;
  165 +
  166 +// Unlock (unpause) the request thread so it can resume the request
  167 +// Should be called by delegates when they have populated the authentication information after an authentication challenge
  168 +- (void)retryWithAuthentication;
  169 +
  170 +// Cancel loading and clean up
  171 +- (void)cancelLoad;
  172 +
  173 +// Called from timer on main thread to update progress delegates
  174 +- (void)updateUploadProgress;
  175 +- (void)updateDownloadProgress;
  176 +
  177 +#pragma mark keychain stuff
  178 +
  179 +//Save credentials to the keychain
  180 ++ (void)saveCredentials:(NSURLCredential *)credentials forHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;
  181 +
  182 +//Return credentials from the keychain
  183 ++ (NSURLCredential *)savedCredentialsForHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;
  184 +
  185 +//Called when a request completes successfully
  186 +- (void)requestFinished;
  187 +
  188 +//Called when a request fails
  189 +- (void)failWithProblem:(NSString *)problem;
  190 +
  191 +@end
  1 +//
  2 +// ASIHTTPRequest.m
  3 +//
  4 +// Created by Ben Copsey on 04/10/2007.
  5 +// Copyright 2007-2008 All-Seeing Interactive. All rights reserved.
  6 +//
  7 +// Portions are based on the ImageClient example from Apple:
  8 +// See: http://developer.apple.com/samplecode/ImageClient/listing37.html
  9 +
  10 +#import "ASIHTTPRequest.h"
  11 +#import "AppDelegate.h"
  12 +
  13 +const NSTimeInterval PROGRESS_INDICATOR_TIMER_INTERVAL = 0.05; // seconds between progress updates
  14 +const double PROGRESS_INDICATOR_CHUNK_SIZE = 1024; //Each progress step will be 1KB
  15 +
  16 +static NSString *NetworkRequestErrorDomain = @"com.All-SeeingInteractive.MemexTrails.NetworkError.";
  17 +
  18 +static const CFOptionFlags kNetworkEvents = kCFStreamEventOpenCompleted |
  19 + kCFStreamEventHasBytesAvailable |
  20 + kCFStreamEventEndEncountered |
  21 + kCFStreamEventErrorOccurred;
  22 +
  23 +
  24 +static CFMutableDictionaryRef sharedCredentials = NULL;
  25 +static CFHTTPAuthenticationRef sharedAuthentication = NULL;
  26 +
  27 +static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventType type, void *clientCallBackInfo) {
  28 + [((ASIHTTPRequest*)clientCallBackInfo) handleNetworkEvent: type];
  29 +}
  30 +
  31 +
  32 +@implementation ASIHTTPRequest
  33 +
  34 +#pragma mark init / dealloc
  35 +
  36 +- (id)initWithURL:(NSURL *)newURL
  37 +{
  38 + [super init];
  39 + url = [newURL retain];
  40 + postData = nil;
  41 + fileData = nil;
  42 + username = nil;
  43 + password = nil;
  44 + requestHeaders = nil;
  45 + authenticationRealm = nil;
  46 + outputStream = nil;
  47 + authentication = NULL;
  48 + credentials = NULL;
  49 + request = NULL;
  50 + usesKeychain = NO;
  51 +
  52 + return self;
  53 +}
  54 +
  55 +- (void)dealloc
  56 +{
  57 + if (authentication) {
  58 + CFRelease(authentication);
  59 + }
  60 + if (credentials) {
  61 + CFRelease(credentials);
  62 + }
  63 + if (request) {
  64 + CFRelease(request);
  65 + }
  66 + [self cancelLoad];
  67 + [error release];
  68 + [delegate release];
  69 + [uploadProgressDelegate release];
  70 + [downloadProgressDelegate release];
  71 + [postData release];
  72 + [fileData release];
  73 + [requestHeaders release];
  74 + [downloadDestinationPath release];
  75 + [outputStream release];
  76 + [username release];
  77 + [password release];
  78 + [authenticationRealm release];
  79 + [url release];
  80 + [authenticationLock release];
  81 + [super dealloc];
  82 +}
  83 +
  84 +#pragma mark delegate configuration
  85 +
  86 +- (void)setDelegate:(id)newDelegate
  87 +{
  88 + [delegate release];
  89 + delegate = [newDelegate retain];
  90 +}
  91 +
  92 +- (void)setUploadProgressDelegate:(id)newDelegate
  93 +{
  94 + [uploadProgressDelegate release];
  95 + uploadProgressDelegate = [newDelegate retain];
  96 +}
  97 +
  98 +- (void)setDownloadProgressDelegate:(id)newDelegate
  99 +{
  100 + [downloadProgressDelegate release];
  101 + downloadProgressDelegate = [newDelegate retain];
  102 +}
  103 +
  104 +
  105 +#pragma mark setup request
  106 +
  107 +- (void)addRequestHeader:(NSString *)header value:(NSString *)value
  108 +{
  109 + if (!requestHeaders) {
  110 + requestHeaders = [[NSMutableDictionary alloc] init];
  111 + }
  112 + [requestHeaders setObject:value forKey:header];
  113 +}
  114 +
  115 +
  116 +- (void)setPostValue:(id)value forKey:(NSString *)key
  117 +{
  118 + if (!postData) {
  119 + postData = [[NSMutableDictionary alloc] init];
  120 + }
  121 + [postData setValue:value forKey:key];
  122 +}
  123 +
  124 +- (void)setFile:(NSString *)filePath forKey:(NSString *)key
  125 +{
  126 + if (!fileData) {
  127 + fileData = [[NSMutableDictionary alloc] init];
  128 + }
  129 + [fileData setValue:filePath forKey:key];
  130 +}
  131 +
  132 +- (void)setUsername:(NSString *)newUsername andPassword:(NSString *)newPassword
  133 +{
  134 + [username release];
  135 + username = [newUsername retain];
  136 + [password release];
  137 + password = [newPassword retain];
  138 +}
  139 +
  140 +- (void)setUsesKeychain:(BOOL)shouldUseKeychain
  141 +{
  142 + usesKeychain = shouldUseKeychain;
  143 +}
  144 +
  145 +
  146 +- (void)setDownloadDestinationPath:(NSString *)newDestinationPath
  147 +{
  148 + [downloadDestinationPath release];
  149 + downloadDestinationPath = [newDestinationPath retain];
  150 +}
  151 +
  152 +
  153 +- (NSString *)downloadDestinationPath
  154 +{
  155 + return downloadDestinationPath;
  156 +}
  157 +
  158 +- (void)setDidFinishSelector:(SEL)selector
  159 +{
  160 + didFinishSelector = selector;
  161 +}
  162 +
  163 +- (void)setDidFailSelector:(SEL)selector
  164 +{
  165 + didFinishSelector = selector;
  166 +}
  167 +
  168 +
  169 +- (NSString *)authenticationRealm
  170 +{
  171 + return authenticationRealm;
  172 +}
  173 +
  174 +- (NSString *)host
  175 +{
  176 + return [url host];
  177 +}
  178 +
  179 +- (NSError *)error
  180 +{
  181 + return error;
  182 +}
  183 +
  184 +- (BOOL)isFinished
  185 +{
  186 + return complete;
  187 +}
  188 +
  189 +
  190 +#pragma mark request logic
  191 +
  192 +- (void)main
  193 +{
  194 +
  195 + complete = NO;
  196 +
  197 + // We'll make a post request only if the user specified post data
  198 + NSString *method = @"GET";
  199 + if ([postData count] > 0 || [fileData count] > 0) {
  200 + method = @"POST";
  201 + }
  202 +
  203 + // Create a new HTTP request.
  204 + request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, (CFStringRef)method, (CFURLRef)url, kCFHTTPVersion1_1);
  205 + if (!request) {
  206 + [self failWithProblem:@"Unable to create request"];
  207 + return;
  208 + }
  209 +
  210 + if (sharedAuthentication && sharedCredentials) {
  211 + CFHTTPMessageApplyCredentialDictionary(request, sharedAuthentication, sharedCredentials, NULL);
  212 + }
  213 +
  214 +
  215 + NSString *stringBoundary = @"0xKhTmLbOuNdArY";
  216 +
  217 + //Add custom headers
  218 + NSString *header;
  219 + for (header in requestHeaders) {
  220 + CFHTTPMessageSetHeaderFieldValue(request, (CFStringRef)header, (CFStringRef)[requestHeaders objectForKey:header]);
  221 + }
  222 + CFHTTPMessageSetHeaderFieldValue(request, (CFStringRef)@"Content-Type", (CFStringRef)[NSString stringWithFormat:@"multipart/form-data; boundary=%@",stringBoundary]);
  223 +
  224 +
  225 + if ([postData count] > 0) {
  226 +
  227 +
  228 + NSMutableData *postBody = [NSMutableData data];
  229 + [postBody appendData:[[NSString stringWithFormat:@"--%@\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
  230 +
  231 + //Adds post data
  232 + NSData *endItemBoundary = [[NSString stringWithFormat:@"\r\n--%@\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding];
  233 + NSEnumerator *e = [postData keyEnumerator];
  234 + NSString *key;
  235 + while (key = [e nextObject]) {
  236 + [postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",key] dataUsingEncoding:NSUTF8StringEncoding]];
  237 + [postBody appendData:[[postData objectForKey:key] dataUsingEncoding:NSUTF8StringEncoding]];
  238 + [postBody appendData:endItemBoundary];
  239 + }
  240 +
  241 + //Adds files to upload
  242 + NSData *contentTypeHeader = [[NSString stringWithString:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding];
  243 + e = [fileData keyEnumerator];
  244 + while (key = [e nextObject]) {
  245 + NSString *filePath = [fileData objectForKey:key];
  246 + [postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",key,[filePath lastPathComponent]] dataUsingEncoding:NSUTF8StringEncoding]];
  247 + [postBody appendData:contentTypeHeader];
  248 + [postBody appendData:[NSData dataWithContentsOfMappedFile:filePath]];
  249 + [postBody appendData:endItemBoundary];
  250 + }
  251 +
  252 + [postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
  253 +
  254 + // Set the body.
  255 + CFHTTPMessageSetBody(request, (CFDataRef)postBody);
  256 +
  257 + postLength = [postBody length];
  258 + }
  259 +
  260 + [self loadRequest];
  261 +
  262 +}
  263 +
  264 +- (BOOL)complete
  265 +{
  266 + return complete;
  267 +}
  268 +
  269 +- (NSString *)dataString
  270 +{
  271 + if (!receivedData) {
  272 + return nil;
  273 + }
  274 + NSString *theData = [[[NSString alloc] initWithBytes:[(NSData *)receivedData bytes] length:[(NSData *)receivedData length] encoding:NSUTF8StringEncoding] autorelease];
  275 + return theData;
  276 +}
  277 +
  278 +//Subclasses can override this method to process the result in the same thread
  279 +//If not overidden, it will call the didFinishSelector on the delegate, if one has been setup
  280 +- (void)requestFinished
  281 +{
  282 + if (didFinishSelector) {
  283 + if ([delegate respondsToSelector:didFinishSelector]) {
  284 + [delegate performSelectorOnMainThread:didFinishSelector withObject:self waitUntilDone:YES];
  285 + }
  286 + }
  287 +}
  288 +
  289 +//Subclasses can override this method to perform error handling in the same thread
  290 +//If not overidden, it will call the didFailSelector on the delegate, if one has been setup
  291 +- (void)failWithProblem:(NSString *)problem
  292 +{
  293 + complete = YES;
  294 + error =[[NSError errorWithDomain:NetworkRequestErrorDomain
  295 + code:1
  296 + userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"An error occurred",@"Title",
  297 + problem,@"Description",nil]] retain];
  298 + NSLog(problem);
  299 +
  300 + if (didFailSelector) {
  301 + if ([delegate respondsToSelector:didFailSelector]) {
  302 + [delegate performSelectorOnMainThread:didFailSelector withObject:self waitUntilDone:YES];
  303 + }
  304 + }
  305 +}
  306 +
  307 +//Called by delegate to resume loading once authentication info has been populated
  308 +- (void)retryWithAuthentication
  309 +{
  310 + [authenticationLock lockWhenCondition:1];
  311 + [authenticationLock unlockWithCondition:2];
  312 +}
  313 +
  314 +- (void)loadRequest
  315 +{
  316 + //Callled twice during authentication test - fix this
  317 + [authenticationLock release];
  318 + authenticationLock = [[NSConditionLock alloc] initWithCondition:1];
  319 +
  320 + complete = NO;
  321 + totalBytesRead = 0;
  322 + contentLength = 0;
  323 + haveExaminedHeaders = NO;
  324 + receivedData = CFDataCreateMutable(NULL, 0);
  325 +
  326 + // Create the stream for the request.
  327 + readStream = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, request,readStream);
  328 + if (!readStream) {
  329 + [self failWithProblem:@"Unable to create read stream"];
  330 + return;
  331 + }
  332 +
  333 + // Set the client
  334 + CFStreamClientContext ctxt = {0, self, NULL, NULL, NULL};
  335 + if (!CFReadStreamSetClient(readStream, kNetworkEvents, ReadStreamClientCallBack, &ctxt)) {
  336 + CFRelease(readStream);
  337 + readStream = NULL;
  338 + [self failWithProblem:@"Unable to setup read stream"];
  339 + return;
  340 + }
  341 +
  342 + // Schedule the stream
  343 + CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
  344 +
  345 + // Start the HTTP connection
  346 + if (!CFReadStreamOpen(readStream)) {
  347 + CFReadStreamSetClient(readStream, 0, NULL, NULL);
  348 + CFReadStreamUnscheduleFromRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
  349 + CFRelease(readStream);
  350 + readStream = NULL;
  351 + [self failWithProblem:@"Unable to start http connection"];
  352 + return;
  353 + }
  354 +
  355 +
  356 + if (uploadProgressDelegate) {
  357 + [self performSelectorOnMainThread:@selector(resetUploadProgress:) withObject:[NSNumber numberWithDouble:postLength] waitUntilDone:YES];
  358 + }
  359 +
  360 + [self performSelectorOnMainThread:@selector(setupProgressTimer) withObject:nil waitUntilDone:YES];
  361 +
  362 +
  363 + // Wait for the request to finish
  364 + NSDate* endDate = [NSDate distantFuture];
  365 + while (!complete) {
  366 +
  367 + // See if our NSOperationQueue told us to cancel
  368 + if ([self isCancelled]) {
  369 + [self failWithProblem:@"The request was cancelled"];
  370 + [self cancelLoad];
  371 + complete = YES;
  372 + break;
  373 + }
  374 + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:endDate];
  375 + }
  376 +}
  377 +
  378 +
  379 +- (void)cancelLoad
  380 +{
  381 + if (readStream) {
  382 + CFReadStreamClose(readStream);
  383 + CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL);
  384 + CFReadStreamUnscheduleFromRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
  385 + CFRelease(readStream);
  386 + readStream = NULL;
  387 + }
  388 +
  389 + if (receivedData) {
  390 + CFRelease(receivedData);
  391 + receivedData = NULL;
  392 +
  393 + //If we were downloading to a file, let's remove it
  394 + } else if (downloadDestinationPath) {
  395 + [outputStream close];
  396 + [[NSFileManager defaultManager] removeFileAtPath:downloadDestinationPath handler:nil];
  397 + }
  398 +
  399 + haveExaminedHeaders = NO;
  400 +}
  401 +
  402 +
  403 +#pragma mark upload/download progress
  404 +
  405 +- (void)setupProgressTimer
  406 +{
  407 + progressTimer = [NSTimer
  408 + timerWithTimeInterval:PROGRESS_INDICATOR_TIMER_INTERVAL
  409 + target:self
  410 + selector:@selector(updateProgressIndicators)
  411 + userInfo:nil
  412 + repeats:YES];
  413 + [[NSRunLoop currentRunLoop] addTimer:progressTimer forMode:NSDefaultRunLoopMode];
  414 +}
  415 +
  416 +
  417 +- (void)updateProgressIndicators
  418 +{
  419 + [self updateUploadProgress];
  420 + [self updateDownloadProgress];
  421 +
  422 +}
  423 +
  424 +- (void)resetUploadProgress:(NSNumber *)max
  425 +{
  426 + [uploadProgressDelegate setMaxValue:[max doubleValue]/PROGRESS_INDICATOR_CHUNK_SIZE];
  427 + [uploadProgressDelegate setDoubleValue:0];
  428 +}
  429 +
  430 +- (void)updateUploadProgress
  431 +{
  432 + if (complete) {
  433 + [progressTimer invalidate];
  434 + progressTimer = nil;
  435 + [uploadProgressDelegate setDoubleValue:postLength];
  436 +
  437 + } else if (uploadProgressDelegate) {
  438 + CFNumberRef byteCount = (CFNumberRef)CFReadStreamCopyProperty (readStream, kCFStreamPropertyHTTPRequestBytesWrittenCount);
  439 + [uploadProgressDelegate setDoubleValue:[(NSNumber *)byteCount doubleValue]/PROGRESS_INDICATOR_CHUNK_SIZE];
  440 + }
  441 +}
  442 +
  443 +- (void)updateDownloadProgress
  444 +{
  445 + if (complete) {
  446 + [progressTimer invalidate];
  447 + progressTimer = nil;
  448 + [downloadProgressDelegate setDoubleValue:contentLength];
  449 +
  450 + } else if (downloadProgressDelegate) {
  451 + [downloadProgressDelegate setDoubleValue:totalBytesRead/PROGRESS_INDICATOR_CHUNK_SIZE];
  452 + }
  453 +}
  454 +
  455 +
  456 +- (void)resetDownloadProgress:(NSNumber *)max
  457 +{
  458 + [downloadProgressDelegate setMaxValue:[max doubleValue]/PROGRESS_INDICATOR_CHUNK_SIZE];
  459 + [downloadProgressDelegate setDoubleValue:0];
  460 +}
  461 +
  462 +
  463 +#pragma mark http authentication
  464 +
  465 +// Parse the response headers to get the content-length, and check to see if we need to authenticate
  466 +- (BOOL)isAuthorizationFailure
  467 + {
  468 + CFHTTPMessageRef responseHeaders = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader);
  469 + BOOL isAuthenticationChallenge = NO;
  470 + if (responseHeaders) {
  471 + if (CFHTTPMessageIsHeaderComplete(responseHeaders)) {
  472 + CFStringRef cLength = CFHTTPMessageCopyHeaderFieldValue(responseHeaders,CFSTR("Content-Length"));
  473 + if (cLength) {
  474 + contentLength = CFStringGetDoubleValue(cLength);
  475 + if (downloadProgressDelegate) {
  476 + [self performSelectorOnMainThread:@selector(resetDownloadProgress:) withObject:[NSNumber numberWithDouble:contentLength] waitUntilDone:YES];
  477 + }
  478 + CFRelease(cLength);
  479 + }
  480 +
  481 + // Is the server response a challenge for credentials?
  482 + isAuthenticationChallenge = (CFHTTPMessageGetResponseStatusCode(responseHeaders) == 401);
  483 + }
  484 + CFRelease(responseHeaders);
  485 +
  486 + }
  487 +
  488 +
  489 +
  490 + return isAuthenticationChallenge;
  491 +}
  492 +
  493 +- (void)applyCredentialsAndResume {
  494 + // Apply whatever credentials we've built up to the old request
  495 + if (!CFHTTPMessageApplyCredentialDictionary(request, authentication, credentials, NULL)) {
  496 + [self failWithProblem:@"Failed to apply credentials to request"];
  497 + } else {
  498 +
  499 + //If we have credentials and they're ok, let's save them to the keychain
  500 + if (usesKeychain) {
  501 + NSURLCredential *authenticationCredentials = [NSURLCredential credentialWithUser:(NSString *)CFDictionaryGetValue(credentials, kCFHTTPAuthenticationUsername)
  502 + password:(NSString *)CFDictionaryGetValue(credentials, kCFHTTPAuthenticationPassword)
  503 + persistence:NSURLCredentialPersistencePermanent];
  504 +
  505 + if (authenticationCredentials) {
  506 + [ASIHTTPRequest saveCredentials:authenticationCredentials forHost:[url host] port:[[url port] intValue] protocol:[url scheme] realm:authenticationRealm];
  507 + }
  508 + }
  509 +
  510 + // Now that we've updated our request, retry the load
  511 + [self loadRequest];
  512 + }
  513 +}
  514 +
  515 +
  516 +- (void)applyCredentialsLoad
  517 +{
  518 + // Get the authentication information
  519 + if (!authentication) {
  520 + CFHTTPMessageRef responseHeader = (CFHTTPMessageRef) CFReadStreamCopyProperty(readStream,kCFStreamPropertyHTTPResponseHeader);
  521 + authentication = CFHTTPAuthenticationCreateFromResponse(NULL, responseHeader);
  522 + CFRelease(responseHeader);
  523 + }
  524 + CFStreamError err;
  525 + if (!authentication) {
  526 + // the newly created authentication object is bad, must return
  527 + [self failWithProblem:@"Failed to get authentication object from response headers"];
  528 + return;
  529 +
  530 +
  531 + //Authentication is not valid, we need to get new ones
  532 + } else if (!CFHTTPAuthenticationIsValid(authentication, &err)) {
  533 +
  534 + // destroy authentication and credentials
  535 + if (credentials) {
  536 + CFRelease(credentials);
  537 + credentials = NULL;
  538 + }
  539 + CFRelease(authentication);
  540 + authentication = NULL;
  541 +
  542 + // check for bad credentials (to be treated separately)
  543 + if (err.domain == kCFStreamErrorDomainHTTP && (err.error == kCFStreamErrorHTTPAuthenticationBadUserName || err.error == kCFStreamErrorHTTPAuthenticationBadPassword)) {
  544 + ignoreError = YES;
  545 + if ([delegate respondsToSelector:@selector(authorizationNeededForRequest:)]) {
  546 + [delegate performSelectorOnMainThread:@selector(authorizationNeededForRequest:) withObject:self waitUntilDone:YES];
  547 + [authenticationLock lockWhenCondition:2];
  548 + [authenticationLock unlock];
  549 + [self applyCredentialsLoad];
  550 + return;
  551 + }
  552 + [self failWithProblem:@"Waiting for authentication"];
  553 + complete = YES;
  554 + return;
  555 + } else {
  556 + [self failWithProblem:@"An authentication problem occurred"];
  557 + return;
  558 + }
  559 +
  560 +
  561 + } else {
  562 +
  563 + [self cancelLoad];
  564 +
  565 + if (credentials) {
  566 + [self applyCredentialsAndResume];
  567 +
  568 + // are a user name & password needed?
  569 + } else if (CFHTTPAuthenticationRequiresUserNameAndPassword(authentication)) {
  570 +
  571 +
  572 + // Build the credentials dictionary
  573 + credentials = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
  574 +
  575 +
  576 + [authenticationRealm release];
  577 + authenticationRealm = nil;
  578 +
  579 + // Get the authentication realm
  580 + if (!CFHTTPAuthenticationRequiresAccountDomain(authentication)) {
  581 + authenticationRealm = (NSString *)CFHTTPAuthenticationCopyRealm(authentication);
  582 + }
  583 +
  584 + //First, let's look at the url to see if the username and password were included
  585 + CFStringRef user = (CFStringRef)[url user];
  586 + CFStringRef pass = (CFStringRef)[url password];
  587 +
  588 + //If the username and password weren't in the url, let's try to use the ones set in this object
  589 + if ((!user || !pass) && username && password) {
  590 + user = (CFStringRef)username;
  591 + pass = (CFStringRef)password;
  592 + }
  593 +
  594 + //Ok, that didn't work, let's try the keychain
  595 + if ((!user || !pass) && usesKeychain) {
  596 +
  597 + NSURLCredential *authenticationCredentials = [ASIHTTPRequest savedCredentialsForHost:[url host] port:[[url port] intValue] protocol:[url scheme] realm:authenticationRealm];
  598 + if (authenticationCredentials) {
  599 + user = (CFStringRef)[authenticationCredentials user];
  600 + pass = (CFStringRef)[authenticationCredentials password];
  601 + }
  602 +
  603 + }
  604 +
  605 + //If we have a username and password, let's apply them to the request and continue
  606 + if (user && pass) {
  607 +
  608 + CFDictionarySetValue(credentials, kCFHTTPAuthenticationUsername, user);
  609 + CFDictionarySetValue(credentials, kCFHTTPAuthenticationPassword, pass);
  610 +
  611 + [self applyCredentialsAndResume];
  612 + return;
  613 + }
  614 + if (credentials) {
  615 + CFRelease(credentials);
  616 + credentials = NULL;
  617 + }
  618 + //We've got no credentials, let's ask the delegate to sort this out
  619 + ignoreError = YES;
  620 + if ([delegate respondsToSelector:@selector(authorizationNeededForRequest:)]) {
  621 + [delegate performSelectorOnMainThread:@selector(authorizationNeededForRequest:) withObject:self waitUntilDone:YES];
  622 + [authenticationLock lockWhenCondition:2];
  623 + [authenticationLock unlock];
  624 + [self applyCredentialsLoad];
  625 + return;
  626 + }
  627 + [self failWithProblem:@"Waiting for authentication"];
  628 + complete = YES;
  629 + return;
  630 +
  631 +
  632 + //We don't need a username or password, let's carry on
  633 + } else {
  634 + [self applyCredentialsAndResume];
  635 + }
  636 + }
  637 +}
  638 +
  639 +
  640 +#pragma mark stream status handlers
  641 +
  642 +
  643 +- (void)handleNetworkEvent:(CFStreamEventType)type
  644 +{
  645 +
  646 + // Dispatch the stream events.
  647 + switch (type) {
  648 + case kCFStreamEventHasBytesAvailable:
  649 + [self handleBytesAvailable];
  650 + break;
  651 +
  652 + case kCFStreamEventEndEncountered:
  653 + [self handleStreamComplete];
  654 + break;
  655 +
  656 + case kCFStreamEventErrorOccurred:
  657 + [self handleStreamError];
  658 + break;
  659 +
  660 + default:
  661 + break;
  662 + }
  663 +}
  664 +
  665 +
  666 +- (void)handleBytesAvailable
  667 +{
  668 +
  669 + if (!haveExaminedHeaders) {
  670 + haveExaminedHeaders = YES;
  671 + if ([self isAuthorizationFailure]) {
  672 + [self applyCredentialsLoad];
  673 + return;
  674 + }
  675 + }
  676 +
  677 + UInt8 buffer[2048];
  678 + CFIndex bytesRead = CFReadStreamRead(readStream, buffer, sizeof(buffer));
  679 +
  680 +
  681 + // Less than zero is an error
  682 + if (bytesRead < 0) {
  683 + [self handleStreamError];
  684 +
  685 + // If zero bytes were read, wait for the EOF to come.
  686 + } else if (bytesRead) {
  687 +
  688 + totalBytesRead += bytesRead;
  689 +
  690 + // Are we downloading to a file?
  691 + if (downloadDestinationPath) {
  692 + if (!outputStream) {
  693 + outputStream = [[NSOutputStream alloc] initToFileAtPath:downloadDestinationPath append:NO];
  694 + [outputStream open];
  695 + }
  696 + [outputStream write:buffer maxLength:bytesRead];
  697 +
  698 + //Otherwise, let's add the data to our in-memory store
  699 + } else {
  700 + CFDataAppendBytes(receivedData, buffer, bytesRead);
  701 + }
  702 + }
  703 +}
  704 +
  705 +
  706 +- (void)handleStreamComplete
  707 +{
  708 + complete = YES;
  709 + [self updateUploadProgress];
  710 + [self updateDownloadProgress];
  711 + if (readStream) {
  712 + CFReadStreamClose(readStream);
  713 + CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL);
  714 + CFReadStreamUnscheduleFromRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
  715 + CFRelease(readStream);
  716 + readStream = NULL;
  717 + }
  718 +
  719 + //close the output stream as we're done writing to the file
  720 + if (downloadDestinationPath) {
  721 + [outputStream close];
  722 + }
  723 +
  724 + [self requestFinished];
  725 +}
  726 +
  727 +
  728 +- (void)handleStreamError
  729 +{
  730 + complete = YES;
  731 + NSError *err = [(NSError *)CFReadStreamCopyError(readStream) autorelease];
  732 +
  733 + [self cancelLoad];
  734 +
  735 + if (!error) { //We may already have handled this error
  736 + [self failWithProblem:[NSString stringWithFormat: @"An error occurred: %@",[err localizedDescription]]];
  737 + }
  738 +
  739 +
  740 +}
  741 +
  742 +
  743 +#pragma mark keychain storage
  744 +
  745 ++ (void)saveCredentials:(NSURLCredential *)credentials forHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm
  746 +{
  747 + NSURLProtectionSpace *protectionSpace = [[[NSURLProtectionSpace alloc] initWithHost:host
  748 + port:port
  749 + protocol:protocol
  750 + realm:realm
  751 + authenticationMethod:NSURLAuthenticationMethodDefault] autorelease];
  752 +
  753 +
  754 + NSURLCredentialStorage *storage = [NSURLCredentialStorage sharedCredentialStorage];
  755 + [storage setDefaultCredential:credentials forProtectionSpace:protectionSpace];
  756 +}
  757 +
  758 ++ (NSURLCredential *)savedCredentialsForHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm
  759 +{
  760 + NSURLProtectionSpace *protectionSpace = [[[NSURLProtectionSpace alloc] initWithHost:host
  761 + port:port
  762 + protocol:protocol
  763 + realm:realm
  764 + authenticationMethod:NSURLAuthenticationMethodDefault] autorelease];
  765 +
  766 +
  767 + NSURLCredentialStorage *storage = [NSURLCredentialStorage sharedCredentialStorage];
  768 + return [storage defaultCredentialForProtectionSpace:protectionSpace];
  769 +}
  770 +
  771 +
  772 +
  773 +
  774 +
  775 +@end
  1 +//
  2 +// ASIProgressDelegate.h
  3 +//
  4 +// Created by Ben Copsey on 28/03/2008.
  5 +// Copyright 2008 All-Seeing Interactive. All rights reserved
  6 +//
  7 +
  8 +#import <Cocoa/Cocoa.h>
  9 +
  10 +@protocol ASIProgressDelegate
  11 +
  12 +- (void)incrementProgress;
  13 +- (void)setDoubleValue:(double)newValue;
  14 +- (void)incrementBy:(double)amount;
  15 +- (void)setMaxValue:(double)newMax;
  16 +@end
  1 +//
  2 +// AppDelegate.h
  3 +//
  4 +// Created by Ben Copsey on 09/07/2008.
  5 +// Copyright 2008 All-Seeing Interactive Ltd. All rights reserved.
  6 +//
  7 +
  8 +#import <Cocoa/Cocoa.h>
  9 +@class ASIHTTPRequest;
  10 +
  11 +@interface AppDelegate : NSObject {
  12 + NSOperationQueue *networkQueue;
  13 + IBOutlet NSProgressIndicator *progressIndicator;
  14 + IBOutlet NSTextView *htmlSource;
  15 + IBOutlet NSTextField *fileLocation;
  16 + IBOutlet NSWindow *window;
  17 + IBOutlet NSWindow *loginWindow;
  18 +
  19 + IBOutlet NSTextField *host;
  20 + IBOutlet NSTextField *realm;
  21 + IBOutlet NSTextField *username;
  22 + IBOutlet NSTextField *password;
  23 +
  24 + IBOutlet NSTextField *topSecretInfo;
  25 + IBOutlet NSButton *keychainCheckbox;
  26 +
  27 + IBOutlet NSImageView *imageView1;
  28 + IBOutlet NSImageView *imageView2;
  29 + IBOutlet NSImageView *imageView3;
  30 +}
  31 +
  32 +- (IBAction)simpleURLFetch:(id)sender;
  33 +- (IBAction)URLFetchWithProgress:(id)sender;
  34 +
  35 +
  36 +- (IBAction)fetchThreeImages:(id)sender;
  37 +
  38 +- (void)authorizationNeededForRequest:(ASIHTTPRequest *)request;
  39 +- (IBAction)dismissAuthSheet:(id)sender;
  40 +- (IBAction)fetchTopSecretInformation:(id)sender;
  41 +
  42 +- (IBAction)postWithProgress:(id)sender;
  43 +@end
  1 +//
  2 +// AppDelegate.m
  3 +//
  4 +// Created by Ben Copsey on 09/07/2008.
  5 +// Copyright 2008 All-Seeing Interactive Ltd. All rights reserved.
  6 +//
  7 +
  8 +#import "AppDelegate.h"
  9 +#import "ASIHTTPRequest.h"
  10 +
  11 +@implementation AppDelegate
  12 +
  13 +- (id)init
  14 +{
  15 + [super init];
  16 + networkQueue = [[NSOperationQueue alloc] init];
  17 + return self;
  18 +}
  19 +
  20 +- (void)dealloc
  21 +{
  22 + [networkQueue release];
  23 + [super dealloc];
  24 +}
  25 +
  26 +
  27 +- (IBAction)simpleURLFetch:(id)sender
  28 +{
  29 + ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]] autorelease];
  30 + [request start];
  31 + if ([request dataString]) {
  32 + [htmlSource setString:[request dataString]];
  33 + }
  34 +}
  35 +
  36 +
  37 +- (IBAction)URLFetchWithProgress:(id)sender
  38 +{
  39 + [networkQueue cancelAllOperations];
  40 + ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://trails-network.net/Downloads/MemexTrails_1.0b1.zip"]] autorelease];
  41 + [request setDelegate:self];
  42 + [request setDownloadProgressDelegate:progressIndicator];
  43 + [request setDidFinishSelector:@selector(URLFetchWithProgressComplete:)];
  44 + [request setDownloadDestinationPath:[[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"MemexTrails_1.0b1.zip"]];
  45 + [networkQueue addOperation:request];
  46 +}
  47 +
  48 +- (void)URLFetchWithProgressComplete:(ASIHTTPRequest *)request
  49 +{
  50 + if ([request error]) {
  51 + [fileLocation setStringValue:[NSString stringWithFormat:@"An error occurred: %@",[[[request error] userInfo] objectForKey:@"Title"]]];
  52 + } else {
  53 + [fileLocation setStringValue:[NSString stringWithFormat:@"File downloaded to %@",[request downloadDestinationPath]]];
  54 + }
  55 +}
  56 +
  57 +- (IBAction)fetchThreeImages:(id)sender
  58 +{
  59 + [imageView1 setImage:nil];
  60 + [imageView2 setImage:nil];
  61 + [imageView3 setImage:nil];
  62 +
  63 + [networkQueue cancelAllOperations];
  64 + [progressIndicator setDoubleValue:0];
  65 + [progressIndicator setMaxValue:3];
  66 + ASIHTTPRequest *request;
  67 + request = [[[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://allseeing-i.com/i/logo.png"]] autorelease];
  68 + [request setDelegate:self];
  69 + [request setDidFinishSelector:@selector(imageFetchComplete:)];
  70 + [request setDownloadDestinationPath:[[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"1.png"]];
  71 + [networkQueue addOperation:request];
  72 +
  73 + request = [[[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://allseeing-i.com/i/trailsnetwork.png"]] autorelease];
  74 + [request setDelegate:self];
  75 + [request setDidFinishSelector:@selector(imageFetchComplete:)];
  76 + [request setDownloadDestinationPath:[[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"2.png"]];
  77 + [networkQueue addOperation:request];
  78 +
  79 + request = [[[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://allseeing-i.com/i/sharedspace20.png"]] autorelease];
  80 + [request setDelegate:self];
  81 + [request setDidFinishSelector:@selector(imageFetchComplete:)];
  82 + [request setDownloadDestinationPath:[[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"3.png"]];
  83 + [networkQueue addOperation:request];
  84 +}
  85 +
  86 +
  87 +- (void)imageFetchComplete:(ASIHTTPRequest *)request
  88 +{
  89 + NSImage *img = [[[NSImage alloc] initWithContentsOfFile:[request downloadDestinationPath]] autorelease];
  90 + if (img) {
  91 + if ([imageView1 image]) {
  92 + if ([imageView2 image]) {
  93 + [imageView3 setImage:img];
  94 + } else {
  95 + [imageView2 setImage:img];
  96 + }
  97 + } else {
  98 + [imageView1 setImage:img];
  99 + }
  100 + }
  101 + [progressIndicator incrementBy:1];
  102 +
  103 +}
  104 +
  105 +
  106 +- (IBAction)fetchTopSecretInformation:(id)sender
  107 +{
  108 + [networkQueue cancelAllOperations];
  109 + [progressIndicator setDoubleValue:0];
  110 + ASIHTTPRequest *request;
  111 + request = [[[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://allseeing-i.com/top_secret/"]] autorelease];
  112 + [request setDelegate:self];
  113 + [request setDidFinishSelector:@selector(topSecretFetchComplete:)];
  114 + [request setUsesKeychain:[keychainCheckbox state]];
  115 + [networkQueue addOperation:request];
  116 +
  117 +}
  118 +
  119 +- (IBAction)topSecretFetchComplete:(ASIHTTPRequest *)request
  120 +{
  121 + if (![request error]) {
  122 + [topSecretInfo setStringValue:[request dataString]];
  123 + [topSecretInfo setFont:[NSFont boldSystemFontOfSize:13]];
  124 + }
  125 +}
  126 +
  127 +- (void)authorizationNeededForRequest:(ASIHTTPRequest *)request
  128 +{
  129 + [realm setStringValue:[request authenticationRealm]];
  130 + [host setStringValue:[request host]];
  131 +
  132 + [NSApp beginSheet: loginWindow
  133 + modalForWindow: window
  134 + modalDelegate: self
  135 + didEndSelector: @selector(authSheetDidEnd:returnCode:contextInfo:)
  136 + contextInfo: request];
  137 +}
  138 +
  139 +- (IBAction)dismissAuthSheet:(id)sender {
  140 + [[NSApplication sharedApplication] endSheet: loginWindow returnCode: [(NSControl*)sender tag]];
  141 +}
  142 +
  143 +- (void)authSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo {
  144 + ASIHTTPRequest *request = (ASIHTTPRequest *)contextInfo;
  145 + if (returnCode == NSOKButton) {
  146 + [request setUsername:[[[username stringValue] copy] autorelease] andPassword:[[[password stringValue] copy] autorelease]];
  147 + [request retryWithAuthentication];
  148 + } else {
  149 + [request cancelLoad];
  150 + }
  151 + [loginWindow orderOut: self];
  152 +}
  153 +
  154 +- (IBAction)postWithProgress:(id)sender
  155 +{
  156 + //Create a 1mb file
  157 + NSMutableData *data = [NSMutableData dataWithLength:1024*1024];
  158 + NSString *path = [[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"bigfile"];
  159 + [data writeToFile:path atomically:NO];
  160 +
  161 + [networkQueue cancelAllOperations];
  162 + [progressIndicator setDoubleValue:0];
  163 + ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ignore"]] autorelease];
  164 + [request setDelegate:self];
  165 + [request setUploadProgressDelegate:progressIndicator];
  166 + [request setPostValue:@"test" forKey:@"value1"];
  167 + [request setPostValue:@"test" forKey:@"value2"];
  168 + [request setPostValue:@"test" forKey:@"value3"];
  169 +
  170 + [request setFile:path forKey:@"file"];
  171 +
  172 + [networkQueue addOperation:request];
  173 +
  174 +}
  175 +
  176 +
  177 +
  178 +@end
1 B/* Localized versions of Info.plist keys */ 1 B/* Localized versions of Info.plist keys */
This diff could not be displayed because it is too large.
No preview for this file type
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>CFBundleDevelopmentRegion</key>
  6 + <string>English</string>
  7 + <key>CFBundleExecutable</key>
  8 + <string>${EXECUTABLE_NAME}</string>
  9 + <key>CFBundleIconFile</key>
  10 + <string></string>
  11 + <key>CFBundleIdentifier</key>
  12 + <string>com.allseeing-i.asi-http-request</string>
  13 + <key>CFBundleInfoDictionaryVersion</key>
  14 + <string>6.0</string>
  15 + <key>CFBundleName</key>
  16 + <string>${PRODUCT_NAME}</string>
  17 + <key>CFBundlePackageType</key>
  18 + <string>APPL</string>
  19 + <key>CFBundleSignature</key>
  20 + <string>????</string>
  21 + <key>CFBundleVersion</key>
  22 + <string>1.0</string>
  23 + <key>NSMainNibFile</key>
  24 + <string>MainMenu</string>
  25 + <key>NSPrincipalClass</key>
  26 + <string>NSApplication</string>
  27 +</dict>
  28 +</plist>
  1 +* Copyright (c) 2007-2008, All-Seeing Interactive
  2 +* All rights reserved.
  3 +*
  4 +* Redistribution and use in source and binary forms, with or without
  5 +* modification, are permitted provided that the following conditions are met:
  6 +* * Redistributions of source code must retain the above copyright
  7 +* notice, this list of conditions and the following disclaimer.
  8 +* * Redistributions in binary form must reproduce the above copyright
  9 +* notice, this list of conditions and the following disclaimer in the
  10 +* documentation and/or other materials provided with the distribution.
  11 +* * Neither the name of the All-Seeing Interactive nor the
  12 +* names of its contributors may be used to endorse or promote products
  13 +* derived from this software without specific prior written permission.
  14 +*
  15 +* THIS SOFTWARE IS PROVIDED BY All-Seeing Interactive ''AS IS'' AND ANY
  16 +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17 +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18 +* DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
  19 +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20 +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21 +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  22 +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23 +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  24 +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>ActivePerspectiveName</key>
  6 + <string>Project</string>
  7 + <key>AllowedModules</key>
  8 + <array>
  9 + <dict>
  10 + <key>BundleLoadPath</key>
  11 + <string></string>
  12 + <key>MaxInstances</key>
  13 + <string>n</string>
  14 + <key>Module</key>
  15 + <string>PBXSmartGroupTreeModule</string>
  16 + <key>Name</key>
  17 + <string>Groups and Files Outline View</string>
  18 + </dict>
  19 + <dict>
  20 + <key>BundleLoadPath</key>
  21 + <string></string>
  22 + <key>MaxInstances</key>
  23 + <string>n</string>
  24 + <key>Module</key>
  25 + <string>PBXNavigatorGroup</string>
  26 + <key>Name</key>
  27 + <string>Editor</string>
  28 + </dict>
  29 + <dict>
  30 + <key>BundleLoadPath</key>
  31 + <string></string>
  32 + <key>MaxInstances</key>
  33 + <string>n</string>
  34 + <key>Module</key>
  35 + <string>XCTaskListModule</string>
  36 + <key>Name</key>
  37 + <string>Task List</string>
  38 + </dict>
  39 + <dict>
  40 + <key>BundleLoadPath</key>
  41 + <string></string>
  42 + <key>MaxInstances</key>
  43 + <string>n</string>
  44 + <key>Module</key>
  45 + <string>XCDetailModule</string>
  46 + <key>Name</key>
  47 + <string>File and Smart Group Detail Viewer</string>
  48 + </dict>
  49 + <dict>
  50 + <key>BundleLoadPath</key>
  51 + <string></string>
  52 + <key>MaxInstances</key>
  53 + <string>1</string>
  54 + <key>Module</key>
  55 + <string>PBXBuildResultsModule</string>
  56 + <key>Name</key>
  57 + <string>Detailed Build Results Viewer</string>
  58 + </dict>
  59 + <dict>
  60 + <key>BundleLoadPath</key>
  61 + <string></string>
  62 + <key>MaxInstances</key>
  63 + <string>1</string>
  64 + <key>Module</key>
  65 + <string>PBXProjectFindModule</string>
  66 + <key>Name</key>
  67 + <string>Project Batch Find Tool</string>
  68 + </dict>
  69 + <dict>
  70 + <key>BundleLoadPath</key>
  71 + <string></string>
  72 + <key>MaxInstances</key>
  73 + <string>n</string>
  74 + <key>Module</key>
  75 + <string>XCProjectFormatConflictsModule</string>
  76 + <key>Name</key>
  77 + <string>Project Format Conflicts List</string>
  78 + </dict>
  79 + <dict>
  80 + <key>BundleLoadPath</key>
  81 + <string></string>
  82 + <key>MaxInstances</key>
  83 + <string>n</string>
  84 + <key>Module</key>
  85 + <string>PBXBookmarksModule</string>
  86 + <key>Name</key>
  87 + <string>Bookmarks Tool</string>
  88 + </dict>
  89 + <dict>
  90 + <key>BundleLoadPath</key>
  91 + <string></string>
  92 + <key>MaxInstances</key>
  93 + <string>n</string>
  94 + <key>Module</key>
  95 + <string>PBXClassBrowserModule</string>
  96 + <key>Name</key>
  97 + <string>Class Browser</string>
  98 + </dict>
  99 + <dict>
  100 + <key>BundleLoadPath</key>
  101 + <string></string>
  102 + <key>MaxInstances</key>
  103 + <string>n</string>
  104 + <key>Module</key>
  105 + <string>PBXCVSModule</string>
  106 + <key>Name</key>
  107 + <string>Source Code Control Tool</string>
  108 + </dict>
  109 + <dict>
  110 + <key>BundleLoadPath</key>
  111 + <string></string>
  112 + <key>MaxInstances</key>
  113 + <string>n</string>
  114 + <key>Module</key>
  115 + <string>PBXDebugBreakpointsModule</string>
  116 + <key>Name</key>
  117 + <string>Debug Breakpoints Tool</string>
  118 + </dict>
  119 + <dict>
  120 + <key>BundleLoadPath</key>
  121 + <string></string>
  122 + <key>MaxInstances</key>
  123 + <string>n</string>
  124 + <key>Module</key>
  125 + <string>XCDockableInspector</string>
  126 + <key>Name</key>
  127 + <string>Inspector</string>
  128 + </dict>
  129 + <dict>
  130 + <key>BundleLoadPath</key>
  131 + <string></string>
  132 + <key>MaxInstances</key>
  133 + <string>n</string>
  134 + <key>Module</key>
  135 + <string>PBXOpenQuicklyModule</string>
  136 + <key>Name</key>
  137 + <string>Open Quickly Tool</string>
  138 + </dict>
  139 + <dict>
  140 + <key>BundleLoadPath</key>
  141 + <string></string>
  142 + <key>MaxInstances</key>
  143 + <string>1</string>
  144 + <key>Module</key>
  145 + <string>PBXDebugSessionModule</string>
  146 + <key>Name</key>
  147 + <string>Debugger</string>
  148 + </dict>
  149 + <dict>
  150 + <key>BundleLoadPath</key>
  151 + <string></string>
  152 + <key>MaxInstances</key>
  153 + <string>1</string>
  154 + <key>Module</key>
  155 + <string>PBXDebugCLIModule</string>
  156 + <key>Name</key>
  157 + <string>Debug Console</string>
  158 + </dict>
  159 + <dict>
  160 + <key>BundleLoadPath</key>
  161 + <string></string>
  162 + <key>MaxInstances</key>
  163 + <string>n</string>
  164 + <key>Module</key>
  165 + <string>XCSnapshotModule</string>
  166 + <key>Name</key>
  167 + <string>Snapshots Tool</string>
  168 + </dict>
  169 + </array>
  170 + <key>BundlePath</key>
  171 + <string>/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources</string>
  172 + <key>Description</key>
  173 + <string>DefaultDescriptionKey</string>
  174 + <key>DockingSystemVisible</key>
  175 + <false/>
  176 + <key>Extension</key>
  177 + <string>mode1v3</string>
  178 + <key>FavBarConfig</key>
  179 + <dict>
  180 + <key>PBXProjectModuleGUID</key>
  181 + <string>B5ABC7B40E24C52A0072F422</string>
  182 + <key>XCBarModuleItemNames</key>
  183 + <dict/>
  184 + <key>XCBarModuleItems</key>
  185 + <array/>
  186 + </dict>
  187 + <key>FirstTimeWindowDisplayed</key>
  188 + <false/>
  189 + <key>Identifier</key>
  190 + <string>com.apple.perspectives.project.mode1v3</string>
  191 + <key>MajorVersion</key>
  192 + <integer>33</integer>
  193 + <key>MinorVersion</key>
  194 + <integer>0</integer>
  195 + <key>Name</key>
  196 + <string>Default</string>
  197 + <key>Notifications</key>
  198 + <array/>
  199 + <key>OpenEditors</key>
  200 + <array>
  201 + <dict>
  202 + <key>Content</key>
  203 + <dict>
  204 + <key>PBXProjectModuleGUID</key>
  205 + <string>B513D4520E2BE8A9000A50C6</string>
  206 + <key>PBXProjectModuleLabel</key>
  207 + <string>ASIHTTPRequest.m</string>
  208 + <key>PBXSplitModuleInNavigatorKey</key>
  209 + <dict>
  210 + <key>Split0</key>
  211 + <dict>
  212 + <key>PBXProjectModuleGUID</key>
  213 + <string>B513D4530E2BE8A9000A50C6</string>
  214 + <key>PBXProjectModuleLabel</key>
  215 + <string>ASIHTTPRequest.m</string>
  216 + <key>_historyCapacity</key>
  217 + <integer>0</integer>
  218 + <key>bookmark</key>
  219 + <string>B513D49B0E2BF854000A50C6</string>
  220 + <key>history</key>
  221 + <array>
  222 + <string>B513D4110E2BE42A000A50C6</string>
  223 + </array>
  224 + </dict>
  225 + <key>SplitCount</key>
  226 + <string>1</string>
  227 + </dict>
  228 + <key>StatusBarVisibility</key>
  229 + <true/>
  230 + </dict>
  231 + <key>Geometry</key>
  232 + <dict>
  233 + <key>Frame</key>
  234 + <string>{{0, 20}, {1475, 777}}</string>
  235 + <key>PBXModuleWindowStatusBarHidden2</key>
  236 + <false/>
  237 + <key>RubberWindowFrame</key>
  238 + <string>190 -332 1475 818 0 0 1440 878 </string>
  239 + </dict>
  240 + </dict>
  241 + </array>
  242 + <key>PerspectiveWidths</key>
  243 + <array>
  244 + <integer>-1</integer>
  245 + <integer>-1</integer>
  246 + </array>
  247 + <key>Perspectives</key>
  248 + <array>
  249 + <dict>
  250 + <key>ChosenToolbarItems</key>
  251 + <array>
  252 + <string>active-target-popup</string>
  253 + <string>active-buildstyle-popup</string>
  254 + <string>action</string>
  255 + <string>NSToolbarFlexibleSpaceItem</string>
  256 + <string>buildOrClean</string>
  257 + <string>build-and-goOrGo</string>
  258 + <string>com.apple.ide.PBXToolbarStopButton</string>
  259 + <string>get-info</string>
  260 + <string>toggle-editor</string>
  261 + <string>NSToolbarFlexibleSpaceItem</string>
  262 + <string>com.apple.pbx.toolbar.searchfield</string>
  263 + </array>
  264 + <key>ControllerClassBaseName</key>
  265 + <string></string>
  266 + <key>IconName</key>
  267 + <string>WindowOfProjectWithEditor</string>
  268 + <key>Identifier</key>
  269 + <string>perspective.project</string>
  270 + <key>IsVertical</key>
  271 + <false/>
  272 + <key>Layout</key>
  273 + <array>
  274 + <dict>
  275 + <key>ContentConfiguration</key>
  276 + <dict>
  277 + <key>PBXBottomSmartGroupGIDs</key>
  278 + <array>
  279 + <string>1C37FBAC04509CD000000102</string>
  280 + <string>1C37FAAC04509CD000000102</string>
  281 + <string>1C08E77C0454961000C914BD</string>
  282 + <string>1C37FABC05509CD000000102</string>
  283 + <string>1C37FABC05539CD112110102</string>
  284 + <string>E2644B35053B69B200211256</string>
  285 + <string>1C37FABC04509CD000100104</string>
  286 + <string>1CC0EA4004350EF90044410B</string>
  287 + <string>1CC0EA4004350EF90041110B</string>
  288 + </array>
  289 + <key>PBXProjectModuleGUID</key>
  290 + <string>1CE0B1FE06471DED0097A5F4</string>
  291 + <key>PBXProjectModuleLabel</key>
  292 + <string>Files</string>
  293 + <key>PBXProjectStructureProvided</key>
  294 + <string>yes</string>
  295 + <key>PBXSmartGroupTreeModuleColumnData</key>
  296 + <dict>
  297 + <key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
  298 + <array>
  299 + <real>186</real>
  300 + </array>
  301 + <key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
  302 + <array>
  303 + <string>MainColumn</string>
  304 + </array>
  305 + </dict>
  306 + <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
  307 + <dict>
  308 + <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
  309 + <array>
  310 + <string>29B97314FDCFA39411CA2CEA</string>
  311 + <string>080E96DDFE201D6D7F000001</string>
  312 + <string>29B97317FDCFA39411CA2CEA</string>
  313 + <string>1C37FABC05509CD000000102</string>
  314 + </array>
  315 + <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
  316 + <array>
  317 + <array>
  318 + <integer>5</integer>
  319 + <integer>1</integer>
  320 + <integer>0</integer>
  321 + </array>
  322 + </array>
  323 + <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
  324 + <string>{{0, 0}, {186, 681}}</string>
  325 + </dict>
  326 + <key>PBXTopSmartGroupGIDs</key>
  327 + <array/>
  328 + <key>XCIncludePerspectivesSwitch</key>
  329 + <true/>
  330 + <key>XCSharingToken</key>
  331 + <string>com.apple.Xcode.GFSharingToken</string>
  332 + </dict>
  333 + <key>GeometryConfiguration</key>
  334 + <dict>
  335 + <key>Frame</key>
  336 + <string>{{0, 0}, {203, 699}}</string>
  337 + <key>GroupTreeTableConfiguration</key>
  338 + <array>
  339 + <string>MainColumn</string>
  340 + <real>186</real>
  341 + </array>
  342 + <key>RubberWindowFrame</key>
  343 + <string>308 138 1121 740 0 0 1440 878 </string>
  344 + </dict>
  345 + <key>Module</key>
  346 + <string>PBXSmartGroupTreeModule</string>
  347 + <key>Proportion</key>
  348 + <string>203pt</string>
  349 + </dict>
  350 + <dict>
  351 + <key>Dock</key>
  352 + <array>
  353 + <dict>
  354 + <key>BecomeActive</key>
  355 + <true/>
  356 + <key>ContentConfiguration</key>
  357 + <dict>
  358 + <key>PBXProjectModuleGUID</key>
  359 + <string>1CE0B20306471E060097A5F4</string>
  360 + <key>PBXProjectModuleLabel</key>
  361 + <string>ASIHTTPRequest.m</string>
  362 + <key>PBXSplitModuleInNavigatorKey</key>
  363 + <dict>
  364 + <key>Split0</key>
  365 + <dict>
  366 + <key>PBXProjectModuleGUID</key>
  367 + <string>1CE0B20406471E060097A5F4</string>
  368 + <key>PBXProjectModuleLabel</key>
  369 + <string>ASIHTTPRequest.m</string>
  370 + <key>_historyCapacity</key>
  371 + <integer>0</integer>
  372 + <key>bookmark</key>
  373 + <string>B513D49A0E2BF854000A50C6</string>
  374 + <key>history</key>
  375 + <array>
  376 + <string>B513D3E90E2BD48A000A50C6</string>
  377 + <string>B513D3EA0E2BD48A000A50C6</string>
  378 + <string>B513D4170E2BE8A9000A50C6</string>
  379 + <string>B513D41B0E2BE8A9000A50C6</string>
  380 + <string>B513D4930E2BF854000A50C6</string>
  381 + <string>B513D4940E2BF854000A50C6</string>
  382 + <string>B513D4950E2BF854000A50C6</string>
  383 + </array>
  384 + <key>prevStack</key>
  385 + <array>
  386 + <string>B5ABC8250E24CDE70072F422</string>
  387 + <string>B5ABC8260E24CDE70072F422</string>
  388 + <string>B5ABC8280E24CDE70072F422</string>
  389 + <string>B5ABC82F0E24CDE70072F422</string>
  390 + <string>B5ABC8300E24CDE70072F422</string>
  391 + <string>B513D25D0E2B507F000A50C6</string>
  392 + <string>B513D25E0E2B507F000A50C6</string>
  393 + <string>B513D2750E2B5152000A50C6</string>
  394 + <string>B513D2760E2B5152000A50C6</string>
  395 + <string>B513D2770E2B5152000A50C6</string>
  396 + <string>B513D2850E2B522F000A50C6</string>
  397 + <string>B513D2860E2B522F000A50C6</string>
  398 + <string>B513D2870E2B522F000A50C6</string>
  399 + <string>B513D2880E2B522F000A50C6</string>
  400 + <string>B513D2890E2B522F000A50C6</string>
  401 + <string>B513D28F0E2B524B000A50C6</string>
  402 + <string>B513D2900E2B524B000A50C6</string>
  403 + <string>B513D2950E2B5259000A50C6</string>
  404 + <string>B513D2960E2B5259000A50C6</string>
  405 + <string>B513D2A00E2B52F3000A50C6</string>
  406 + <string>B513D2A10E2B52F3000A50C6</string>
  407 + <string>B513D2AA0E2B542B000A50C6</string>
  408 + <string>B513D2C60E2B562C000A50C6</string>
  409 + <string>B513D2C70E2B562C000A50C6</string>
  410 + <string>B513D2CF0E2B56C6000A50C6</string>
  411 + <string>B513D2D60E2B56FF000A50C6</string>
  412 + <string>B513D2D70E2B56FF000A50C6</string>
  413 + <string>B513D2D80E2B56FF000A50C6</string>
  414 + <string>B513D2DD0E2B575C000A50C6</string>
  415 + <string>B513D2DE0E2B575C000A50C6</string>
  416 + <string>B513D2E40E2B57B7000A50C6</string>
  417 + <string>B513D2E50E2B57B7000A50C6</string>
  418 + <string>B513D2E60E2B57B7000A50C6</string>
  419 + <string>B513D2E70E2B57B7000A50C6</string>
  420 + <string>B513D2EC0E2B5841000A50C6</string>
  421 + <string>B513D2F40E2B5A2E000A50C6</string>
  422 + <string>B513D2F50E2B5A2E000A50C6</string>
  423 + <string>B513D2F60E2B5A2E000A50C6</string>
  424 + <string>B513D2F70E2B5A2E000A50C6</string>
  425 + <string>B513D2FD0E2B5A3F000A50C6</string>
  426 + <string>B513D2FE0E2B5A3F000A50C6</string>
  427 + <string>B513D30A0E2B5A62000A50C6</string>
  428 + <string>B513D3100E2B5C2F000A50C6</string>
  429 + <string>B513D3110E2B5C2F000A50C6</string>
  430 + <string>B513D3190E2B5CDB000A50C6</string>
  431 + <string>B513D3210E2B5D23000A50C6</string>
  432 + <string>B513D3220E2B5D23000A50C6</string>
  433 + <string>B513D3230E2B5D23000A50C6</string>
  434 + <string>B513D3520E2B5F47000A50C6</string>
  435 + <string>B513D3530E2B5F47000A50C6</string>
  436 + <string>B513D3540E2B5F47000A50C6</string>
  437 + <string>B513D3550E2B5F47000A50C6</string>
  438 + <string>B513D3560E2B5F47000A50C6</string>
  439 + <string>B513D3570E2B5F47000A50C6</string>
  440 + <string>B513D3580E2B5F47000A50C6</string>
  441 + <string>B513D35F0E2B5F47000A50C6</string>
  442 + <string>B513D3760E2B61A1000A50C6</string>
  443 + <string>B513D3770E2B61A1000A50C6</string>
  444 + <string>B513D3780E2B61A1000A50C6</string>
  445 + <string>B513D3790E2B61A1000A50C6</string>
  446 + <string>B513D37A0E2B61A1000A50C6</string>
  447 + <string>B513D3800E2B61BA000A50C6</string>
  448 + <string>B513D3810E2B61BA000A50C6</string>
  449 + <string>B513D3820E2B61BA000A50C6</string>
  450 + <string>B513D38F0E2B62C1000A50C6</string>
  451 + <string>B513D3900E2B62C1000A50C6</string>
  452 + <string>B513D3910E2B62C1000A50C6</string>
  453 + <string>B513D3930E2B62C1000A50C6</string>
  454 + <string>B513D3940E2B62C1000A50C6</string>
  455 + <string>B513D3950E2B62C1000A50C6</string>
  456 + <string>B513D39F0E2B6303000A50C6</string>
  457 + <string>B513D3A00E2B6303000A50C6</string>
  458 + <string>B513D3A10E2B6303000A50C6</string>
  459 + <string>B513D3A20E2B6303000A50C6</string>
  460 + <string>B513D3AE0E2BD1BC000A50C6</string>
  461 + <string>B513D3AF0E2BD1BC000A50C6</string>
  462 + <string>B513D3B00E2BD1BC000A50C6</string>
  463 + <string>B513D3B10E2BD1BC000A50C6</string>
  464 + <string>B513D3B20E2BD1BC000A50C6</string>
  465 + <string>B513D3B30E2BD1BC000A50C6</string>
  466 + <string>B513D3B40E2BD1BC000A50C6</string>
  467 + <string>B513D3B50E2BD1BC000A50C6</string>
  468 + <string>B513D3B60E2BD1BC000A50C6</string>
  469 + <string>B513D3B70E2BD1BC000A50C6</string>
  470 + <string>B513D3B80E2BD1BC000A50C6</string>
  471 + <string>B513D3BA0E2BD1BC000A50C6</string>
  472 + <string>B513D3BB0E2BD1BC000A50C6</string>
  473 + <string>B513D3C30E2BD1BC000A50C6</string>
  474 + <string>B513D3C40E2BD1BC000A50C6</string>
  475 + <string>B513D3CE0E2BD213000A50C6</string>
  476 + <string>B513D3CF0E2BD213000A50C6</string>
  477 + <string>B513D3D00E2BD213000A50C6</string>
  478 + <string>B513D3D10E2BD213000A50C6</string>
  479 + <string>B513D3D20E2BD213000A50C6</string>
  480 + <string>B513D3D30E2BD213000A50C6</string>
  481 + <string>B513D3D40E2BD213000A50C6</string>
  482 + <string>B513D3D50E2BD213000A50C6</string>
  483 + <string>B513D3D60E2BD213000A50C6</string>
  484 + <string>B513D3D70E2BD213000A50C6</string>
  485 + <string>B513D3F00E2BD48A000A50C6</string>
  486 + <string>B513D3F10E2BD48A000A50C6</string>
  487 + <string>B513D3F20E2BD48A000A50C6</string>
  488 + <string>B513D3F30E2BD48A000A50C6</string>
  489 + <string>B513D3F40E2BD48A000A50C6</string>
  490 + <string>B513D3F80E2BD48A000A50C6</string>
  491 + <string>B513D3F90E2BD48A000A50C6</string>
  492 + <string>B513D3FA0E2BD48A000A50C6</string>
  493 + <string>B513D3FB0E2BD48A000A50C6</string>
  494 + <string>B513D3FC0E2BD48A000A50C6</string>
  495 + <string>B513D3FD0E2BD48A000A50C6</string>
  496 + <string>B513D3FE0E2BD48A000A50C6</string>
  497 + <string>B513D3FF0E2BD48A000A50C6</string>
  498 + <string>B513D4000E2BD48A000A50C6</string>
  499 + <string>B513D4010E2BD48A000A50C6</string>
  500 + <string>B513D4020E2BD48A000A50C6</string>
  501 + <string>B513D4030E2BD48A000A50C6</string>
  502 + <string>B513D4040E2BD48A000A50C6</string>
  503 + <string>B513D4050E2BD48A000A50C6</string>
  504 + <string>B513D4060E2BD48A000A50C6</string>
  505 + <string>B513D4070E2BD48A000A50C6</string>
  506 + <string>B513D4080E2BD48A000A50C6</string>
  507 + <string>B513D40E0E2BD48A000A50C6</string>
  508 + <string>B513D40F0E2BD48A000A50C6</string>
  509 + <string>B513D41E0E2BE8A9000A50C6</string>
  510 + <string>B513D41F0E2BE8A9000A50C6</string>
  511 + <string>B513D4200E2BE8A9000A50C6</string>
  512 + <string>B513D4210E2BE8A9000A50C6</string>
  513 + <string>B513D4220E2BE8A9000A50C6</string>
  514 + <string>B513D4230E2BE8A9000A50C6</string>
  515 + <string>B513D4240E2BE8A9000A50C6</string>
  516 + <string>B513D4250E2BE8A9000A50C6</string>
  517 + <string>B513D4260E2BE8A9000A50C6</string>
  518 + <string>B513D4270E2BE8A9000A50C6</string>
  519 + <string>B513D4280E2BE8A9000A50C6</string>
  520 + <string>B513D4290E2BE8A9000A50C6</string>
  521 + <string>B513D42D0E2BE8A9000A50C6</string>
  522 + <string>B513D42E0E2BE8A9000A50C6</string>
  523 + <string>B513D42F0E2BE8A9000A50C6</string>
  524 + <string>B513D4300E2BE8A9000A50C6</string>
  525 + <string>B513D4310E2BE8A9000A50C6</string>
  526 + <string>B513D4320E2BE8A9000A50C6</string>
  527 + <string>B513D4350E2BE8A9000A50C6</string>
  528 + <string>B513D4360E2BE8A9000A50C6</string>
  529 + <string>B513D4370E2BE8A9000A50C6</string>
  530 + <string>B513D4380E2BE8A9000A50C6</string>
  531 + <string>B513D4390E2BE8A9000A50C6</string>
  532 + <string>B513D43A0E2BE8A9000A50C6</string>
  533 + <string>B513D43E0E2BE8A9000A50C6</string>
  534 + <string>B513D43F0E2BE8A9000A50C6</string>
  535 + <string>B513D4400E2BE8A9000A50C6</string>
  536 + <string>B513D4410E2BE8A9000A50C6</string>
  537 + <string>B513D4420E2BE8A9000A50C6</string>
  538 + <string>B513D4430E2BE8A9000A50C6</string>
  539 + <string>B513D4440E2BE8A9000A50C6</string>
  540 + <string>B513D4450E2BE8A9000A50C6</string>
  541 + <string>B513D4460E2BE8A9000A50C6</string>
  542 + <string>B513D4470E2BE8A9000A50C6</string>
  543 + <string>B513D4480E2BE8A9000A50C6</string>
  544 + <string>B513D4490E2BE8A9000A50C6</string>
  545 + <string>B513D44A0E2BE8A9000A50C6</string>
  546 + <string>B513D44B0E2BE8A9000A50C6</string>
  547 + <string>B513D44C0E2BE8A9000A50C6</string>
  548 + <string>B513D44D0E2BE8A9000A50C6</string>
  549 + <string>B513D44E0E2BE8A9000A50C6</string>
  550 + <string>B513D44F0E2BE8A9000A50C6</string>
  551 + <string>B513D4500E2BE8A9000A50C6</string>
  552 + <string>B513D4590E2BEDE4000A50C6</string>
  553 + <string>B513D45A0E2BEDE4000A50C6</string>
  554 + <string>B513D45B0E2BEDE4000A50C6</string>
  555 + <string>B513D45C0E2BEDE4000A50C6</string>
  556 + <string>B513D45D0E2BEDE4000A50C6</string>
  557 + <string>B513D4860E2BF2C4000A50C6</string>
  558 + <string>B513D4870E2BF2C4000A50C6</string>
  559 + <string>B513D4960E2BF854000A50C6</string>
  560 + <string>B513D4970E2BF854000A50C6</string>
  561 + <string>B513D4980E2BF854000A50C6</string>
  562 + <string>B513D4990E2BF854000A50C6</string>
  563 + </array>
  564 + </dict>
  565 + <key>SplitCount</key>
  566 + <string>1</string>
  567 + </dict>
  568 + <key>StatusBarVisibility</key>
  569 + <true/>
  570 + </dict>
  571 + <key>GeometryConfiguration</key>
  572 + <dict>
  573 + <key>Frame</key>
  574 + <string>{{0, 0}, {913, 581}}</string>
  575 + <key>RubberWindowFrame</key>
  576 + <string>308 138 1121 740 0 0 1440 878 </string>
  577 + </dict>
  578 + <key>Module</key>
  579 + <string>PBXNavigatorGroup</string>
  580 + <key>Proportion</key>
  581 + <string>581pt</string>
  582 + </dict>
  583 + <dict>
  584 + <key>ContentConfiguration</key>
  585 + <dict>
  586 + <key>PBXProjectModuleGUID</key>
  587 + <string>1CE0B20506471E060097A5F4</string>
  588 + <key>PBXProjectModuleLabel</key>
  589 + <string>Detail</string>
  590 + </dict>
  591 + <key>GeometryConfiguration</key>
  592 + <dict>
  593 + <key>Frame</key>
  594 + <string>{{0, 586}, {913, 113}}</string>
  595 + <key>RubberWindowFrame</key>
  596 + <string>308 138 1121 740 0 0 1440 878 </string>
  597 + </dict>
  598 + <key>Module</key>
  599 + <string>XCDetailModule</string>
  600 + <key>Proportion</key>
  601 + <string>113pt</string>
  602 + </dict>
  603 + </array>
  604 + <key>Proportion</key>
  605 + <string>913pt</string>
  606 + </dict>
  607 + </array>
  608 + <key>Name</key>
  609 + <string>Project</string>
  610 + <key>ServiceClasses</key>
  611 + <array>
  612 + <string>XCModuleDock</string>
  613 + <string>PBXSmartGroupTreeModule</string>
  614 + <string>XCModuleDock</string>
  615 + <string>PBXNavigatorGroup</string>
  616 + <string>XCDetailModule</string>
  617 + </array>
  618 + <key>TableOfContents</key>
  619 + <array>
  620 + <string>B513D2600E2B507F000A50C6</string>
  621 + <string>1CE0B1FE06471DED0097A5F4</string>
  622 + <string>B513D2610E2B507F000A50C6</string>
  623 + <string>1CE0B20306471E060097A5F4</string>
  624 + <string>1CE0B20506471E060097A5F4</string>
  625 + </array>
  626 + <key>ToolbarConfiguration</key>
  627 + <string>xcode.toolbar.config.defaultV3</string>
  628 + </dict>
  629 + <dict>
  630 + <key>ControllerClassBaseName</key>
  631 + <string></string>
  632 + <key>IconName</key>
  633 + <string>WindowOfProject</string>
  634 + <key>Identifier</key>
  635 + <string>perspective.morph</string>
  636 + <key>IsVertical</key>
  637 + <integer>0</integer>
  638 + <key>Layout</key>
  639 + <array>
  640 + <dict>
  641 + <key>BecomeActive</key>
  642 + <integer>1</integer>
  643 + <key>ContentConfiguration</key>
  644 + <dict>
  645 + <key>PBXBottomSmartGroupGIDs</key>
  646 + <array>
  647 + <string>1C37FBAC04509CD000000102</string>
  648 + <string>1C37FAAC04509CD000000102</string>
  649 + <string>1C08E77C0454961000C914BD</string>
  650 + <string>1C37FABC05509CD000000102</string>
  651 + <string>1C37FABC05539CD112110102</string>
  652 + <string>E2644B35053B69B200211256</string>
  653 + <string>1C37FABC04509CD000100104</string>
  654 + <string>1CC0EA4004350EF90044410B</string>
  655 + <string>1CC0EA4004350EF90041110B</string>
  656 + </array>
  657 + <key>PBXProjectModuleGUID</key>
  658 + <string>11E0B1FE06471DED0097A5F4</string>
  659 + <key>PBXProjectModuleLabel</key>
  660 + <string>Files</string>
  661 + <key>PBXProjectStructureProvided</key>
  662 + <string>yes</string>
  663 + <key>PBXSmartGroupTreeModuleColumnData</key>
  664 + <dict>
  665 + <key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
  666 + <array>
  667 + <real>186</real>
  668 + </array>
  669 + <key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
  670 + <array>
  671 + <string>MainColumn</string>
  672 + </array>
  673 + </dict>
  674 + <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
  675 + <dict>
  676 + <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
  677 + <array>
  678 + <string>29B97314FDCFA39411CA2CEA</string>
  679 + <string>1C37FABC05509CD000000102</string>
  680 + </array>
  681 + <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
  682 + <array>
  683 + <array>
  684 + <integer>0</integer>
  685 + </array>
  686 + </array>
  687 + <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
  688 + <string>{{0, 0}, {186, 337}}</string>
  689 + </dict>
  690 + <key>PBXTopSmartGroupGIDs</key>
  691 + <array/>
  692 + <key>XCIncludePerspectivesSwitch</key>
  693 + <integer>1</integer>
  694 + <key>XCSharingToken</key>
  695 + <string>com.apple.Xcode.GFSharingToken</string>
  696 + </dict>
  697 + <key>GeometryConfiguration</key>
  698 + <dict>
  699 + <key>Frame</key>
  700 + <string>{{0, 0}, {203, 355}}</string>
  701 + <key>GroupTreeTableConfiguration</key>
  702 + <array>
  703 + <string>MainColumn</string>
  704 + <real>186</real>
  705 + </array>
  706 + <key>RubberWindowFrame</key>
  707 + <string>373 269 690 397 0 0 1440 878 </string>
  708 + </dict>
  709 + <key>Module</key>
  710 + <string>PBXSmartGroupTreeModule</string>
  711 + <key>Proportion</key>
  712 + <string>100%</string>
  713 + </dict>
  714 + </array>
  715 + <key>Name</key>
  716 + <string>Morph</string>
  717 + <key>PreferredWidth</key>
  718 + <integer>300</integer>
  719 + <key>ServiceClasses</key>
  720 + <array>
  721 + <string>XCModuleDock</string>
  722 + <string>PBXSmartGroupTreeModule</string>
  723 + </array>
  724 + <key>TableOfContents</key>
  725 + <array>
  726 + <string>11E0B1FE06471DED0097A5F4</string>
  727 + </array>
  728 + <key>ToolbarConfiguration</key>
  729 + <string>xcode.toolbar.config.default.shortV3</string>
  730 + </dict>
  731 + </array>
  732 + <key>PerspectivesBarVisible</key>
  733 + <false/>
  734 + <key>ShelfIsVisible</key>
  735 + <false/>
  736 + <key>SourceDescription</key>
  737 + <string>file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecificationMode1.xcperspec'</string>
  738 + <key>StatusbarIsVisible</key>
  739 + <true/>
  740 + <key>TimeStamp</key>
  741 + <real>0.0</real>
  742 + <key>ToolbarDisplayMode</key>
  743 + <integer>1</integer>
  744 + <key>ToolbarIsVisible</key>
  745 + <true/>
  746 + <key>ToolbarSizeMode</key>
  747 + <integer>1</integer>
  748 + <key>Type</key>
  749 + <string>Perspectives</string>
  750 + <key>UpdateMessage</key>
  751 + <string>The Default Workspace in this version of Xcode now includes support to hide and show the detail view (what has been referred to as the "Metro-Morph" feature). You must discard your current Default Workspace settings and update to the latest Default Workspace in order to gain this feature. Do you wish to update to the latest Workspace defaults for project '%@'?</string>
  752 + <key>WindowJustification</key>
  753 + <integer>5</integer>
  754 + <key>WindowOrderList</key>
  755 + <array>
  756 + <string>1C530D57069F1CE1000CFCEE</string>
  757 + <string>B513D2650E2B507F000A50C6</string>
  758 + <string>B513D2660E2B507F000A50C6</string>
  759 + <string>B5ABC8410E24CDE70072F422</string>
  760 + <string>B513D4520E2BE8A9000A50C6</string>
  761 + <string>1C78EAAD065D492600B07095</string>
  762 + <string>1CD10A99069EF8BA00B06720</string>
  763 + <string>/Users/ben/asi-http-request/asi-http-request.xcodeproj</string>
  764 + </array>
  765 + <key>WindowString</key>
  766 + <string>308 138 1121 740 0 0 1440 878 </string>
  767 + <key>WindowToolsV3</key>
  768 + <array>
  769 + <dict>
  770 + <key>FirstTimeWindowDisplayed</key>
  771 + <false/>
  772 + <key>Identifier</key>
  773 + <string>windowTool.build</string>
  774 + <key>IsVertical</key>
  775 + <true/>
  776 + <key>Layout</key>
  777 + <array>
  778 + <dict>
  779 + <key>Dock</key>
  780 + <array>
  781 + <dict>
  782 + <key>BecomeActive</key>
  783 + <true/>
  784 + <key>ContentConfiguration</key>
  785 + <dict>
  786 + <key>PBXProjectModuleGUID</key>
  787 + <string>1CD0528F0623707200166675</string>
  788 + <key>PBXProjectModuleLabel</key>
  789 + <string>ASIHTTPRequest.m</string>
  790 + <key>StatusBarVisibility</key>
  791 + <true/>
  792 + </dict>
  793 + <key>GeometryConfiguration</key>
  794 + <dict>
  795 + <key>Frame</key>
  796 + <string>{{0, 0}, {1440, 536}}</string>
  797 + <key>RubberWindowFrame</key>
  798 + <string>0 60 1440 818 0 0 1440 878 </string>
  799 + </dict>
  800 + <key>Module</key>
  801 + <string>PBXNavigatorGroup</string>
  802 + <key>Proportion</key>
  803 + <string>536pt</string>
  804 + </dict>
  805 + <dict>
  806 + <key>ContentConfiguration</key>
  807 + <dict>
  808 + <key>PBXProjectModuleGUID</key>
  809 + <string>XCMainBuildResultsModuleGUID</string>
  810 + <key>PBXProjectModuleLabel</key>
  811 + <string>Build</string>
  812 + <key>XCBuildResultsTrigger_Collapse</key>
  813 + <integer>1021</integer>
  814 + <key>XCBuildResultsTrigger_Open</key>
  815 + <integer>1011</integer>
  816 + </dict>
  817 + <key>GeometryConfiguration</key>
  818 + <dict>
  819 + <key>Frame</key>
  820 + <string>{{0, 541}, {1440, 236}}</string>
  821 + <key>RubberWindowFrame</key>
  822 + <string>0 60 1440 818 0 0 1440 878 </string>
  823 + </dict>
  824 + <key>Module</key>
  825 + <string>PBXBuildResultsModule</string>
  826 + <key>Proportion</key>
  827 + <string>236pt</string>
  828 + </dict>
  829 + </array>
  830 + <key>Proportion</key>
  831 + <string>777pt</string>
  832 + </dict>
  833 + </array>
  834 + <key>Name</key>
  835 + <string>Build Results</string>
  836 + <key>ServiceClasses</key>
  837 + <array>
  838 + <string>PBXBuildResultsModule</string>
  839 + </array>
  840 + <key>StatusbarIsVisible</key>
  841 + <true/>
  842 + <key>TableOfContents</key>
  843 + <array>
  844 + <string>B5ABC8410E24CDE70072F422</string>
  845 + <string>B513D2620E2B507F000A50C6</string>
  846 + <string>1CD0528F0623707200166675</string>
  847 + <string>XCMainBuildResultsModuleGUID</string>
  848 + </array>
  849 + <key>ToolbarConfiguration</key>
  850 + <string>xcode.toolbar.config.buildV3</string>
  851 + <key>WindowString</key>
  852 + <string>0 60 1440 818 0 0 1440 878 </string>
  853 + <key>WindowToolGUID</key>
  854 + <string>B5ABC8410E24CDE70072F422</string>
  855 + <key>WindowToolIsVisible</key>
  856 + <false/>
  857 + </dict>
  858 + <dict>
  859 + <key>FirstTimeWindowDisplayed</key>
  860 + <false/>
  861 + <key>Identifier</key>
  862 + <string>windowTool.debugger</string>
  863 + <key>IsVertical</key>
  864 + <true/>
  865 + <key>Layout</key>
  866 + <array>
  867 + <dict>
  868 + <key>Dock</key>
  869 + <array>
  870 + <dict>
  871 + <key>ContentConfiguration</key>
  872 + <dict>
  873 + <key>Debugger</key>
  874 + <dict>
  875 + <key>HorizontalSplitView</key>
  876 + <dict>
  877 + <key>_collapsingFrameDimension</key>
  878 + <real>0.0</real>
  879 + <key>_indexOfCollapsedView</key>
  880 + <integer>0</integer>
  881 + <key>_percentageOfCollapsedView</key>
  882 + <real>0.0</real>
  883 + <key>isCollapsed</key>
  884 + <string>yes</string>
  885 + <key>sizes</key>
  886 + <array>
  887 + <string>{{0, 0}, {713, 338}}</string>
  888 + <string>{{713, 0}, {851, 338}}</string>
  889 + </array>
  890 + </dict>
  891 + <key>VerticalSplitView</key>
  892 + <dict>
  893 + <key>_collapsingFrameDimension</key>
  894 + <real>0.0</real>
  895 + <key>_indexOfCollapsedView</key>
  896 + <integer>0</integer>
  897 + <key>_percentageOfCollapsedView</key>
  898 + <real>0.0</real>
  899 + <key>isCollapsed</key>
  900 + <string>yes</string>
  901 + <key>sizes</key>
  902 + <array>
  903 + <string>{{0, 0}, {1564, 338}}</string>
  904 + <string>{{0, 338}, {1564, 297}}</string>
  905 + </array>
  906 + </dict>
  907 + </dict>
  908 + <key>LauncherConfigVersion</key>
  909 + <string>8</string>
  910 + <key>PBXProjectModuleGUID</key>
  911 + <string>1C162984064C10D400B95A72</string>
  912 + <key>PBXProjectModuleLabel</key>
  913 + <string>Debug - GLUTExamples (Underwater)</string>
  914 + </dict>
  915 + <key>GeometryConfiguration</key>
  916 + <dict>
  917 + <key>DebugConsoleVisible</key>
  918 + <string>None</string>
  919 + <key>DebugConsoleWindowFrame</key>
  920 + <string>{{200, 200}, {500, 300}}</string>
  921 + <key>DebugSTDIOWindowFrame</key>
  922 + <string>{{200, 200}, {500, 300}}</string>
  923 + <key>Frame</key>
  924 + <string>{{0, 0}, {1564, 635}}</string>
  925 + <key>PBXDebugSessionStackFrameViewKey</key>
  926 + <dict>
  927 + <key>DebugVariablesTableConfiguration</key>
  928 + <array>
  929 + <string>Name</string>
  930 + <real>248</real>
  931 + <string>Type</string>
  932 + <real>84</real>
  933 + <string>Value</string>
  934 + <real>85</real>
  935 + <string>Summary</string>
  936 + <real>406</real>
  937 + </array>
  938 + <key>Frame</key>
  939 + <string>{{713, 0}, {851, 338}}</string>
  940 + <key>RubberWindowFrame</key>
  941 + <string>-221 202 1564 676 0 0 1440 878 </string>
  942 + </dict>
  943 + <key>RubberWindowFrame</key>
  944 + <string>-221 202 1564 676 0 0 1440 878 </string>
  945 + </dict>
  946 + <key>Module</key>
  947 + <string>PBXDebugSessionModule</string>
  948 + <key>Proportion</key>
  949 + <string>635pt</string>
  950 + </dict>
  951 + </array>
  952 + <key>Proportion</key>
  953 + <string>635pt</string>
  954 + </dict>
  955 + </array>
  956 + <key>Name</key>
  957 + <string>Debugger</string>
  958 + <key>ServiceClasses</key>
  959 + <array>
  960 + <string>PBXDebugSessionModule</string>
  961 + </array>
  962 + <key>StatusbarIsVisible</key>
  963 + <true/>
  964 + <key>TableOfContents</key>
  965 + <array>
  966 + <string>1CD10A99069EF8BA00B06720</string>
  967 + <string>B513D2530E2B5029000A50C6</string>
  968 + <string>1C162984064C10D400B95A72</string>
  969 + <string>B513D2540E2B5029000A50C6</string>
  970 + <string>B513D2550E2B5029000A50C6</string>
  971 + <string>B513D2560E2B5029000A50C6</string>
  972 + <string>B513D2570E2B5029000A50C6</string>
  973 + <string>B513D2580E2B5029000A50C6</string>
  974 + </array>
  975 + <key>ToolbarConfiguration</key>
  976 + <string>xcode.toolbar.config.debugV3</string>
  977 + <key>WindowString</key>
  978 + <string>-221 202 1564 676 0 0 1440 878 </string>
  979 + <key>WindowToolGUID</key>
  980 + <string>1CD10A99069EF8BA00B06720</string>
  981 + <key>WindowToolIsVisible</key>
  982 + <true/>
  983 + </dict>
  984 + <dict>
  985 + <key>FirstTimeWindowDisplayed</key>
  986 + <false/>
  987 + <key>Identifier</key>
  988 + <string>windowTool.find</string>
  989 + <key>IsVertical</key>
  990 + <true/>
  991 + <key>Layout</key>
  992 + <array>
  993 + <dict>
  994 + <key>Dock</key>
  995 + <array>
  996 + <dict>
  997 + <key>Dock</key>
  998 + <array>
  999 + <dict>
  1000 + <key>ContentConfiguration</key>
  1001 + <dict>
  1002 + <key>PBXProjectModuleGUID</key>
  1003 + <string>1CDD528C0622207200134675</string>
  1004 + <key>PBXProjectModuleLabel</key>
  1005 + <string>&lt;No Editor&gt;</string>
  1006 + <key>StatusBarVisibility</key>
  1007 + <true/>
  1008 + </dict>
  1009 + <key>GeometryConfiguration</key>
  1010 + <dict>
  1011 + <key>Frame</key>
  1012 + <string>{{0, 0}, {781, 212}}</string>
  1013 + <key>RubberWindowFrame</key>
  1014 + <string>329 385 781 470 0 0 1440 878 </string>
  1015 + </dict>
  1016 + <key>Module</key>
  1017 + <string>PBXNavigatorGroup</string>
  1018 + <key>Proportion</key>
  1019 + <string>781pt</string>
  1020 + </dict>
  1021 + </array>
  1022 + <key>Proportion</key>
  1023 + <string>212pt</string>
  1024 + </dict>
  1025 + <dict>
  1026 + <key>BecomeActive</key>
  1027 + <true/>
  1028 + <key>ContentConfiguration</key>
  1029 + <dict>
  1030 + <key>PBXProjectModuleGUID</key>
  1031 + <string>1CD0528E0623707200166675</string>
  1032 + <key>PBXProjectModuleLabel</key>
  1033 + <string>Project Find</string>
  1034 + </dict>
  1035 + <key>GeometryConfiguration</key>
  1036 + <dict>
  1037 + <key>Frame</key>
  1038 + <string>{{0, 217}, {781, 212}}</string>
  1039 + <key>RubberWindowFrame</key>
  1040 + <string>329 385 781 470 0 0 1440 878 </string>
  1041 + </dict>
  1042 + <key>Module</key>
  1043 + <string>PBXProjectFindModule</string>
  1044 + <key>Proportion</key>
  1045 + <string>212pt</string>
  1046 + </dict>
  1047 + </array>
  1048 + <key>Proportion</key>
  1049 + <string>429pt</string>
  1050 + </dict>
  1051 + </array>
  1052 + <key>Name</key>
  1053 + <string>Project Find</string>
  1054 + <key>ServiceClasses</key>
  1055 + <array>
  1056 + <string>PBXProjectFindModule</string>
  1057 + </array>
  1058 + <key>StatusbarIsVisible</key>
  1059 + <true/>
  1060 + <key>TableOfContents</key>
  1061 + <array>
  1062 + <string>1C530D57069F1CE1000CFCEE</string>
  1063 + <string>B513D3460E2B5F3E000A50C6</string>
  1064 + <string>B513D3470E2B5F3E000A50C6</string>
  1065 + <string>1CDD528C0622207200134675</string>
  1066 + <string>1CD0528E0623707200166675</string>
  1067 + </array>
  1068 + <key>WindowString</key>
  1069 + <string>329 385 781 470 0 0 1440 878 </string>
  1070 + <key>WindowToolGUID</key>
  1071 + <string>1C530D57069F1CE1000CFCEE</string>
  1072 + <key>WindowToolIsVisible</key>
  1073 + <false/>
  1074 + </dict>
  1075 + <dict>
  1076 + <key>Identifier</key>
  1077 + <string>MENUSEPARATOR</string>
  1078 + </dict>
  1079 + <dict>
  1080 + <key>FirstTimeWindowDisplayed</key>
  1081 + <false/>
  1082 + <key>Identifier</key>
  1083 + <string>windowTool.debuggerConsole</string>
  1084 + <key>IsVertical</key>
  1085 + <true/>
  1086 + <key>Layout</key>
  1087 + <array>
  1088 + <dict>
  1089 + <key>Dock</key>
  1090 + <array>
  1091 + <dict>
  1092 + <key>BecomeActive</key>
  1093 + <true/>
  1094 + <key>ContentConfiguration</key>
  1095 + <dict>
  1096 + <key>PBXProjectModuleGUID</key>
  1097 + <string>1C78EAAC065D492600B07095</string>
  1098 + <key>PBXProjectModuleLabel</key>
  1099 + <string>Debugger Console</string>
  1100 + </dict>
  1101 + <key>GeometryConfiguration</key>
  1102 + <dict>
  1103 + <key>Frame</key>
  1104 + <string>{{0, 0}, {629, 511}}</string>
  1105 + <key>RubberWindowFrame</key>
  1106 + <string>49 209 629 552 0 0 1440 878 </string>
  1107 + </dict>
  1108 + <key>Module</key>
  1109 + <string>PBXDebugCLIModule</string>
  1110 + <key>Proportion</key>
  1111 + <string>511pt</string>
  1112 + </dict>
  1113 + </array>
  1114 + <key>Proportion</key>
  1115 + <string>511pt</string>
  1116 + </dict>
  1117 + </array>
  1118 + <key>Name</key>
  1119 + <string>Debugger Console</string>
  1120 + <key>ServiceClasses</key>
  1121 + <array>
  1122 + <string>PBXDebugCLIModule</string>
  1123 + </array>
  1124 + <key>StatusbarIsVisible</key>
  1125 + <true/>
  1126 + <key>TableOfContents</key>
  1127 + <array>
  1128 + <string>1C78EAAD065D492600B07095</string>
  1129 + <string>B513D2630E2B507F000A50C6</string>
  1130 + <string>1C78EAAC065D492600B07095</string>
  1131 + </array>
  1132 + <key>ToolbarConfiguration</key>
  1133 + <string>xcode.toolbar.config.consoleV3</string>
  1134 + <key>WindowString</key>
  1135 + <string>49 209 629 552 0 0 1440 878 </string>
  1136 + <key>WindowToolGUID</key>
  1137 + <string>1C78EAAD065D492600B07095</string>
  1138 + <key>WindowToolIsVisible</key>
  1139 + <true/>
  1140 + </dict>
  1141 + <dict>
  1142 + <key>Identifier</key>
  1143 + <string>windowTool.snapshots</string>
  1144 + <key>Layout</key>
  1145 + <array>
  1146 + <dict>
  1147 + <key>Dock</key>
  1148 + <array>
  1149 + <dict>
  1150 + <key>Module</key>
  1151 + <string>XCSnapshotModule</string>
  1152 + <key>Proportion</key>
  1153 + <string>100%</string>
  1154 + </dict>
  1155 + </array>
  1156 + <key>Proportion</key>
  1157 + <string>100%</string>
  1158 + </dict>
  1159 + </array>
  1160 + <key>Name</key>
  1161 + <string>Snapshots</string>
  1162 + <key>ServiceClasses</key>
  1163 + <array>
  1164 + <string>XCSnapshotModule</string>
  1165 + </array>
  1166 + <key>StatusbarIsVisible</key>
  1167 + <string>Yes</string>
  1168 + <key>ToolbarConfiguration</key>
  1169 + <string>xcode.toolbar.config.snapshots</string>
  1170 + <key>WindowString</key>
  1171 + <string>315 824 300 550 0 0 1440 878 </string>
  1172 + <key>WindowToolIsVisible</key>
  1173 + <string>Yes</string>
  1174 + </dict>
  1175 + <dict>
  1176 + <key>Identifier</key>
  1177 + <string>windowTool.scm</string>
  1178 + <key>Layout</key>
  1179 + <array>
  1180 + <dict>
  1181 + <key>Dock</key>
  1182 + <array>
  1183 + <dict>
  1184 + <key>ContentConfiguration</key>
  1185 + <dict>
  1186 + <key>PBXProjectModuleGUID</key>
  1187 + <string>1C78EAB2065D492600B07095</string>
  1188 + <key>PBXProjectModuleLabel</key>
  1189 + <string>&lt;No Editor&gt;</string>
  1190 + <key>PBXSplitModuleInNavigatorKey</key>
  1191 + <dict>
  1192 + <key>Split0</key>
  1193 + <dict>
  1194 + <key>PBXProjectModuleGUID</key>
  1195 + <string>1C78EAB3065D492600B07095</string>
  1196 + </dict>
  1197 + <key>SplitCount</key>
  1198 + <string>1</string>
  1199 + </dict>
  1200 + <key>StatusBarVisibility</key>
  1201 + <integer>1</integer>
  1202 + </dict>
  1203 + <key>GeometryConfiguration</key>
  1204 + <dict>
  1205 + <key>Frame</key>
  1206 + <string>{{0, 0}, {452, 0}}</string>
  1207 + <key>RubberWindowFrame</key>
  1208 + <string>743 379 452 308 0 0 1280 1002 </string>
  1209 + </dict>
  1210 + <key>Module</key>
  1211 + <string>PBXNavigatorGroup</string>
  1212 + <key>Proportion</key>
  1213 + <string>0pt</string>
  1214 + </dict>
  1215 + <dict>
  1216 + <key>BecomeActive</key>
  1217 + <integer>1</integer>
  1218 + <key>ContentConfiguration</key>
  1219 + <dict>
  1220 + <key>PBXProjectModuleGUID</key>
  1221 + <string>1CD052920623707200166675</string>
  1222 + <key>PBXProjectModuleLabel</key>
  1223 + <string>SCM</string>
  1224 + </dict>
  1225 + <key>GeometryConfiguration</key>
  1226 + <dict>
  1227 + <key>ConsoleFrame</key>
  1228 + <string>{{0, 259}, {452, 0}}</string>
  1229 + <key>Frame</key>
  1230 + <string>{{0, 7}, {452, 259}}</string>
  1231 + <key>RubberWindowFrame</key>
  1232 + <string>743 379 452 308 0 0 1280 1002 </string>
  1233 + <key>TableConfiguration</key>
  1234 + <array>
  1235 + <string>Status</string>
  1236 + <real>30</real>
  1237 + <string>FileName</string>
  1238 + <real>199</real>
  1239 + <string>Path</string>
  1240 + <real>197.09500122070312</real>
  1241 + </array>
  1242 + <key>TableFrame</key>
  1243 + <string>{{0, 0}, {452, 250}}</string>
  1244 + </dict>
  1245 + <key>Module</key>
  1246 + <string>PBXCVSModule</string>
  1247 + <key>Proportion</key>
  1248 + <string>262pt</string>
  1249 + </dict>
  1250 + </array>
  1251 + <key>Proportion</key>
  1252 + <string>266pt</string>
  1253 + </dict>
  1254 + </array>
  1255 + <key>Name</key>
  1256 + <string>SCM</string>
  1257 + <key>ServiceClasses</key>
  1258 + <array>
  1259 + <string>PBXCVSModule</string>
  1260 + </array>
  1261 + <key>StatusbarIsVisible</key>
  1262 + <integer>1</integer>
  1263 + <key>TableOfContents</key>
  1264 + <array>
  1265 + <string>1C78EAB4065D492600B07095</string>
  1266 + <string>1C78EAB5065D492600B07095</string>
  1267 + <string>1C78EAB2065D492600B07095</string>
  1268 + <string>1CD052920623707200166675</string>
  1269 + </array>
  1270 + <key>ToolbarConfiguration</key>
  1271 + <string>xcode.toolbar.config.scm</string>
  1272 + <key>WindowString</key>
  1273 + <string>743 379 452 308 0 0 1280 1002 </string>
  1274 + </dict>
  1275 + <dict>
  1276 + <key>Identifier</key>
  1277 + <string>windowTool.breakpoints</string>
  1278 + <key>IsVertical</key>
  1279 + <integer>0</integer>
  1280 + <key>Layout</key>
  1281 + <array>
  1282 + <dict>
  1283 + <key>Dock</key>
  1284 + <array>
  1285 + <dict>
  1286 + <key>BecomeActive</key>
  1287 + <integer>1</integer>
  1288 + <key>ContentConfiguration</key>
  1289 + <dict>
  1290 + <key>PBXBottomSmartGroupGIDs</key>
  1291 + <array>
  1292 + <string>1C77FABC04509CD000000102</string>
  1293 + </array>
  1294 + <key>PBXProjectModuleGUID</key>
  1295 + <string>1CE0B1FE06471DED0097A5F4</string>
  1296 + <key>PBXProjectModuleLabel</key>
  1297 + <string>Files</string>
  1298 + <key>PBXProjectStructureProvided</key>
  1299 + <string>no</string>
  1300 + <key>PBXSmartGroupTreeModuleColumnData</key>
  1301 + <dict>
  1302 + <key>PBXSmartGroupTreeModuleColumnWidthsKey</key>
  1303 + <array>
  1304 + <real>168</real>
  1305 + </array>
  1306 + <key>PBXSmartGroupTreeModuleColumnsKey_v4</key>
  1307 + <array>
  1308 + <string>MainColumn</string>
  1309 + </array>
  1310 + </dict>
  1311 + <key>PBXSmartGroupTreeModuleOutlineStateKey_v7</key>
  1312 + <dict>
  1313 + <key>PBXSmartGroupTreeModuleOutlineStateExpansionKey</key>
  1314 + <array>
  1315 + <string>1C77FABC04509CD000000102</string>
  1316 + </array>
  1317 + <key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
  1318 + <array>
  1319 + <array>
  1320 + <integer>0</integer>
  1321 + </array>
  1322 + </array>
  1323 + <key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
  1324 + <string>{{0, 0}, {168, 350}}</string>
  1325 + </dict>
  1326 + <key>PBXTopSmartGroupGIDs</key>
  1327 + <array/>
  1328 + <key>XCIncludePerspectivesSwitch</key>
  1329 + <integer>0</integer>
  1330 + </dict>
  1331 + <key>GeometryConfiguration</key>
  1332 + <dict>
  1333 + <key>Frame</key>
  1334 + <string>{{0, 0}, {185, 368}}</string>
  1335 + <key>GroupTreeTableConfiguration</key>
  1336 + <array>
  1337 + <string>MainColumn</string>
  1338 + <real>168</real>
  1339 + </array>
  1340 + <key>RubberWindowFrame</key>
  1341 + <string>315 424 744 409 0 0 1440 878 </string>
  1342 + </dict>
  1343 + <key>Module</key>
  1344 + <string>PBXSmartGroupTreeModule</string>
  1345 + <key>Proportion</key>
  1346 + <string>185pt</string>
  1347 + </dict>
  1348 + <dict>
  1349 + <key>ContentConfiguration</key>
  1350 + <dict>
  1351 + <key>PBXProjectModuleGUID</key>
  1352 + <string>1CA1AED706398EBD00589147</string>
  1353 + <key>PBXProjectModuleLabel</key>
  1354 + <string>Detail</string>
  1355 + </dict>
  1356 + <key>GeometryConfiguration</key>
  1357 + <dict>
  1358 + <key>Frame</key>
  1359 + <string>{{190, 0}, {554, 368}}</string>
  1360 + <key>RubberWindowFrame</key>
  1361 + <string>315 424 744 409 0 0 1440 878 </string>
  1362 + </dict>
  1363 + <key>Module</key>
  1364 + <string>XCDetailModule</string>
  1365 + <key>Proportion</key>
  1366 + <string>554pt</string>
  1367 + </dict>
  1368 + </array>
  1369 + <key>Proportion</key>
  1370 + <string>368pt</string>
  1371 + </dict>
  1372 + </array>
  1373 + <key>MajorVersion</key>
  1374 + <integer>3</integer>
  1375 + <key>MinorVersion</key>
  1376 + <integer>0</integer>
  1377 + <key>Name</key>
  1378 + <string>Breakpoints</string>
  1379 + <key>ServiceClasses</key>
  1380 + <array>
  1381 + <string>PBXSmartGroupTreeModule</string>
  1382 + <string>XCDetailModule</string>
  1383 + </array>
  1384 + <key>StatusbarIsVisible</key>
  1385 + <integer>1</integer>
  1386 + <key>TableOfContents</key>
  1387 + <array>
  1388 + <string>1CDDB66807F98D9800BB5817</string>
  1389 + <string>1CDDB66907F98D9800BB5817</string>
  1390 + <string>1CE0B1FE06471DED0097A5F4</string>
  1391 + <string>1CA1AED706398EBD00589147</string>
  1392 + </array>
  1393 + <key>ToolbarConfiguration</key>
  1394 + <string>xcode.toolbar.config.breakpointsV3</string>
  1395 + <key>WindowString</key>
  1396 + <string>315 424 744 409 0 0 1440 878 </string>
  1397 + <key>WindowToolGUID</key>
  1398 + <string>1CDDB66807F98D9800BB5817</string>
  1399 + <key>WindowToolIsVisible</key>
  1400 + <integer>1</integer>
  1401 + </dict>
  1402 + <dict>
  1403 + <key>Identifier</key>
  1404 + <string>windowTool.debugAnimator</string>
  1405 + <key>Layout</key>
  1406 + <array>
  1407 + <dict>
  1408 + <key>Dock</key>
  1409 + <array>
  1410 + <dict>
  1411 + <key>Module</key>
  1412 + <string>PBXNavigatorGroup</string>
  1413 + <key>Proportion</key>
  1414 + <string>100%</string>
  1415 + </dict>
  1416 + </array>
  1417 + <key>Proportion</key>
  1418 + <string>100%</string>
  1419 + </dict>
  1420 + </array>
  1421 + <key>Name</key>
  1422 + <string>Debug Visualizer</string>
  1423 + <key>ServiceClasses</key>
  1424 + <array>
  1425 + <string>PBXNavigatorGroup</string>
  1426 + </array>
  1427 + <key>StatusbarIsVisible</key>
  1428 + <integer>1</integer>
  1429 + <key>ToolbarConfiguration</key>
  1430 + <string>xcode.toolbar.config.debugAnimatorV3</string>
  1431 + <key>WindowString</key>
  1432 + <string>100 100 700 500 0 0 1280 1002 </string>
  1433 + </dict>
  1434 + <dict>
  1435 + <key>Identifier</key>
  1436 + <string>windowTool.bookmarks</string>
  1437 + <key>Layout</key>
  1438 + <array>
  1439 + <dict>
  1440 + <key>Dock</key>
  1441 + <array>
  1442 + <dict>
  1443 + <key>Module</key>
  1444 + <string>PBXBookmarksModule</string>
  1445 + <key>Proportion</key>
  1446 + <string>100%</string>
  1447 + </dict>
  1448 + </array>
  1449 + <key>Proportion</key>
  1450 + <string>100%</string>
  1451 + </dict>
  1452 + </array>
  1453 + <key>Name</key>
  1454 + <string>Bookmarks</string>
  1455 + <key>ServiceClasses</key>
  1456 + <array>
  1457 + <string>PBXBookmarksModule</string>
  1458 + </array>
  1459 + <key>StatusbarIsVisible</key>
  1460 + <integer>0</integer>
  1461 + <key>WindowString</key>
  1462 + <string>538 42 401 187 0 0 1280 1002 </string>
  1463 + </dict>
  1464 + <dict>
  1465 + <key>Identifier</key>
  1466 + <string>windowTool.projectFormatConflicts</string>
  1467 + <key>Layout</key>
  1468 + <array>
  1469 + <dict>
  1470 + <key>Dock</key>
  1471 + <array>
  1472 + <dict>
  1473 + <key>Module</key>
  1474 + <string>XCProjectFormatConflictsModule</string>
  1475 + <key>Proportion</key>
  1476 + <string>100%</string>
  1477 + </dict>
  1478 + </array>
  1479 + <key>Proportion</key>
  1480 + <string>100%</string>
  1481 + </dict>
  1482 + </array>
  1483 + <key>Name</key>
  1484 + <string>Project Format Conflicts</string>
  1485 + <key>ServiceClasses</key>
  1486 + <array>
  1487 + <string>XCProjectFormatConflictsModule</string>
  1488 + </array>
  1489 + <key>StatusbarIsVisible</key>
  1490 + <integer>0</integer>
  1491 + <key>WindowContentMinSize</key>
  1492 + <string>450 300</string>
  1493 + <key>WindowString</key>
  1494 + <string>50 850 472 307 0 0 1440 877</string>
  1495 + </dict>
  1496 + <dict>
  1497 + <key>Identifier</key>
  1498 + <string>windowTool.classBrowser</string>
  1499 + <key>Layout</key>
  1500 + <array>
  1501 + <dict>
  1502 + <key>Dock</key>
  1503 + <array>
  1504 + <dict>
  1505 + <key>BecomeActive</key>
  1506 + <integer>1</integer>
  1507 + <key>ContentConfiguration</key>
  1508 + <dict>
  1509 + <key>OptionsSetName</key>
  1510 + <string>Hierarchy, all classes</string>
  1511 + <key>PBXProjectModuleGUID</key>
  1512 + <string>1CA6456E063B45B4001379D8</string>
  1513 + <key>PBXProjectModuleLabel</key>
  1514 + <string>Class Browser - NSObject</string>
  1515 + </dict>
  1516 + <key>GeometryConfiguration</key>
  1517 + <dict>
  1518 + <key>ClassesFrame</key>
  1519 + <string>{{0, 0}, {374, 96}}</string>
  1520 + <key>ClassesTreeTableConfiguration</key>
  1521 + <array>
  1522 + <string>PBXClassNameColumnIdentifier</string>
  1523 + <real>208</real>
  1524 + <string>PBXClassBookColumnIdentifier</string>
  1525 + <real>22</real>
  1526 + </array>
  1527 + <key>Frame</key>
  1528 + <string>{{0, 0}, {630, 331}}</string>
  1529 + <key>MembersFrame</key>
  1530 + <string>{{0, 105}, {374, 395}}</string>
  1531 + <key>MembersTreeTableConfiguration</key>
  1532 + <array>
  1533 + <string>PBXMemberTypeIconColumnIdentifier</string>
  1534 + <real>22</real>
  1535 + <string>PBXMemberNameColumnIdentifier</string>
  1536 + <real>216</real>
  1537 + <string>PBXMemberTypeColumnIdentifier</string>
  1538 + <real>97</real>
  1539 + <string>PBXMemberBookColumnIdentifier</string>
  1540 + <real>22</real>
  1541 + </array>
  1542 + <key>PBXModuleWindowStatusBarHidden2</key>
  1543 + <integer>1</integer>
  1544 + <key>RubberWindowFrame</key>
  1545 + <string>385 179 630 352 0 0 1440 878 </string>
  1546 + </dict>
  1547 + <key>Module</key>
  1548 + <string>PBXClassBrowserModule</string>
  1549 + <key>Proportion</key>
  1550 + <string>332pt</string>
  1551 + </dict>
  1552 + </array>
  1553 + <key>Proportion</key>
  1554 + <string>332pt</string>
  1555 + </dict>
  1556 + </array>
  1557 + <key>Name</key>
  1558 + <string>Class Browser</string>
  1559 + <key>ServiceClasses</key>
  1560 + <array>
  1561 + <string>PBXClassBrowserModule</string>
  1562 + </array>
  1563 + <key>StatusbarIsVisible</key>
  1564 + <integer>0</integer>
  1565 + <key>TableOfContents</key>
  1566 + <array>
  1567 + <string>1C0AD2AF069F1E9B00FABCE6</string>
  1568 + <string>1C0AD2B0069F1E9B00FABCE6</string>
  1569 + <string>1CA6456E063B45B4001379D8</string>
  1570 + </array>
  1571 + <key>ToolbarConfiguration</key>
  1572 + <string>xcode.toolbar.config.classbrowser</string>
  1573 + <key>WindowString</key>
  1574 + <string>385 179 630 352 0 0 1440 878 </string>
  1575 + <key>WindowToolGUID</key>
  1576 + <string>1C0AD2AF069F1E9B00FABCE6</string>
  1577 + <key>WindowToolIsVisible</key>
  1578 + <integer>0</integer>
  1579 + </dict>
  1580 + <dict>
  1581 + <key>Identifier</key>
  1582 + <string>windowTool.refactoring</string>
  1583 + <key>IncludeInToolsMenu</key>
  1584 + <integer>0</integer>
  1585 + <key>Layout</key>
  1586 + <array>
  1587 + <dict>
  1588 + <key>Dock</key>
  1589 + <array>
  1590 + <dict>
  1591 + <key>BecomeActive</key>
  1592 + <integer>1</integer>
  1593 + <key>GeometryConfiguration</key>
  1594 + <dict>
  1595 + <key>Frame</key>
  1596 + <string>{0, 0}, {500, 335}</string>
  1597 + <key>RubberWindowFrame</key>
  1598 + <string>{0, 0}, {500, 335}</string>
  1599 + </dict>
  1600 + <key>Module</key>
  1601 + <string>XCRefactoringModule</string>
  1602 + <key>Proportion</key>
  1603 + <string>100%</string>
  1604 + </dict>
  1605 + </array>
  1606 + <key>Proportion</key>
  1607 + <string>100%</string>
  1608 + </dict>
  1609 + </array>
  1610 + <key>Name</key>
  1611 + <string>Refactoring</string>
  1612 + <key>ServiceClasses</key>
  1613 + <array>
  1614 + <string>XCRefactoringModule</string>
  1615 + </array>
  1616 + <key>WindowString</key>
  1617 + <string>200 200 500 356 0 0 1920 1200 </string>
  1618 + </dict>
  1619 + </array>
  1620 +</dict>
  1621 +</plist>
This diff could not be displayed because it is too large.
This diff was suppressed by a .gitattributes entry.
  1 +//
  2 +// Prefix header for all source files of the 'asi-http-request' target in the 'asi-http-request' project
  3 +//
  4 +
  5 +#ifdef __OBJC__
  6 + #import <Cocoa/Cocoa.h>
  7 +#endif
  1 +//
  2 +// main.m
  3 +// asi-http-request
  4 +//
  5 +// Created by Ben Copsey on 09/07/2008.
  6 +// Copyright __MyCompanyName__ 2008. All rights reserved.
  7 +//
  8 +
  9 +#import <Cocoa/Cocoa.h>
  10 +
  11 +int main(int argc, char *argv[])
  12 +{
  13 + return NSApplicationMain(argc, (const char **) argv);
  14 +}