<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -541,9 +541,17 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
 // Returns the maximum amount of data we can read as part of the current measurement period, and sleeps this thread if our allowance is used up
 + (unsigned long)maxUploadReadLength;
 
+#pragma mark miscellany 
+
 // Determines whether we're on iPhone OS 2.0 at runtime, currently used to determine whether we should apply a workaround for an issue with converting longs to doubles on iPhone OS 2
 + (BOOL)isiPhoneOS2;
 
+// Used for generating Authorization header when using basic authentication when shouldPresentCredentialsBeforeChallenge is true
+// And also by ASIS3Request
++ (NSString *)base64forData:(NSData *)theData;
+
+#pragma mark ===
+
 @property (retain) NSString *username;
 @property (retain) NSString *password;
 @property (retain) NSString *domain;</diff>
      <filename>Classes/ASIHTTPRequest.h</filename>
    </modified>
    <modified>
      <diff>@@ -141,8 +141,6 @@ static BOOL isiPhoneOS2;
 
 @implementation ASIHTTPRequest
 
-
-
 #pragma mark init / dealloc
 
 + (void)initialize
@@ -456,15 +454,31 @@ static BOOL isiPhoneOS2;
     }
 	
 	
-	// If we've already talked to this server and have valid credentials, let's apply them to the request
+	
 	if ([self shouldPresentCredentialsBeforeChallenge]) {
+		
+		NSDictionary *credentials = nil;
 		if ([self useSessionPersistance]) {
-			NSDictionary *credentials = [self findSessionAuthenticationCredentials];
-			if (credentials) {
-				if (!CFHTTPMessageApplyCredentialDictionary(request, (CFHTTPAuthenticationRef)[credentials objectForKey:@&quot;Authentication&quot;], (CFDictionaryRef)[credentials objectForKey:@&quot;Credentials&quot;], NULL)) {
-					[[self class] removeAuthenticationCredentialsFromSessionStore:[credentials objectForKey:@&quot;Credentials&quot;]];
-				}
+			credentials = [self findSessionAuthenticationCredentials];
+		}
+		
+		
+		// Do we have credentials that might be for basic authentication set?
+		if ([self username] &amp;&amp; [self password] &amp;&amp; ![self domain]) {
+			
+			// If we have stored credentials, is this server asking for basic authentication? If we don't have credentials, we'll assume basic
+			if (!credentials || (CFStringRef)[credentials objectForKey:@&quot;AuthenticationScheme&quot;] == kCFHTTPAuthenticationSchemeBasic) {
+				[self addRequestHeader:@&quot;Authorisation&quot; value:[ASIHTTPRequest base64forData:[[NSString stringWithFormat:@&quot;%@:%@&quot;,[self username],[self password]] dataUsingEncoding:NSUTF8StringEncoding]]];
 			}
+		}
+		
+		if (credentials &amp;&amp; ![[self requestHeaders] objectForKey:@&quot;Authorisation&quot;]) {
+			// If we've already talked to this server and have valid credentials, let's apply them to the request
+			if (!CFHTTPMessageApplyCredentialDictionary(request, (CFHTTPAuthenticationRef)[credentials objectForKey:@&quot;Authentication&quot;], (CFDictionaryRef)[credentials objectForKey:@&quot;Credentials&quot;], NULL)) {
+				[[self class] removeAuthenticationCredentialsFromSessionStore:[credentials objectForKey:@&quot;Credentials&quot;]];
+			}
+		}
+		if ([self useSessionPersistance]) {
 			credentials = [self findSessionProxyAuthenticationCredentials];
 			if (credentials) {
 				if (!CFHTTPMessageApplyCredentialDictionary(request, (CFHTTPAuthenticationRef)[credentials objectForKey:@&quot;Authentication&quot;], (CFDictionaryRef)[credentials objectForKey:@&quot;Credentials&quot;], NULL)) {
@@ -2893,11 +2907,47 @@ static BOOL isiPhoneOS2;
 	return toRead;
 }
 
+#pragma mark miscellany 
+
 + (BOOL)isiPhoneOS2
 {
+	// Value is set in +initialize
 	return isiPhoneOS2;
 }
 
+// From: http://www.cocoadev.com/index.pl?BaseSixtyFour
+
++ (NSString*)base64forData:(NSData*)theData {
+	
+	const uint8_t* input = (const uint8_t*)[theData bytes];
+	NSInteger length = [theData length];
+	
+    static char table[] = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=&quot;;
+	
+    NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
+    uint8_t* output = (uint8_t*)data.mutableBytes;
+	
+    for (NSInteger i = 0; i &lt; length; i += 3) {
+        NSInteger value = 0;
+        for (NSInteger j = i; j &lt; (i + 3); j++) {
+            value &lt;&lt;= 8;
+			
+            if (j &lt; length) {
+                value |= (0xFF &amp; input[j]);
+            }
+        }
+		
+        NSInteger index = (i / 3) * 4;
+        output[index + 0] =                    table[(value &gt;&gt; 18) &amp; 0x3F];
+        output[index + 1] =                    table[(value &gt;&gt; 12) &amp; 0x3F];
+        output[index + 2] = (i + 1) &lt; length ? table[(value &gt;&gt; 6)  &amp; 0x3F] : '=';
+        output[index + 3] = (i + 2) &lt; length ? table[(value &gt;&gt; 0)  &amp; 0x3F] : '=';
+    }
+	
+    return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
+}
+
+#pragma mark ===
 
 @synthesize username;
 @synthesize password;</diff>
      <filename>Classes/ASIHTTPRequest.m</filename>
    </modified>
    <modified>
      <diff>@@ -20,7 +20,7 @@ static NSString *sharedSecretAccessKey = nil;
 @interface ASIS3Request ()
 	- (void)parseError;
 	+ (NSData *)HMACSHA1withKey:(NSString *)key forString:(NSString *)string;
-	+ (NSString *)base64forData:(NSData *)theData;
+	
 	@property (retain, nonatomic) NSString *currentErrorString;
 @end
 
@@ -138,7 +138,7 @@ static NSString *sharedSecretAccessKey = nil;
 	} else {
 		stringToSign = [NSString stringWithFormat:@&quot;%@\n\n\n%@\n%@%@&quot;,[self requestMethod],dateString,canonicalizedAmzHeaders,canonicalizedResource];
 	}
-	NSString *signature = [ASIS3Request base64forData:[ASIS3Request HMACSHA1withKey:[self secretAccessKey] forString:stringToSign]];
+	NSString *signature = [ASIHTTPRequest base64forData:[ASIS3Request HMACSHA1withKey:[self secretAccessKey] forString:stringToSign]];
 	NSString *authorizationString = [NSString stringWithFormat:@&quot;AWS %@:%@&quot;,[self accessKey],signature];
 	[self addRequestHeader:@&quot;Authorization&quot; value:authorizationString];
 }
@@ -244,40 +244,6 @@ static NSString *sharedSecretAccessKey = nil;
 	return [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
 }
 
-
-// From: http://www.cocoadev.com/index.pl?BaseSixtyFour
-
-+ (NSString*)base64forData:(NSData*)theData {
-	
-	const uint8_t* input = (const uint8_t*)[theData bytes];
-	NSInteger length = [theData length];
-	
-    static char table[] = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=&quot;;
-	
-    NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
-    uint8_t* output = (uint8_t*)data.mutableBytes;
-	
-    for (NSInteger i = 0; i &lt; length; i += 3) {
-        NSInteger value = 0;
-        for (NSInteger j = i; j &lt; (i + 3); j++) {
-            value &lt;&lt;= 8;
-			
-            if (j &lt; length) {
-                value |= (0xFF &amp; input[j]);
-            }
-        }
-		
-        NSInteger index = (i / 3) * 4;
-        output[index + 0] =                    table[(value &gt;&gt; 18) &amp; 0x3F];
-        output[index + 1] =                    table[(value &gt;&gt; 12) &amp; 0x3F];
-        output[index + 2] = (i + 1) &lt; length ? table[(value &gt;&gt; 6)  &amp; 0x3F] : '=';
-        output[index + 3] = (i + 2) &lt; length ? table[(value &gt;&gt; 0)  &amp; 0x3F] : '=';
-    }
-	
-    return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
-}
-
-
 @synthesize bucket;
 @synthesize path;
 @synthesize dateString;</diff>
      <filename>Classes/ASIS3Request.m</filename>
    </modified>
    <modified>
      <diff>@@ -557,6 +557,7 @@
 
 - (void)testDigestAuthentication
 {
+	[ASIHTTPRequest removeCredentialsForHost:@&quot;allseeing-i.com&quot; port:0 protocol:@&quot;http&quot; realm:@&quot;Keep out&quot;];
 	[ASIHTTPRequest clearSession];
 	
 	NSURL *url = [[[NSURL alloc] initWithString:@&quot;http://allseeing-i.com/ASIHTTPRequest/tests/digest-authentication&quot;] autorelease];
@@ -564,12 +565,14 @@
 	BOOL success;
 	NSError *err;
 	
+	// Test authentication needed when no credentials supplied
 	request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
 	[request setUseKeychainPersistance:NO];
 	[request start];
 	success = [[request error] code] == ASIAuthenticationErrorType;
 	GHAssertTrue(success,@&quot;Failed to generate permission denied error with no credentials&quot;);
 	
+	// Test wrong credentials supplied
 	request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
 	[request setUseKeychainPersistance:NO];
 	[request setUsername:@&quot;wrong&quot;];
@@ -578,6 +581,7 @@
 	success = [[request error] code] == ASIAuthenticationErrorType;
 	GHAssertTrue(success,@&quot;Failed to generate permission denied error with wrong credentials&quot;);
 	
+	// Test correct credentials supplied
 	request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
 	[request setUseSessionPersistance:YES];
 	[request setUseKeychainPersistance:YES];
@@ -587,6 +591,7 @@
 	err = [request error];
 	GHAssertNil(err,@&quot;Failed to supply correct username and password&quot;);
 	
+	// Ensure credentials are not reused
 	request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
 	[request setUseSessionPersistance:NO];
 	[request setUseKeychainPersistance:NO];
@@ -594,6 +599,7 @@
 	success = [[request error] code] == ASIAuthenticationErrorType;
 	GHAssertTrue(success,@&quot;Reused credentials when we shouldn't have&quot;);
 	
+	// Ensure credentials stored in the session are reused
 	request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
 	[request setUseSessionPersistance:YES];
 	[request setUseKeychainPersistance:NO];
@@ -603,11 +609,28 @@
 	
 	[ASIHTTPRequest clearSession];
 	
+	// Ensure credentials stored in the session were wiped
 	request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
 	[request setUseKeychainPersistance:NO];
 	[request start];
 	success = [[request error] code] == ASIAuthenticationErrorType;
 	GHAssertTrue(success,@&quot;Failed to clear credentials&quot;);
+	
+	// Ensure credentials stored in the keychain are reused
+	request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+	[request setUseKeychainPersistance:YES];
+	[request start];
+	err = [request error];
+	GHAssertNil(err,@&quot;Failed to reuse credentials&quot;);
+	
+	[ASIHTTPRequest removeCredentialsForHost:@&quot;allseeing-i.com&quot; port:80 protocol:@&quot;http&quot; realm:@&quot;Keep out&quot;];
+	
+	// Ensure credentials stored in the keychain were wiped
+	request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
+	[request setUseKeychainPersistance:YES];
+	[request start];
+	success = [[request error] code] == ASIAuthenticationErrorType;
+	GHAssertTrue(success,@&quot;Failed to clear credentials&quot;);	
 }
 
 - (void)testNTLMHandshake</diff>
      <filename>Classes/Tests/ASIHTTPRequestTests.m</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>2e918451a5bc6fba0d84a8942a07cf8a3c46a5b6</id>
    </parent>
  </parents>
  <author>
    <name>Ben Copsey</name>
    <email>ben@allseeing-i.com</email>
  </author>
  <url>http://github.com/pokeb/asi-http-request/commit/4dd54fbe91a82ed58e31adaec3fcbe4213a9c6be</url>
  <id>4dd54fbe91a82ed58e31adaec3fcbe4213a9c6be</id>
  <committed-date>2009-10-14T05:57:45-07:00</committed-date>
  <authored-date>2009-10-14T05:57:45-07:00</authored-date>
  <message>Start work on generating basic authentication Authorization header (needs tests)</message>
  <tree>2ede11a698fd1a99dad5e6cf593b91f5e567c0fa</tree>
  <committer>
    <name>Ben Copsey</name>
    <email>ben@allseeing-i.com</email>
  </committer>
</commit>
