Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added cookie support, including per-request cookies (request and resp…

…onse) and session persistant cookies

One or two small bug fixes
  • Loading branch information...
commit bc988eeaa7f29a5a3acb597be247643b90844bd1 1 parent d001857
@pokeb authored
View
34 ASIHTTPCookie.h
@@ -0,0 +1,34 @@
+//
+// ASIHTTPCookie.h
+// asi-http-request
+//
+// Created by Ben Copsey on 25/08/2008.
+// Copyright 2008 All-Seeing Interactive. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+
+
+@interface ASIHTTPCookie : NSObject {
+ NSString *name;
+ NSString *value;
+ NSDate *expires;
+ NSString *path;
+ NSString *domain;
+ BOOL requiresHTTPS;
+}
+
+- (void)setValue:(NSString *)newValue forProperty:(NSString *)property;
+
++ (NSMutableArray *)cookiesFromHeader:(NSString *)header;
++ (NSString *)urlEncodedValue:(NSString *)string;
++ (NSString *)urlDecodedValue:(NSString *)string;
+
+@property (retain) NSString *name;
+@property (retain) NSString *value;
+@property (retain) NSDate *expires;
+@property (retain) NSString *path;
+@property (retain) NSString *domain;
+@property (assign) BOOL requiresHTTPS;
+
+@end
View
100 ASIHTTPCookie.m
@@ -0,0 +1,100 @@
+//
+// ASIHTTPCookie.m
+// asi-http-request
+//
+// Created by Ben Copsey on 25/08/2008.
+// Copyright 2008 All-Seeing Interactive. All rights reserved.
+//
+
+#import "ASIHTTPCookie.h"
+
+@implementation ASIHTTPCookie
+
+- (void)setValue:(NSString *)newValue forProperty:(NSString *)property
+{
+ NSString *prop = [property lowercaseString];
+ if ([prop isEqualToString:@"expires"]) {
+ //[self setExpires:[NSDate dateFrom
+ return;
+ } else if ([prop isEqualToString:@"domain"]) {
+ [self setDomain:newValue];
+ return;
+ } else if ([prop isEqualToString:@"path"]) {
+ [self setPath:newValue];
+ return;
+ } else if ([prop isEqualToString:@"secure"]) {
+ [self setRequiresHTTPS:[newValue isEqualToString:@"1"]];
+ return;
+ }
+ if (![self name] && ![self value]) {
+ [self setName:property];
+ [self setValue:newValue];
+ }
+}
+
+
+// I know this looks like a really ugly way to parse the Set-Cookie header, but I'd guess this is probably one of the simplest methods!
+// You can't rely on a comma being a cookie delimeter, since it's quite likely that the expiry date for a cookie will contain a comma
+
+
++ (NSMutableArray *)cookiesFromHeader:(NSString *)header
+{
+ NSMutableArray *cookies = [[[NSMutableArray alloc] init] autorelease];
+ ASIHTTPCookie *cookie = [[[ASIHTTPCookie alloc] init] autorelease];
+
+ NSArray *parts = [header componentsSeparatedByString:@"="];
+ int i;
+ NSString *name;
+ NSString *value;
+ NSArray *components;
+ NSString *newKey;
+ NSString *terminator;
+ for (i=0; i<[parts count]; i++) {
+ NSString *part = [parts objectAtIndex:i];
+ if (i == 0) {
+ name = part;
+ continue;
+ } else if (i == [parts count]-1) {
+ [cookie setValue:[ASIHTTPCookie urlDecodedValue:part] forProperty:name];
+ [cookies addObject:cookie];
+ continue;
+ }
+ components = [part componentsSeparatedByString:@" "];
+ newKey = [components lastObject];
+ value = [part substringWithRange:NSMakeRange(0,[part length]-[newKey length]-2)];
+ [cookie setValue:[ASIHTTPCookie urlDecodedValue:value] forProperty:name];
+
+ terminator = [part substringWithRange:NSMakeRange([part length]-[newKey length]-2,1)];
+ if ([terminator isEqualToString:@","]) {
+ [cookies addObject:cookie];
+ cookie = [[[ASIHTTPCookie alloc] init] autorelease];
+ }
+ name = newKey;
+ }
+
+ return cookies;
+
+}
+
++ (NSString *)urlDecodedValue:(NSString *)string
+{
+ NSMutableString *s = [NSMutableString stringWithString:[string stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
+ //Also swap plus signs for spaces
+ [s replaceOccurrencesOfString:@"+" withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [s length])];
+ return [NSString stringWithString:s];
+}
+
++ (NSString *)urlEncodedValue:(NSString *)string
+{
+ return [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+}
+
+@synthesize name;
+@synthesize value;
+@synthesize expires;
+@synthesize path;
+@synthesize domain;
+@synthesize requiresHTTPS;
+@end
+
+
View
25 ASIHTTPRequest.h
@@ -32,9 +32,18 @@
//Dictionary for custom HTTP request headers
NSMutableDictionary *requestHeaders;
- //Will be populate with HTTP response headers from the server
+ //Will be populated with HTTP response headers from the server
NSDictionary *responseHeaders;
+ //Can be used to manually insert cookie headers to a request, but it's more likely that sessionCookies will do this for you
+ NSMutableArray *requestCookies;
+
+ //Will be populated with Cookies
+ NSMutableArray *responseCookies;
+
+ //If use cokie persistance is true, network requests will present valid cookies from previous requests
+ BOOL useCookiePersistance;
+
//If useKeychainPersistance is true, network requests will attempt to read credentials from the keychain, and will save them in the keychain when they are successfully presented
BOOL useKeychainPersistance;
@@ -215,6 +224,17 @@
// Remove credentials from the keychain
+ (void)removeCredentialsForHost:(NSString *)host port:(int)port protocol:(NSString *)protocol realm:(NSString *)realm;
+// Store cookies for a particular request in the session
++ (void)recordCookiesInSessionForRequest:(ASIHTTPRequest *)request;
+
++ (void)setSessionCookies:(NSMutableArray *)newSessionCookies;
++ (NSMutableArray *)sessionCookies;
+
+// Dump all session data (authentication and cookies)
++ (void)clearSession;
+
+
+
@property (retain) NSString *username;
@property (retain) NSString *password;
@property (retain) NSString *domain;
@@ -232,6 +252,9 @@
@property (retain) NSError *error;
@property (assign,readonly) BOOL complete;
@property (retain) NSDictionary *responseHeaders;
+@property (retain) NSMutableArray *requestCookies;
+@property (retain) NSMutableArray *responseCookies;
+@property (assign) BOOL useCookiePersistance;
@property (retain) NSDictionary *requestCredentials;
@property (assign) int responseStatusCode;
@property (retain) NSMutableData *receivedData;
View
119 ASIHTTPRequest.m
@@ -11,6 +11,7 @@
// See: http://developer.apple.com/samplecode/ImageClient/listing37.html
#import "ASIHTTPRequest.h"
+#import "ASIHTTPCookie.h"
static NSString *NetworkRequestErrorDomain = @"com.Your-Company.Your-Product.NetworkError.";
@@ -21,6 +22,7 @@
static CFHTTPAuthenticationRef sessionAuthentication = NULL;
static NSMutableDictionary *sessionCredentials = nil;
+static NSMutableArray *sessionCookies = nil;
static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventType type, void *clientCallBackInfo) {
@@ -51,6 +53,8 @@ - (id)initWithURL:(NSURL *)newURL
responseHeaders = nil;
[self setUseKeychainPersistance:NO];
[self setUseSessionPersistance:YES];
+ [self setUseCookiePersistance:YES];
+ [self setRequestCookies:[[[NSMutableArray alloc] init] autorelease]];
didFinishSelector = @selector(requestFinished:);
didFailSelector = @selector(requestFailed:);
delegate = nil;
@@ -164,6 +168,55 @@ - (void)main
//Set your own boundary string only if really obsessive. We don't bother to check if post data contains the boundary, since it's pretty unlikely that it does.
NSString *stringBoundary = @"0xKhTmLbOuNdArY";
+ //Add cookies from session
+ if (useCookiePersistance && [[ASIHTTPRequest sessionCookies] count] > 0) {
+ ASIHTTPCookie *requestCookie;
+ ASIHTTPCookie *storedCookie;
+ for (storedCookie in sessionCookies) {
+ BOOL foundExistingCookie = NO;
+ //Look for existing cookies in the request - these will always take precedence over session stored cookies
+ for (requestCookie in requestCookies) {
+ if ([[requestCookie domain] isEqualToString:[storedCookie domain]]) {
+ if ([[requestCookie path] isEqualToString:[storedCookie path]] || (![requestCookie path] && ![storedCookie path])) {
+ if ([[requestCookie name] isEqualToString:[storedCookie name]]) {
+ foundExistingCookie = YES;
+ break;
+ }
+ }
+ }
+ }
+ if (!foundExistingCookie) {
+ [requestCookies addObject:storedCookie];
+ }
+ }
+ }
+
+ //Apply request cookies
+ if ([requestCookies count] > 0) {
+ ASIHTTPCookie *cookie;
+ NSString *cookieHeader = nil;
+ for (cookie in requestCookies) {
+ //Ensure the cookie is valid for this request
+ if ([[[url host] substringWithRange:NSMakeRange([[url host] length]-[[cookie domain] length],[[cookie domain] length])] isEqualToString:[cookie domain]]) {
+ if ([[[url path] substringWithRange:NSMakeRange(0,[[cookie path] length])] isEqualToString:[cookie path]]) {
+ if (![cookie requiresHTTPS] || [[url port] intValue] == 443) {
+ if (![cookie expires] || [[cookie expires] timeIntervalSinceNow] > 0) {
+ if (!cookieHeader) {
+ cookieHeader = [NSString stringWithFormat: @"%@=%@",[cookie name],[ASIHTTPCookie urlEncodedValue:[cookie value]]];
+ } else {
+ cookieHeader = [NSString stringWithFormat: @"%@; %@=%@",cookieHeader,[cookie name],[ASIHTTPCookie urlEncodedValue:[cookie value]]];
+ }
+ }
+ }
+ }
+ }
+ }
+ if (cookieHeader) {
+ [self addRequestHeader:@"Cookie" value:cookieHeader];
+ }
+ }
+
+
//Add custom headers
NSString *header;
for (header in requestHeaders) {
@@ -207,8 +260,6 @@ - (void)main
}
[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
-
- NSString *foo = [[[NSString alloc] initWithBytes:[postBody bytes] length:[postBody length] encoding:NSUTF8StringEncoding] autorelease];
// Set the body.
CFHTTPMessageSetBody(request, (CFDataRef)postBody);
@@ -422,6 +473,16 @@ - (BOOL)readResponseHeadersReturningAuthenticationFailure
[self performSelectorOnMainThread:@selector(resetDownloadProgress:) withObject:[NSNumber numberWithDouble:contentLength] waitUntilDone:YES];
}
}
+
+ //Handle cookies
+ NSString *cookieHeader = [responseHeaders valueForKey:@"Set-Cookie"];
+ if (cookieHeader) {
+ [self setResponseCookies:[ASIHTTPCookie cookiesFromHeader:cookieHeader]];
+ if (useCookiePersistance) {
+ [ASIHTTPRequest recordCookiesInSessionForRequest:self];
+ }
+ }
+
}
}
@@ -768,6 +829,57 @@ + (void)removeCredentialsForHost:(NSString *)host port:(int)port protocol:(NSStr
}
++ (void)recordCookiesInSessionForRequest:(ASIHTTPRequest *)request
+{
+ if (!sessionCookies) {
+ [self setSessionCookies:[[[NSMutableArray alloc] init] autorelease]];
+ }
+ ASIHTTPCookie *newCookie;
+ ASIHTTPCookie *storedCookie;
+ for (newCookie in [request responseCookies]) {
+ //If we didn't get a domain for the cookie, let's add the one from this request, so we aren't sending cookies from the wrong server later on
+ if (![newCookie domain]) {
+ [newCookie setDomain:[[request url] host]];
+ }
+ int i = 0;
+ BOOL foundExistingCookie = NO;
+ for (storedCookie in sessionCookies) {
+ if ([[storedCookie domain] isEqualToString:[newCookie domain]]) {
+ if ([[storedCookie path] isEqualToString:[newCookie path]] || (![storedCookie path] && ![newCookie path])) {
+ if ([[storedCookie name] isEqualToString:[newCookie name]]) {
+ foundExistingCookie = YES;
+ [sessionCookies replaceObjectAtIndex:i withObject:newCookie];
+ break;
+ }
+ }
+ }
+ i++;
+ }
+ if (!foundExistingCookie) {
+ [sessionCookies addObject:newCookie];
+ }
+ }
+}
+
++ (NSMutableArray *)sessionCookies
+{
+ return sessionCookies;
+}
+
++ (void)setSessionCookies:(NSMutableArray *)newSessionCookies
+{
+ [sessionCookies release];
+ sessionCookies = [newSessionCookies retain];
+}
+
+// Dump all session data (authentication and cookies)
++ (void)clearSession
+{
+ [ASIHTTPRequest setSessionAuthentication:NULL];
+ [ASIHTTPRequest setSessionCredentials:nil];
+ [ASIHTTPRequest setSessionCookies:nil];
+}
+
@synthesize username;
@synthesize password;
@@ -778,6 +890,7 @@ + (void)removeCredentialsForHost:(NSString *)host port:(int)port protocol:(NSStr
@synthesize downloadProgressDelegate;
@synthesize useKeychainPersistance;
@synthesize useSessionPersistance;
+@synthesize useCookiePersistance;
@synthesize downloadDestinationPath;
@synthesize didFinishSelector;
@synthesize didFailSelector;
@@ -785,6 +898,8 @@ + (void)removeCredentialsForHost:(NSString *)host port:(int)port protocol:(NSStr
@synthesize error;
@synthesize complete;
@synthesize responseHeaders;
+@synthesize responseCookies;
+@synthesize requestCookies;
@synthesize requestCredentials;
@synthesize responseStatusCode;
@synthesize receivedData;
View
2  ASIHTTPRequestTests.h
@@ -14,5 +14,5 @@
- (void)testBasicDownload;
- (void)testOperationQueue;
-
+- (void)testCookies;
@end
View
224 ASIHTTPRequestTests.m
@@ -8,6 +8,7 @@
#import "ASIHTTPRequestTests.h"
#import "ASIHTTPRequest.h"
+#import "ASIHTTPCookie.h"
@implementation ASIHTTPRequestTests
@@ -23,96 +24,163 @@ @implementation ASIHTTPRequestTests
- Session persistence
*/
-- (void)testBasicDownload
+//- (void)testBasicDownload
+//{
+// //Grab data
+// NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com"] autorelease];
+// ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+// [request start];
+// NSString *html = [request dataString];
+// STAssertNotNil(html,@"Basic synchronous request failed");
+//
+// //Check we're getting the correct response headers
+// NSString *pingBackHeader = [[request responseHeaders] objectForKey:@"X-Pingback"];
+// BOOL success = [pingBackHeader isEqualToString:@"http://allseeing-i.com/Ping-Back"];
+// STAssertTrue(success,@"Failed to populate response headers");
+//
+// //Check we're getting back the correct status code
+// url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/a-page-that-does-not-exist"] autorelease];
+// request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+// [request start];
+// success = ([request responseStatusCode] == 404);
+// STAssertTrue(success,@"Didn't get correct status code");
+//
+// //Check data
+// NSRange notFound = NSMakeRange(NSNotFound, 0);
+// success = !NSEqualRanges([html rangeOfString:@"All-Seeing Interactive"],notFound);
+// STAssertTrue(success,@"Failed to download the correct data");
+//
+// //Attempt to grab from bad url (astonishingly, there is a website at http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com !)
+// url = [[[NSURL alloc] initWithString:@"http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaab.com"] autorelease];
+// request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+// [request start];
+// NSError *error = [request error];
+// STAssertNotNil(error,@"Failed to generate an error for a bad host - this test may fail when your DNS server redirects you to another page when it can't find a domain name (eg OpenDNS)");
+//}
+//
+//- (void)testOperationQueue
+//{
+// NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
+//
+// NSURL *url;
+// url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/asi-http-request/tests/first"] autorelease];
+// ASIHTTPRequest *request1 = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+// [queue addOperation:request1];
+//
+// url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/asi-http-request/tests/second"] autorelease];
+// ASIHTTPRequest *request2 = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+// [queue addOperation:request2];
+//
+// url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/asi-http-request/tests/third"] autorelease];
+// ASIHTTPRequest *request3 = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+// [queue addOperation:request3];
+//
+// url = [[[NSURL alloc] initWithString:@"http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaab.com"] autorelease];
+// ASIHTTPRequest *request4 = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+// [queue addOperation:request4];
+//
+// url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/asi-http-request/tests/broken"] autorelease];
+// ASIHTTPRequest *request5 = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+// [queue addOperation:request5];
+//
+// [queue waitUntilAllOperationsAreFinished];
+//
+// BOOL success;
+//
+// success = ([request1 error] == nil);
+// STAssertTrue(success,@"Request 1 failed");
+//
+// success = [[request1 dataString] isEqualToString:@"This is the expected content for the first string"];
+// STAssertTrue(success,@"Failed to download the correct data for request 1");
+//
+// success = ([request2 error] == nil);
+// STAssertTrue(success,@"Request 2 failed");
+//
+// success = [[request2 dataString] isEqualToString:@"This is the expected content for the second string"];
+// STAssertTrue(success,@"Failed to download the correct data for request 2");
+//
+// success = ([request3 error] == nil);
+// STAssertTrue(success,@"Request 3 failed");
+//
+// success = [[request3 dataString] isEqualToString:@"This is the expected content for the third string"];
+// STAssertTrue(success,@"Failed to download the correct data for request 3");
+//
+// success = ([request4 error] != nil);
+// STAssertTrue(success,@"Request 4 succeed when it should have failed - this test may fail when your DNS server redirects you to another page when it can't find a domain name (eg OpenDNS)");
+//
+// success = ([request5 error] == nil);
+// STAssertTrue(success,@"Request 5 failed");
+//
+// success = ([request5 responseStatusCode] == 404);
+// STAssertTrue(success,@"Failed to obtain the correct status code for request 5");
+//
+//}
+
+- (void)testCookies
{
- //Grab data
- NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com"] autorelease];
+ BOOL success;
+
+ NSURL *url = [[[NSURL alloc] initWithString:@"http://asi/asi-http-request/tests/set_cookie"] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+ [request setUseCookiePersistance:YES];
[request start];
NSString *html = [request dataString];
- STAssertNotNil(html,@"Basic synchronous request failed");
-
- //Check we're getting the correct response headers
- NSString *pingBackHeader = [[request responseHeaders] objectForKey:@"X-Pingback"];
- BOOL success = [pingBackHeader isEqualToString:@"http://allseeing-i.com/Ping-Back"];
- STAssertTrue(success,@"Failed to populate response headers");
+ success = [html isEqualToString:@"I have set a cookie"];
+ STAssertTrue(success,@"Failed to set a cookie");
- //Check we're getting back the correct status code
- url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/a-page-that-does-not-exist"] autorelease];
- request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
- [request start];
- success = ([request responseStatusCode] == 404);
- STAssertTrue(success,@"Didn't get correct status code");
+ NSArray *cookies = [request responseCookies];
+ STAssertNotNil(cookies,@"Failed to store cookie data in responseCookies");
+
+ ASIHTTPCookie *cookie = nil;
+ BOOL foundCookie = NO;
+ for (cookie in cookies) {
+ if ([[cookie name] isEqualToString:@"ASIHTTPRequestTestCookie"]) {
+ foundCookie = YES;
+ success = [[cookie value] isEqualToString:@"This is the value"];
+ STAssertTrue(success,@"Failed to store the correct value for a cookie");
+ success = [[cookie domain] isEqualToString:@"asi"];
+ STAssertTrue(success,@"Failed to store the correct domain for a cookie");
+ success = [[cookie path] isEqualToString:@"/asi-http-request/tests"];
+ STAssertTrue(success,@"Failed to store the correct path for a cookie");
+ break;
+ }
+ }
+ STAssertTrue(foundCookie,@"Failed store a particular cookie - can't continue with the rest of the tests");
- //Check data
- NSRange notFound = NSMakeRange(NSNotFound, 0);
- success = !NSEqualRanges([html rangeOfString:@"All-Seeing Interactive"],notFound);
- STAssertTrue(success,@"Failed to download the correct data");
+ if (!foundCookie) {
+ return;
+ }
- //Attempt to grab from bad url (astonishingly, there is a website at http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com !)
- url = [[[NSURL alloc] initWithString:@"http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaab.com"] autorelease];
+ url = [[[NSURL alloc] initWithString:@"http://asi/asi-http-request/tests/read_cookie"] autorelease];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+ [request setUseCookiePersistance:NO];
+ [request setRequestCookies:[NSMutableArray arrayWithObject:cookie]];
[request start];
- NSError *error = [request error];
- STAssertNotNil(error,@"Failed to generate an error for a bad host");
-}
+ html = [request dataString];
+ success = [html isEqualToString:@"I have 'This is the value' as the value of 'ASIHTTPRequestTestCookie'"];
+ STAssertTrue(success,@"Cookie not presented to the server with cookie persistance OFF");
-- (void)testOperationQueue
-{
- NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
-
- NSURL *url;
- url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/asi-http-request/tests/first"] autorelease];
- ASIHTTPRequest *request1 = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
- [queue addOperation:request1];
-
- url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/asi-http-request/tests/second"] autorelease];
- ASIHTTPRequest *request2 = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
- [queue addOperation:request2];
-
- url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/asi-http-request/tests/third"] autorelease];
- ASIHTTPRequest *request3 = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
- [queue addOperation:request3];
-
- url = [[[NSURL alloc] initWithString:@"http://aaaaaaaaaaaaaaaaaaaaaaaaaaaaab.com"] autorelease];
- ASIHTTPRequest *request4 = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
- [queue addOperation:request4];
-
- url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/asi-http-request/tests/broken"] autorelease];
- ASIHTTPRequest *request5 = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
- [queue addOperation:request5];
-
- [queue waitUntilAllOperationsAreFinished];
-
- BOOL success;
-
- success = ([request1 error] == nil);
- STAssertTrue(success,@"Request 1 failed");
-
- success = [[request1 dataString] isEqualToString:@"This is the expected content for the first string"];
- STAssertTrue(success,@"Failed to download the correct data for request 1");
-
- success = ([request2 error] == nil);
- STAssertTrue(success,@"Request 2 failed");
-
- success = [[request2 dataString] isEqualToString:@"This is the expected content for the second string"];
- STAssertTrue(success,@"Failed to download the correct data for request 2");
-
- success = ([request3 error] == nil);
- STAssertTrue(success,@"Request 3 failed");
-
- success = [[request3 dataString] isEqualToString:@"This is the expected content for the third string"];
- STAssertTrue(success,@"Failed to download the correct data for request 3");
+ url = [[[NSURL alloc] initWithString:@"http://asi/asi-http-request/tests/read_cookie"] autorelease];
+ request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+ [request setUseCookiePersistance:YES];
+ [request start];
+ html = [request dataString];
+ success = [html isEqualToString:@"I have 'This is the value' as the value of 'ASIHTTPRequestTestCookie'"];
+ STAssertTrue(success,@"Cookie not presented to the server with cookie persistance ON");
- success = ([request4 error] != nil);
- STAssertTrue(success,@"Request 4 succeed when it should have failed");
+ url = [[[NSURL alloc] initWithString:@"http://asi/asi-http-request/tests/remove_cookie"] autorelease];
+ request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+ [request start];
+ html = [request dataString];
+ success = [html isEqualToString:@"I have removed a cookie"];
+ STAssertTrue(success,@"Failed to remove a cookie");
- success = ([request5 error] == nil);
- STAssertTrue(success,@"Request 5 failed");
-
- success = ([request5 responseStatusCode] == 404);
- STAssertTrue(success,@"Failed to obtain the correct status code for request 5");
-
+ url = [[[NSURL alloc] initWithString:@"http://asi/asi-http-request/tests/read_cookie"] autorelease];
+ request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+ [request start];
+ html = [request dataString];
+ success = [html isEqualToString:@"No cookie exists"];
+ STAssertTrue(success,@"Cookie presented to the server when it should have been removed");
}
@end
View
3  AppDelegate.m
@@ -147,7 +147,8 @@ - (IBAction)dismissAuthSheet:(id)sender {
- (void)authSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo {
ASIHTTPRequest *request = (ASIHTTPRequest *)contextInfo;
if (returnCode == NSOKButton) {
- [request setUsername:[[[username stringValue] copy] autorelease] andPassword:[[[password stringValue] copy] autorelease]];
+ [request setUsername:[[[username stringValue] copy] autorelease]];
+ [request setPassword:[[[password stringValue] copy] autorelease]];
[request retryWithAuthentication];
} else {
[request cancelLoad];
View
7 README
@@ -27,6 +27,9 @@ ASIHTTPRequest is partly based on code from Apple's ImageClient code samples, so
ASIHTTPRequest is my first open source Objective-C code. I hope to expand the class and example application further (unit tests, maybe even iphone examples...) in the coming months. If you find it helpful, please do get in touch!
To do:
-NTLM Authentication?
-Digest Authentication?
+More unit tests
+Cookie support
+Split up class - move form request stuff into subclass, and have simple implementation for main that sets request body according to data supplied by the subclass - this will allow other types of HTTP request (eg soap)
+Add SOAP example
+See if Digest Authentication works
PUT / DELETE /GET?
View
297 asi-http-request.xcodeproj/ben.mode1v3
@@ -197,7 +197,48 @@
<key>Notifications</key>
<array/>
<key>OpenEditors</key>
- <array/>
+ <array>
+ <dict>
+ <key>Content</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>B5B3BD2C0E6331590071D39F</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>ASIHTTPRequestTests.m</string>
+ <key>PBXSplitModuleInNavigatorKey</key>
+ <dict>
+ <key>Split0</key>
+ <dict>
+ <key>PBXProjectModuleGUID</key>
+ <string>B5B3BD2D0E6331590071D39F</string>
+ <key>PBXProjectModuleLabel</key>
+ <string>ASIHTTPRequestTests.m</string>
+ <key>_historyCapacity</key>
+ <integer>0</integer>
+ <key>bookmark</key>
+ <string>B5B3BF0C0E6345DB0071D39F</string>
+ <key>history</key>
+ <array>
+ <string>B5B3BD2A0E6331480071D39F</string>
+ </array>
+ </dict>
+ <key>SplitCount</key>
+ <string>1</string>
+ </dict>
+ <key>StatusBarVisibility</key>
+ <true/>
+ </dict>
+ <key>Geometry</key>
+ <dict>
+ <key>Frame</key>
+ <string>{{0, 20}, {1485, 777}}</string>
+ <key>PBXModuleWindowStatusBarHidden2</key>
+ <false/>
+ <key>RubberWindowFrame</key>
+ <string>64 -59 1485 818 0 0 1920 1178 </string>
+ </dict>
+ </dict>
+ </array>
<key>PerspectiveWidths</key>
<array>
<integer>-1</integer>
@@ -279,13 +320,13 @@
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
<array>
<array>
- <integer>9</integer>
+ <integer>11</integer>
<integer>5</integer>
<integer>0</integer>
</array>
</array>
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
- <string>{{0, 0}, {312, 760}}</string>
+ <string>{{0, 0}, {312, 861}}</string>
</dict>
<key>PBXTopSmartGroupGIDs</key>
<array/>
@@ -297,14 +338,14 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
- <string>{{0, 0}, {329, 778}}</string>
+ <string>{{0, 0}, {329, 879}}</string>
<key>GroupTreeTableConfiguration</key>
<array>
<string>MainColumn</string>
<real>312</real>
</array>
<key>RubberWindowFrame</key>
- <string>409 250 1342 819 0 0 1920 1178 </string>
+ <string>156 103 1647 920 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXSmartGroupTreeModule</string>
@@ -334,23 +375,26 @@
<key>_historyCapacity</key>
<integer>0</integer>
<key>bookmark</key>
- <string>B567EF390E4EDE4A001E238F</string>
+ <string>B5B3BF0B0E6345DB0071D39F</string>
<key>history</key>
<array>
<string>B5731B8B0E4310180008024F</string>
<string>B5731BBE0E4319180008024F</string>
<string>B5731BEE0E431A050008024F</string>
<string>B5731BEF0E431A050008024F</string>
- <string>B5731BF00E431A050008024F</string>
<string>B5731E180E43424A0008024F</string>
- <string>B5731E330E4344F90008024F</string>
- <string>B5731E550E435ADB0008024F</string>
<string>B5F3B7370E43683600E001FD</string>
<string>B5F3B74C0E4378FA00E001FD</string>
- <string>B567EEF10E4EDA85001E238F</string>
- <string>B567EF2B0E4EDC06001E238F</string>
- <string>B567EF2C0E4EDC06001E238F</string>
- <string>B567EF140E4EDB3D001E238F</string>
+ <string>B567EF5C0E4EE4FC001E238F</string>
+ <string>B567EF5D0E4EE4FC001E238F</string>
+ <string>B5B3BE530E633CEE0071D39F</string>
+ <string>B5B3BE950E63407D0071D39F</string>
+ <string>B5B3BEA90E6342110071D39F</string>
+ <string>B5B3BEC50E6342C30071D39F</string>
+ <string>B5B3BEC60E6342C30071D39F</string>
+ <string>B5B3BEC70E6342C30071D39F</string>
+ <string>B5B3BF070E6345DB0071D39F</string>
+ <string>B5B3BF080E6345DB0071D39F</string>
</array>
<key>prevStack</key>
<array>
@@ -368,15 +412,140 @@
<string>B5731BF60E431A050008024F</string>
<string>B5731D9B0E433A750008024F</string>
<string>B5F3B7390E43683600E001FD</string>
- <string>B567EEF40E4EDA85001E238F</string>
- <string>B567EEF50E4EDA85001E238F</string>
- <string>B567EEF60E4EDA85001E238F</string>
- <string>B567EEF70E4EDA85001E238F</string>
- <string>B567EEF80E4EDA85001E238F</string>
- <string>B567EEF90E4EDA85001E238F</string>
- <string>B567EF160E4EDB3D001E238F</string>
- <string>B567EF2D0E4EDC06001E238F</string>
- <string>B567EF2E0E4EDC06001E238F</string>
+ <string>B567EF630E4EE4FC001E238F</string>
+ <string>B5B3BC680E62DA0E0071D39F</string>
+ <string>B5B3BC690E62DA0E0071D39F</string>
+ <string>B5B3BC6A0E62DA0E0071D39F</string>
+ <string>B5B3BC6B0E62DA0E0071D39F</string>
+ <string>B5B3BC6C0E62DA0E0071D39F</string>
+ <string>B5B3BC6D0E62DA0E0071D39F</string>
+ <string>B5B3BC6E0E62DA0E0071D39F</string>
+ <string>B5B3BC6F0E62DA0E0071D39F</string>
+ <string>B5B3BC700E62DA0E0071D39F</string>
+ <string>B5B3BC710E62DA0E0071D39F</string>
+ <string>B5B3BC720E62DA0E0071D39F</string>
+ <string>B5B3BC730E62DA0E0071D39F</string>
+ <string>B5B3BC740E62DA0E0071D39F</string>
+ <string>B5B3BC750E62DA0E0071D39F</string>
+ <string>B5B3BC760E62DA0E0071D39F</string>
+ <string>B5B3BC770E62DA0E0071D39F</string>
+ <string>B5B3BC780E62DA0E0071D39F</string>
+ <string>B5B3BC790E62DA0E0071D39F</string>
+ <string>B5B3BC7A0E62DA0E0071D39F</string>
+ <string>B5B3BC7B0E62DA0E0071D39F</string>
+ <string>B5B3BC7C0E62DA0E0071D39F</string>
+ <string>B5B3BC7D0E62DA0E0071D39F</string>
+ <string>B5B3BC7E0E62DA0E0071D39F</string>
+ <string>B5B3BC7F0E62DA0E0071D39F</string>
+ <string>B5B3BC920E6315CD0071D39F</string>
+ <string>B5B3BC930E6315CD0071D39F</string>
+ <string>B5B3BC940E6315CD0071D39F</string>
+ <string>B5B3BC950E6315CD0071D39F</string>
+ <string>B5B3BC960E6315CD0071D39F</string>
+ <string>B5B3BCA60E6321C20071D39F</string>
+ <string>B5B3BCA70E6321C20071D39F</string>
+ <string>B5B3BCAE0E6325820071D39F</string>
+ <string>B5B3BCB60E6325E00071D39F</string>
+ <string>B5B3BCB70E6325E00071D39F</string>
+ <string>B5B3BCB80E6325E00071D39F</string>
+ <string>B5B3BCB90E6325E00071D39F</string>
+ <string>B5B3BCBA0E6325E00071D39F</string>
+ <string>B5B3BCBB0E6325E00071D39F</string>
+ <string>B5B3BCCB0E6329C00071D39F</string>
+ <string>B5B3BCCC0E6329C00071D39F</string>
+ <string>B5B3BCCD0E6329C00071D39F</string>
+ <string>B5B3BCCE0E6329C00071D39F</string>
+ <string>B5B3BCCF0E6329C00071D39F</string>
+ <string>B5B3BCD00E6329C00071D39F</string>
+ <string>B5B3BCD10E6329C00071D39F</string>
+ <string>B5B3BCD20E6329C00071D39F</string>
+ <string>B5B3BCD30E6329C00071D39F</string>
+ <string>B5B3BCD40E6329C00071D39F</string>
+ <string>B5B3BCE00E632DEB0071D39F</string>
+ <string>B5B3BD060E632F3C0071D39F</string>
+ <string>B5B3BD070E632F3C0071D39F</string>
+ <string>B5B3BD190E63306D0071D39F</string>
+ <string>B5B3BD250E6331470071D39F</string>
+ <string>B5B3BD260E6331470071D39F</string>
+ <string>B5B3BD270E6331470071D39F</string>
+ <string>B5B3BD3F0E6331CF0071D39F</string>
+ <string>B5B3BD470E6332B70071D39F</string>
+ <string>B5B3BD4D0E6332CB0071D39F</string>
+ <string>B5B3BD570E6333180071D39F</string>
+ <string>B5B3BD630E63333D0071D39F</string>
+ <string>B5B3BD640E63333D0071D39F</string>
+ <string>B5B3BD650E63333D0071D39F</string>
+ <string>B5B3BD660E63333D0071D39F</string>
+ <string>B5B3BDCF0E6336640071D39F</string>
+ <string>B5B3BDD00E6336640071D39F</string>
+ <string>B5B3BDD10E6336640071D39F</string>
+ <string>B5B3BDD20E6336640071D39F</string>
+ <string>B5B3BDD30E6336640071D39F</string>
+ <string>B5B3BDD40E6336640071D39F</string>
+ <string>B5B3BDD50E6336640071D39F</string>
+ <string>B5B3BDDE0E6336920071D39F</string>
+ <string>B5B3BDDF0E6336920071D39F</string>
+ <string>B5B3BDE00E6336920071D39F</string>
+ <string>B5B3BDEA0E6336A70071D39F</string>
+ <string>B5B3BDEB0E6336A70071D39F</string>
+ <string>B5B3BDF80E63370C0071D39F</string>
+ <string>B5B3BDF90E63370C0071D39F</string>
+ <string>B5B3BDFA0E63370C0071D39F</string>
+ <string>B5B3BDFB0E63370C0071D39F</string>
+ <string>B5B3BDFC0E63370C0071D39F</string>
+ <string>B5B3BDFD0E63370C0071D39F</string>
+ <string>B5B3BDFE0E63370C0071D39F</string>
+ <string>B5B3BE200E63389F0071D39F</string>
+ <string>B5B3BE210E63389F0071D39F</string>
+ <string>B5B3BE220E63389F0071D39F</string>
+ <string>B5B3BE2E0E6338E60071D39F</string>
+ <string>B5B3BE550E633CEE0071D39F</string>
+ <string>B5B3BE560E633CEE0071D39F</string>
+ <string>B5B3BE570E633CEE0071D39F</string>
+ <string>B5B3BE580E633CEE0071D39F</string>
+ <string>B5B3BE590E633CEE0071D39F</string>
+ <string>B5B3BE5A0E633CEE0071D39F</string>
+ <string>B5B3BE5B0E633CEE0071D39F</string>
+ <string>B5B3BE5C0E633CEE0071D39F</string>
+ <string>B5B3BE5D0E633CEE0071D39F</string>
+ <string>B5B3BE5E0E633CEE0071D39F</string>
+ <string>B5B3BE5F0E633CEE0071D39F</string>
+ <string>B5B3BE740E633FA50071D39F</string>
+ <string>B5B3BE750E633FA50071D39F</string>
+ <string>B5B3BE760E633FA50071D39F</string>
+ <string>B5B3BE770E633FA50071D39F</string>
+ <string>B5B3BE780E633FA50071D39F</string>
+ <string>B5B3BE790E633FA50071D39F</string>
+ <string>B5B3BE7A0E633FA50071D39F</string>
+ <string>B5B3BE7B0E633FA50071D39F</string>
+ <string>B5B3BE980E63407D0071D39F</string>
+ <string>B5B3BE990E63407D0071D39F</string>
+ <string>B5B3BE9A0E63407D0071D39F</string>
+ <string>B5B3BE9B0E63407D0071D39F</string>
+ <string>B5B3BE9C0E63407D0071D39F</string>
+ <string>B5B3BEAD0E6342110071D39F</string>
+ <string>B5B3BEAE0E6342110071D39F</string>
+ <string>B5B3BEAF0E6342110071D39F</string>
+ <string>B5B3BEB00E6342110071D39F</string>
+ <string>B5B3BEB10E6342110071D39F</string>
+ <string>B5B3BEB20E6342110071D39F</string>
+ <string>B5B3BEB30E6342110071D39F</string>
+ <string>B5B3BEBA0E6342730071D39F</string>
+ <string>B5B3BECA0E6342C30071D39F</string>
+ <string>B5B3BECB0E6342C30071D39F</string>
+ <string>B5B3BECC0E6342C30071D39F</string>
+ <string>B5B3BECD0E6342C30071D39F</string>
+ <string>B5B3BECE0E6342C30071D39F</string>
+ <string>B5B3BECF0E6342C30071D39F</string>
+ <string>B5B3BED00E6342C30071D39F</string>
+ <string>B5B3BED10E6342C30071D39F</string>
+ <string>B5B3BED90E63431A0071D39F</string>
+ <string>B5B3BEEC0E6344FC0071D39F</string>
+ <string>B5B3BEF40E6345140071D39F</string>
+ <string>B5B3BF000E63459A0071D39F</string>
+ <string>B5B3BF010E63459A0071D39F</string>
+ <string>B5B3BF090E6345DB0071D39F</string>
+ <string>B5B3BF0A0E6345DB0071D39F</string>
</array>
</dict>
<key>SplitCount</key>
@@ -388,14 +557,14 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
- <string>{{0, 0}, {1008, 679}}</string>
+ <string>{{0, 0}, {1313, 780}}</string>
<key>RubberWindowFrame</key>
- <string>409 250 1342 819 0 0 1920 1178 </string>
+ <string>156 103 1647 920 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXNavigatorGroup</string>
<key>Proportion</key>
- <string>679pt</string>
+ <string>780pt</string>
</dict>
<dict>
<key>ContentConfiguration</key>
@@ -408,9 +577,9 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
- <string>{{0, 684}, {1008, 94}}</string>
+ <string>{{0, 785}, {1313, 94}}</string>
<key>RubberWindowFrame</key>
- <string>409 250 1342 819 0 0 1920 1178 </string>
+ <string>156 103 1647 920 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>XCDetailModule</string>
@@ -419,7 +588,7 @@
</dict>
</array>
<key>Proportion</key>
- <string>1008pt</string>
+ <string>1313pt</string>
</dict>
</array>
<key>Name</key>
@@ -434,9 +603,9 @@
</array>
<key>TableOfContents</key>
<array>
- <string>B567EEE20E4ED8D2001E238F</string>
+ <string>B5B3BC400E62D2810071D39F</string>
<string>1CE0B1FE06471DED0097A5F4</string>
- <string>B567EEE30E4ED8D2001E238F</string>
+ <string>B5B3BC410E62D2810071D39F</string>
<string>1CE0B20306471E060097A5F4</string>
<string>1CE0B20506471E060097A5F4</string>
</array>
@@ -570,16 +739,18 @@
<integer>5</integer>
<key>WindowOrderList</key>
<array>
+ <string>B5B3BF0D0E6345DB0071D39F</string>
<string>1C530D57069F1CE1000CFCEE</string>
- <string>B567EF0F0E4EDB31001E238F</string>
- <string>B567EF100E4EDB31001E238F</string>
+ <string>B5B3BCD60E6329C00071D39F</string>
+ <string>B5B3BCD70E6329C00071D39F</string>
<string>B5ABC8410E24CDE70072F422</string>
+ <string>B5B3BD2C0E6331590071D39F</string>
<string>1C78EAAD065D492600B07095</string>
<string>1CD10A99069EF8BA00B06720</string>
<string>/Users/ben/asi-http-request/asi-http-request.xcodeproj</string>
</array>
<key>WindowString</key>
- <string>409 250 1342 819 0 0 1920 1178 </string>
+ <string>156 103 1647 920 0 0 1920 1178 </string>
<key>WindowToolsV3</key>
<array>
<dict>
@@ -595,8 +766,6 @@
<key>Dock</key>
<array>
<dict>
- <key>BecomeActive</key>
- <true/>
<key>ContentConfiguration</key>
<dict>
<key>PBXProjectModuleGUID</key>
@@ -611,7 +780,7 @@
<key>Frame</key>
<string>{{0, 0}, {1440, 536}}</string>
<key>RubberWindowFrame</key>
- <string>287 118 1440 818 0 0 1920 1178 </string>
+ <string>283 203 1440 818 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXNavigatorGroup</string>
@@ -619,6 +788,8 @@
<string>536pt</string>
</dict>
<dict>
+ <key>BecomeActive</key>
+ <true/>
<key>ContentConfiguration</key>
<dict>
<key>PBXProjectModuleGUID</key>
@@ -635,7 +806,7 @@
<key>Frame</key>
<string>{{0, 541}, {1440, 236}}</string>
<key>RubberWindowFrame</key>
- <string>287 118 1440 818 0 0 1920 1178 </string>
+ <string>283 203 1440 818 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXBuildResultsModule</string>
@@ -658,18 +829,18 @@
<key>TableOfContents</key>
<array>
<string>B5ABC8410E24CDE70072F422</string>
- <string>B567EEE40E4ED8D2001E238F</string>
+ <string>B5B3BC500E62D8FB0071D39F</string>
<string>1CD0528F0623707200166675</string>
<string>XCMainBuildResultsModuleGUID</string>
</array>
<key>ToolbarConfiguration</key>
<string>xcode.toolbar.config.buildV3</string>
<key>WindowString</key>
- <string>287 118 1440 818 0 0 1920 1178 </string>
+ <string>283 203 1440 818 0 0 1920 1178 </string>
<key>WindowToolGUID</key>
<string>B5ABC8410E24CDE70072F422</string>
<key>WindowToolIsVisible</key>
- <true/>
+ <false/>
</dict>
<dict>
<key>FirstTimeWindowDisplayed</key>
@@ -743,19 +914,19 @@
<key>DebugVariablesTableConfiguration</key>
<array>
<string>Name</string>
- <real>420</real>
+ <real>151</real>
<string>Value</string>
- <real>255</real>
+ <real>85</real>
<string>Summary</string>
- <real>151</real>
+ <real>590</real>
</array>
<key>Frame</key>
<string>{{713, 0}, {851, 339}}</string>
<key>RubberWindowFrame</key>
- <string>158 131 1564 676 0 0 1920 1178 </string>
+ <string>231 251 1564 676 0 0 1920 1178 </string>
</dict>
<key>RubberWindowFrame</key>
- <string>158 131 1564 676 0 0 1920 1178 </string>
+ <string>231 251 1564 676 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXDebugSessionModule</string>
@@ -778,18 +949,18 @@
<key>TableOfContents</key>
<array>
<string>1CD10A99069EF8BA00B06720</string>
- <string>B567EEE50E4ED8D2001E238F</string>
+ <string>B5B3BC510E62D8FB0071D39F</string>
<string>1C162984064C10D400B95A72</string>
- <string>B567EEE60E4ED8D2001E238F</string>
- <string>B567EEE70E4ED8D2001E238F</string>
- <string>B567EEE80E4ED8D2001E238F</string>
- <string>B567EEE90E4ED8D2001E238F</string>
- <string>B567EEEA0E4ED8D2001E238F</string>
+ <string>B5B3BC520E62D8FB0071D39F</string>
+ <string>B5B3BC530E62D8FB0071D39F</string>
+ <string>B5B3BC540E62D8FB0071D39F</string>
+ <string>B5B3BC550E62D8FB0071D39F</string>
+ <string>B5B3BC560E62D8FB0071D39F</string>
</array>
<key>ToolbarConfiguration</key>
<string>xcode.toolbar.config.debugV3</string>
<key>WindowString</key>
- <string>158 131 1564 676 0 0 1920 1178 </string>
+ <string>231 251 1564 676 0 0 1920 1178 </string>
<key>WindowToolGUID</key>
<string>1CD10A99069EF8BA00B06720</string>
<key>WindowToolIsVisible</key>
@@ -811,12 +982,14 @@
<key>Dock</key>
<array>
<dict>
+ <key>BecomeActive</key>
+ <true/>
<key>ContentConfiguration</key>
<dict>
<key>PBXProjectModuleGUID</key>
<string>1CDD528C0622207200134675</string>
<key>PBXProjectModuleLabel</key>
- <string></string>
+ <string>ASIHTTPCookie.m</string>
<key>StatusBarVisibility</key>
<true/>
</dict>
@@ -837,8 +1010,6 @@
<string>212pt</string>
</dict>
<dict>
- <key>BecomeActive</key>
- <true/>
<key>ContentConfiguration</key>
<dict>
<key>PBXProjectModuleGUID</key>
@@ -874,8 +1045,8 @@
<key>TableOfContents</key>
<array>
<string>1C530D57069F1CE1000CFCEE</string>
- <string>B567EF350E4EDE05001E238F</string>
- <string>B567EF360E4EDE05001E238F</string>
+ <string>B5B3BE4F0E633CE50071D39F</string>
+ <string>B5B3BE500E633CE50071D39F</string>
<string>1CDD528C0622207200134675</string>
<string>1CD0528E0623707200166675</string>
</array>
@@ -915,18 +1086,18 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
- <string>{{0, 0}, {636, 839}}</string>
+ <string>{{0, 0}, {985, 866}}</string>
<key>RubberWindowFrame</key>
- <string>138 298 636 880 0 0 1920 1178 </string>
+ <string>433 271 985 907 0 0 1920 1178 </string>
</dict>
<key>Module</key>
<string>PBXDebugCLIModule</string>
<key>Proportion</key>
- <string>839pt</string>
+ <string>866pt</string>
</dict>
</array>
<key>Proportion</key>
- <string>839pt</string>
+ <string>866pt</string>
</dict>
</array>
<key>Name</key>
@@ -940,13 +1111,13 @@
<key>TableOfContents</key>
<array>
<string>1C78EAAD065D492600B07095</string>
- <string>B567EEEB0E4ED8D2001E238F</string>
+ <string>B5B3BC810E62DA0E0071D39F</string>
<string>1C78EAAC065D492600B07095</string>
</array>
<key>ToolbarConfiguration</key>
<string>xcode.toolbar.config.consoleV3</string>
<key>WindowString</key>
- <string>138 298 636 880 0 0 1920 1178 </string>
+ <string>433 271 985 907 0 0 1920 1178 </string>
<key>WindowToolGUID</key>
<string>1C78EAAD065D492600B07095</string>
<key>WindowToolIsVisible</key>
View
4,229 asi-http-request.xcodeproj/ben.pbxuser
4,057 additions, 172 deletions not shown
View
8 asi-http-request.xcodeproj/project.pbxproj
@@ -17,6 +17,8 @@
B5731C300E431B340008024F /* ASIHTTPRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B5731AFB0E430B1F0008024F /* ASIHTTPRequestTests.m */; };
B5ABC7BB0E24C5620072F422 /* ASIHTTPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B5ABC7B90E24C5620072F422 /* ASIHTTPRequest.m */; };
B5ABC80F0E24CB100072F422 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B5ABC80E0E24CB100072F422 /* AppDelegate.m */; };
+ B5B3BC480E62D4790071D39F /* ASIHTTPCookie.m in Sources */ = {isa = PBXBuildFile; fileRef = B5B3BC470E62D4790071D39F /* ASIHTTPCookie.m */; };
+ B5B3BCC10E6327100071D39F /* ASIHTTPCookie.m in Sources */ = {isa = PBXBuildFile; fileRef = B5B3BC470E62D4790071D39F /* ASIHTTPCookie.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -52,6 +54,8 @@
B5ABC7ED0E24C6670072F422 /* ASIProgressDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIProgressDelegate.h; sourceTree = "<group>"; };
B5ABC80D0E24CB100072F422 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
B5ABC80E0E24CB100072F422 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+ B5B3BC460E62D4790071D39F /* ASIHTTPCookie.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASIHTTPCookie.h; sourceTree = "<group>"; };
+ B5B3BC470E62D4790071D39F /* ASIHTTPCookie.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASIHTTPCookie.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -78,6 +82,8 @@
080E96DDFE201D6D7F000001 /* Classes */ = {
isa = PBXGroup;
children = (
+ B5B3BC460E62D4790071D39F /* ASIHTTPCookie.h */,
+ B5B3BC470E62D4790071D39F /* ASIHTTPCookie.m */,
B5ABC80D0E24CB100072F422 /* AppDelegate.h */,
B5ABC80E0E24CB100072F422 /* AppDelegate.m */,
B5ABC7BA0E24C5620072F422 /* ASIHTTPRequest.h */,
@@ -269,6 +275,7 @@
8D11072D0486CEB800E47090 /* main.m in Sources */,
B5ABC7BB0E24C5620072F422 /* ASIHTTPRequest.m in Sources */,
B5ABC80F0E24CB100072F422 /* AppDelegate.m in Sources */,
+ B5B3BC480E62D4790071D39F /* ASIHTTPCookie.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -278,6 +285,7 @@
files = (
B5731B250E430B800008024F /* ASIHTTPRequest.m in Sources */,
B5731C300E431B340008024F /* ASIHTTPRequestTests.m in Sources */,
+ B5B3BCC10E6327100071D39F /* ASIHTTPCookie.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Please sign in to comment.
Something went wrong with that request. Please try again.