Ben Copsey

Remove duplication with calling the delegate for authentication details

@@ -51,36 +51,41 @@ static NSError *ASITooMuchRedirectionError; @@ -51,36 +51,41 @@ static NSError *ASITooMuchRedirectionError;
51 51
52 // Private stuff 52 // Private stuff
53 @interface ASIHTTPRequest () 53 @interface ASIHTTPRequest ()
54 - @property (assign) BOOL complete; 54 +
55 - @property (retain) NSDictionary *responseHeaders; 55 +- (BOOL)askDelegateForCredentials;
56 - @property (retain) NSArray *responseCookies; 56 +- (BOOL)askDelegateForProxyCredentials;
57 - @property (assign) int responseStatusCode; 57 +
58 - @property (retain) NSMutableData *rawResponseData; 58 +@property (assign) BOOL complete;
59 - @property (retain, nonatomic) NSDate *lastActivityTime; 59 +@property (retain) NSDictionary *responseHeaders;
60 - @property (assign) unsigned long long contentLength; 60 +@property (retain) NSArray *responseCookies;
61 - @property (assign) unsigned long long partialDownloadSize; 61 +@property (assign) int responseStatusCode;
62 - @property (assign, nonatomic) unsigned long long uploadBufferSize; 62 +@property (retain) NSMutableData *rawResponseData;
63 - @property (assign) NSStringEncoding responseEncoding; 63 +@property (retain, nonatomic) NSDate *lastActivityTime;
64 - @property (retain, nonatomic) NSOutputStream *postBodyWriteStream; 64 +@property (assign) unsigned long long contentLength;
65 - @property (retain, nonatomic) NSInputStream *postBodyReadStream; 65 +@property (assign) unsigned long long partialDownloadSize;
66 - @property (assign) unsigned long long totalBytesRead; 66 +@property (assign, nonatomic) unsigned long long uploadBufferSize;
67 - @property (assign) unsigned long long totalBytesSent; 67 +@property (assign) NSStringEncoding responseEncoding;
68 - @property (assign, nonatomic) unsigned long long lastBytesRead; 68 +@property (retain, nonatomic) NSOutputStream *postBodyWriteStream;
69 - @property (assign, nonatomic) unsigned long long lastBytesSent; 69 +@property (retain, nonatomic) NSInputStream *postBodyReadStream;
70 - @property (retain) NSLock *cancelledLock; 70 +@property (assign) unsigned long long totalBytesRead;
71 - @property (assign, nonatomic) BOOL haveBuiltPostBody; 71 +@property (assign) unsigned long long totalBytesSent;
72 - @property (retain, nonatomic) NSOutputStream *fileDownloadOutputStream; 72 +@property (assign, nonatomic) unsigned long long lastBytesRead;
73 - @property (assign, nonatomic) int authenticationRetryCount; 73 +@property (assign, nonatomic) unsigned long long lastBytesSent;
74 - @property (assign, nonatomic) int proxyAuthenticationRetryCount; 74 +@property (retain) NSLock *cancelledLock;
75 - @property (assign, nonatomic) BOOL needsProxyAuthentication; 75 +@property (assign, nonatomic) BOOL haveBuiltPostBody;
76 - @property (assign, nonatomic) BOOL updatedProgress; 76 +@property (retain, nonatomic) NSOutputStream *fileDownloadOutputStream;
77 - @property (assign, nonatomic) BOOL needsRedirect; 77 +@property (assign, nonatomic) int authenticationRetryCount;
78 - @property (assign, nonatomic) int redirectCount; 78 +@property (assign, nonatomic) int proxyAuthenticationRetryCount;
79 - @property (retain, nonatomic) NSData *compressedPostBody; 79 +@property (assign, nonatomic) BOOL needsProxyAuthentication;
80 - @property (retain, nonatomic) NSString *compressedPostBodyFilePath; 80 +@property (assign, nonatomic) BOOL updatedProgress;
81 - @property (retain) NSConditionLock *authenticationLock; 81 +@property (assign, nonatomic) BOOL needsRedirect;
82 - @property (retain) NSString *authenticationRealm; 82 +@property (assign, nonatomic) int redirectCount;
83 - @property (retain) NSString *proxyAuthenticationRealm; 83 +@property (retain, nonatomic) NSData *compressedPostBody;
  84 +@property (retain, nonatomic) NSString *compressedPostBodyFilePath;
  85 +@property (retain) NSConditionLock *authenticationLock;
  86 +@property (retain) NSString *authenticationRealm;
  87 +@property (retain) NSString *proxyAuthenticationRealm;
  88 +
84 @end 89 @end
85 90
86 @implementation ASIHTTPRequest 91 @implementation ASIHTTPRequest
@@ -1335,6 +1340,25 @@ static NSError *ASITooMuchRedirectionError; @@ -1335,6 +1340,25 @@ static NSError *ASITooMuchRedirectionError;
1335 [[self authenticationLock] unlockWithCondition:2]; 1340 [[self authenticationLock] unlockWithCondition:2];
1336 } 1341 }
1337 1342
  1343 +- (BOOL)askDelegateForProxyCredentials
  1344 +{
  1345 + // If we have a delegate, we'll see if it can handle proxyAuthorizationNeededForRequest:.
  1346 + // Otherwise, we'll try the queue (if this request is part of one) and it will pass the message on to its own delegate
  1347 + id authorizationDelegate = [self delegate];
  1348 + if (!authorizationDelegate) {
  1349 + authorizationDelegate = [self queue];
  1350 + }
  1351 +
  1352 + if ([authorizationDelegate respondsToSelector:@selector(proxyAuthorizationNeededForRequest:)]) {
  1353 + [authorizationDelegate performSelectorOnMainThread:@selector(proxyAuthorizationNeededForRequest:) withObject:self waitUntilDone:[NSThread isMainThread]];
  1354 + [[self authenticationLock] lockWhenCondition:2];
  1355 + [[self authenticationLock] unlockWithCondition:1];
  1356 +
  1357 + return YES;
  1358 + }
  1359 + return NO;
  1360 +}
  1361 +
1338 - (void)attemptToApplyProxyCredentialsAndResume 1362 - (void)attemptToApplyProxyCredentialsAndResume
1339 { 1363 {
1340 1364
@@ -1346,7 +1370,7 @@ static NSError *ASITooMuchRedirectionError; @@ -1346,7 +1370,7 @@ static NSError *ASITooMuchRedirectionError;
1346 proxyAuthenticationMethod = (NSString *)CFHTTPAuthenticationCopyMethod(proxyAuthentication); 1370 proxyAuthenticationMethod = (NSString *)CFHTTPAuthenticationCopyMethod(proxyAuthentication);
1347 } 1371 }
1348 1372
1349 - 1373 + // If we haven't got a CFHTTPAuthenticationRef by now, something is badly wrong, so we'll have to give up
1350 if (!proxyAuthentication) { 1374 if (!proxyAuthentication) {
1351 [self cancelLoad]; 1375 [self cancelLoad];
1352 [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Failed to get authentication object from response headers",NSLocalizedDescriptionKey,nil]]]; 1376 [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Failed to get authentication object from response headers",NSLocalizedDescriptionKey,nil]]];
@@ -1364,22 +1388,8 @@ static NSError *ASITooMuchRedirectionError; @@ -1364,22 +1388,8 @@ static NSError *ASITooMuchRedirectionError;
1364 if (err.domain == kCFStreamErrorDomainHTTP && (err.error == kCFStreamErrorHTTPAuthenticationBadUserName || err.error == kCFStreamErrorHTTPAuthenticationBadPassword)) { 1388 if (err.domain == kCFStreamErrorDomainHTTP && (err.error == kCFStreamErrorHTTPAuthenticationBadUserName || err.error == kCFStreamErrorHTTPAuthenticationBadPassword)) {
1365 1389
1366 [self setProxyCredentials:nil]; 1390 [self setProxyCredentials:nil];
1367 -  
1368 [self setLastActivityTime:nil]; 1391 [self setLastActivityTime:nil];
1369 - 1392 + if ([self askDelegateForProxyCredentials]) {
1370 - // If we have a delegate, we'll see if it can handle authorizationNeededForRequest.  
1371 - // Otherwise, we'll try the queue (if this request is part of one) and it will pass the message on to its own delegate  
1372 - id authorizationDelegate = [self delegate];  
1373 - if (!authorizationDelegate) {  
1374 - authorizationDelegate = [self queue];  
1375 - }  
1376 -  
1377 - if ([authorizationDelegate respondsToSelector:@selector(proxyAuthorizationNeededForRequest:)]) {  
1378 - [authorizationDelegate performSelectorOnMainThread:@selector(proxyAuthorizationNeededForRequest:) withObject:self waitUntilDone:[NSThread isMainThread]];  
1379 - [[self authenticationLock] lockWhenCondition:2];  
1380 - [[self authenticationLock] unlockWithCondition:1];  
1381 -  
1382 - // Hopefully, the delegate gave us some credentials, let's apply them and reload  
1383 [self attemptToApplyProxyCredentialsAndResume]; 1393 [self attemptToApplyProxyCredentialsAndResume];
1384 return; 1394 return;
1385 } 1395 }
@@ -1393,18 +1403,20 @@ static NSError *ASITooMuchRedirectionError; @@ -1393,18 +1403,20 @@ static NSError *ASITooMuchRedirectionError;
1393 1403
1394 if (proxyCredentials) { 1404 if (proxyCredentials) {
1395 1405
  1406 + // We use startRequest rather than starting all over again in load request because NTLM requires we reuse the request
1396 if (((proxyAuthenticationMethod != (NSString *)kCFHTTPAuthenticationSchemeNTLM) || proxyAuthenticationRetryCount < 2) && [self applyCredentials:proxyCredentials]) { 1407 if (((proxyAuthenticationMethod != (NSString *)kCFHTTPAuthenticationSchemeNTLM) || proxyAuthenticationRetryCount < 2) && [self applyCredentials:proxyCredentials]) {
1397 [self startRequest]; 1408 [self startRequest];
1398 1409
1399 - // We've failed NTLM authentication twice, we should assume our credentials are wrong 1410 + // We've failed NTLM authentication twice, we should assume our credentials are wrong
1400 } else if (proxyAuthenticationMethod == (NSString *)kCFHTTPAuthenticationSchemeNTLM && proxyAuthenticationRetryCount == 2) { 1411 } else if (proxyAuthenticationMethod == (NSString *)kCFHTTPAuthenticationSchemeNTLM && proxyAuthenticationRetryCount == 2) {
1401 [self failWithError:ASIAuthenticationError]; 1412 [self failWithError:ASIAuthenticationError];
1402 1413
  1414 + // Something went wrong, we'll have to give up
1403 } else { 1415 } else {
1404 [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Failed to apply proxy credentials to request",NSLocalizedDescriptionKey,nil]]]; 1416 [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Failed to apply proxy credentials to request",NSLocalizedDescriptionKey,nil]]];
1405 } 1417 }
1406 1418
1407 - // Are a user name & password needed? 1419 + // Are a user name & password needed?
1408 } else if (CFHTTPAuthenticationRequiresUserNameAndPassword(proxyAuthentication)) { 1420 } else if (CFHTTPAuthenticationRequiresUserNameAndPassword(proxyAuthentication)) {
1409 1421
1410 NSMutableDictionary *newCredentials = [self findProxyCredentials]; 1422 NSMutableDictionary *newCredentials = [self findProxyCredentials];
@@ -1420,18 +1432,7 @@ static NSError *ASITooMuchRedirectionError; @@ -1420,18 +1432,7 @@ static NSError *ASITooMuchRedirectionError;
1420 return; 1432 return;
1421 } 1433 }
1422 1434
1423 - // We've got no credentials, let's ask the delegate to sort this out 1435 + if ([self askDelegateForProxyCredentials]) {
1424 - // If we have a delegate, we'll see if it can handle authorizationNeededForRequest.  
1425 - // Otherwise, we'll try the queue (if this request is part of one) and it will pass the message on to its own delegate  
1426 - id authorizationDelegate = [self delegate];  
1427 - if (!authorizationDelegate) {  
1428 - authorizationDelegate = [self queue];  
1429 - }  
1430 -  
1431 - if ([authorizationDelegate respondsToSelector:@selector(proxyAuthorizationNeededForRequest:)]) {  
1432 - [authorizationDelegate performSelectorOnMainThread:@selector(proxyAuthorizationNeededForRequest:) withObject:self waitUntilDone:[NSThread isMainThread]];  
1433 - [[self authenticationLock] lockWhenCondition:2];  
1434 - [[self authenticationLock] unlockWithCondition:1];  
1435 [self attemptToApplyProxyCredentialsAndResume]; 1436 [self attemptToApplyProxyCredentialsAndResume];
1436 return; 1437 return;
1437 } 1438 }
@@ -1443,6 +1444,25 @@ static NSError *ASITooMuchRedirectionError; @@ -1443,6 +1444,25 @@ static NSError *ASITooMuchRedirectionError;
1443 1444
1444 } 1445 }
1445 1446
  1447 +- (BOOL)askDelegateForCredentials
  1448 +{
  1449 + // If we have a delegate, we'll see if it can handle proxyAuthorizationNeededForRequest:.
  1450 + // Otherwise, we'll try the queue (if this request is part of one) and it will pass the message on to its own delegate
  1451 + id authorizationDelegate = [self delegate];
  1452 + if (!authorizationDelegate) {
  1453 + authorizationDelegate = [self queue];
  1454 + }
  1455 +
  1456 + if ([authorizationDelegate respondsToSelector:@selector(authorizationNeededForRequest:)]) {
  1457 + [authorizationDelegate performSelectorOnMainThread:@selector(authorizationNeededForRequest:) withObject:self waitUntilDone:[NSThread isMainThread]];
  1458 + [[self authenticationLock] lockWhenCondition:2];
  1459 + [[self authenticationLock] unlockWithCondition:1];
  1460 +
  1461 + return YES;
  1462 + }
  1463 + return NO;
  1464 +}
  1465 +
1446 - (void)attemptToApplyCredentialsAndResume 1466 - (void)attemptToApplyCredentialsAndResume
1447 { 1467 {
1448 if ([self needsProxyAuthentication]) { 1468 if ([self needsProxyAuthentication]) {
@@ -1458,7 +1478,6 @@ static NSError *ASITooMuchRedirectionError; @@ -1458,7 +1478,6 @@ static NSError *ASITooMuchRedirectionError;
1458 authenticationMethod = (NSString *)CFHTTPAuthenticationCopyMethod(requestAuthentication); 1478 authenticationMethod = (NSString *)CFHTTPAuthenticationCopyMethod(requestAuthentication);
1459 } 1479 }
1460 1480
1461 -  
1462 if (!requestAuthentication) { 1481 if (!requestAuthentication) {
1463 [self cancelLoad]; 1482 [self cancelLoad];
1464 [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Failed to get authentication object from response headers",NSLocalizedDescriptionKey,nil]]]; 1483 [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileApplyingCredentialsType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Failed to get authentication object from response headers",NSLocalizedDescriptionKey,nil]]];
@@ -1479,24 +1498,11 @@ static NSError *ASITooMuchRedirectionError; @@ -1479,24 +1498,11 @@ static NSError *ASITooMuchRedirectionError;
1479 1498
1480 [self setLastActivityTime:nil]; 1499 [self setLastActivityTime:nil];
1481 1500
1482 - // If we have a delegate, we'll see if it can handle authorizationNeededForRequest. 1501 + if ([self askDelegateForCredentials]) {
1483 - // Otherwise, we'll try the queue (if this request is part of one) and it will pass the message on to its own delegate  
1484 - id authorizationDelegate = [self delegate];  
1485 - if (!authorizationDelegate) {  
1486 - authorizationDelegate = [self queue];  
1487 - }  
1488 -  
1489 - if ([authorizationDelegate respondsToSelector:@selector(authorizationNeededForRequest:)]) {  
1490 - [authorizationDelegate performSelectorOnMainThread:@selector(authorizationNeededForRequest:) withObject:self waitUntilDone:[NSThread isMainThread]];  
1491 - [[self authenticationLock] lockWhenCondition:2];  
1492 - [[self authenticationLock] unlockWithCondition:1];  
1493 -  
1494 - // Hopefully, the delegate gave us some credentials, let's apply them and reload  
1495 [self attemptToApplyCredentialsAndResume]; 1502 [self attemptToApplyCredentialsAndResume];
1496 return; 1503 return;
1497 } 1504 }
1498 } 1505 }
1499 - // The delegate isn't interested, we'll have to give up  
1500 [self cancelLoad]; 1506 [self cancelLoad];
1501 [self failWithError:ASIAuthenticationError]; 1507 [self failWithError:ASIAuthenticationError];
1502 return; 1508 return;
@@ -1533,19 +1539,7 @@ static NSError *ASITooMuchRedirectionError; @@ -1533,19 +1539,7 @@ static NSError *ASITooMuchRedirectionError;
1533 return; 1539 return;
1534 } 1540 }
1535 1541
1536 - // We've got no credentials, let's ask the delegate to sort this out 1542 + if ([self askDelegateForCredentials]) {
1537 - // If we have a delegate, we'll see if it can handle authorizationNeededForRequest.  
1538 - // Otherwise, we'll try the queue (if this request is part of one) and it will pass the message on to its own delegate  
1539 - id authorizationDelegate = [self delegate];  
1540 - if (!authorizationDelegate) {  
1541 - authorizationDelegate = [self queue];  
1542 - }  
1543 -  
1544 - if ([authorizationDelegate respondsToSelector:@selector(authorizationNeededForRequest:)]) {  
1545 - [authorizationDelegate performSelectorOnMainThread:@selector(authorizationNeededForRequest:) withObject:self waitUntilDone:[NSThread isMainThread]];  
1546 -  
1547 - [[self authenticationLock] lockWhenCondition:2];  
1548 - [[self authenticationLock] unlockWithCondition:1];  
1549 [self attemptToApplyCredentialsAndResume]; 1543 [self attemptToApplyCredentialsAndResume];
1550 return; 1544 return;
1551 } 1545 }