Plugins/Displays/SMS/GrowlSMSDisplay.m
author Rudy Richter
Sat Aug 01 20:43:39 2009 -0400 (2009-08-01)
changeset 4259 0e9b6b0b1e25
parent 4246 4f52d1d98978
child 4666 59b81a267426
child 4819 2e39ce17d1ea
permissions -rw-r--r--
Plugins: clang warnings
boredzo@2402
     1
//
boredzo@2402
     2
//  GrowlSMSDisplay.m
boredzo@2402
     3
//  Growl Display Plugins
boredzo@2402
     4
//
boredzo@2402
     5
//  Created by Diggory Laycock
ingmarstein@3040
     6
//  Copyright 2005-2006 The Growl Project All rights reserved.
boredzo@2402
     7
//
boredzo@2402
     8
#import "GrowlSMSDisplay.h"
boredzo@2402
     9
#import "GrowlSMSPrefs.h"
boredzo@2402
    10
#import "NSStringAdditions.h"
boredzo@2402
    11
#import "GrowlDefinesInternal.h"
ingmarstein@2699
    12
#import "GrowlApplicationNotification.h"
ingmarstein@2695
    13
#include <Security/SecKeychain.h>
ingmarstein@2695
    14
#include <Security/SecKeychainItem.h>
boredzo@2402
    15
boredzo@2402
    16
#define keychainServiceName "GrowlSMS"
boredzo@2402
    17
#define keychainAccountName "SMSWebServicePassword"
boredzo@2402
    18
boredzo@2402
    19
#define GrowlSMSPrefDomain		@"com.Growl.SMS"
boredzo@2402
    20
#define accountNameKey			@"SMS - Account Name"
boredzo@2402
    21
#define accountAPIIDKey			@"SMS - Account API ID"
boredzo@2402
    22
#define destinationNumberKey	@"SMS - Destination Number"
boredzo@2402
    23
boredzo@2402
    24
boredzo@2402
    25
@implementation GrowlSMSDisplay
boredzo@2402
    26
boredzo@2402
    27
- (id) init {
boredzo@2402
    28
	if ((self = [super init])) {
boredzo@2402
    29
		commandQueue = [[NSMutableArray alloc] init];
boredzo@2402
    30
		xmlHoldingStringValue = [[NSMutableString alloc] init];
boredzo@2402
    31
		waitingForResponse = NO;
Rudy@4246
    32
		creditBalance = 0.0;
boredzo@2402
    33
	}
boredzo@2402
    34
	return self;
boredzo@2402
    35
}
boredzo@2402
    36
boredzo@2402
    37
- (void) dealloc {
boredzo@2402
    38
	[commandQueue release];
boredzo@2402
    39
ofri@2716
    40
	[preferencePane release];
boredzo@2402
    41
	[super dealloc];
boredzo@2402
    42
}
boredzo@2402
    43
boredzo@2402
    44
- (NSPreferencePane *) preferencePane {
ofri@2716
    45
	if (!preferencePane)
ofri@2716
    46
		preferencePane = [[GrowlSMSPrefs alloc] initWithBundle:[NSBundle bundleWithIdentifier:@"com.Growl.SMS"]];
ofri@2716
    47
	return preferencePane;
boredzo@2402
    48
}
boredzo@2402
    49
ingmarstein@2695
    50
- (void) displayNotification:(GrowlApplicationNotification *)notification {
boredzo@2402
    51
	NSString	*accountNameValue = nil;
boredzo@2402
    52
	NSString	*apiIDValue = nil;
boredzo@2402
    53
	NSString	*destinationNumberValue = nil;
boredzo@2402
    54
boredzo@2402
    55
	READ_GROWL_PREF_VALUE(destinationNumberKey, GrowlSMSPrefDomain, NSString *, &destinationNumberValue);
Rudy@4259
    56
	if(destinationNumberValue)
Rudy@4259
    57
		CFMakeCollectable(destinationNumberValue);
boredzo@4141
    58
	[destinationNumberValue autorelease];
boredzo@2402
    59
	READ_GROWL_PREF_VALUE(accountAPIIDKey, GrowlSMSPrefDomain, NSString *, &apiIDValue);
Rudy@4259
    60
	if(apiIDValue)
Rudy@4259
    61
		CFMakeCollectable(apiIDValue);
boredzo@4141
    62
	[apiIDValue autorelease];
boredzo@2402
    63
	READ_GROWL_PREF_VALUE(accountNameKey, GrowlSMSPrefDomain, NSString *, &accountNameValue);
Rudy@4259
    64
	if(accountNameValue)
Rudy@4259
    65
		CFMakeCollectable(accountNameValue);
boredzo@4141
    66
	[accountNameValue autorelease];
boredzo@2402
    67
boredzo@2402
    68
	if (!([destinationNumberValue length] && [apiIDValue length] && [accountNameValue length])) {
diggory@4143
    69
		NSLog(@"SMS display: Cannot send SMS - not enough details in preferences.");
boredzo@2402
    70
		return;
boredzo@2402
    71
	}
boredzo@2402
    72
ingmarstein@2695
    73
	NSDictionary *noteDict = [notification dictionaryRepresentation];
boredzo@2402
    74
	NSString *title = [noteDict objectForKey:GROWL_NOTIFICATION_TITLE];
boredzo@2402
    75
	NSString *desc = [noteDict objectForKey:GROWL_NOTIFICATION_DESCRIPTION];
boredzo@2402
    76
ingmarstein@2699
    77
	//	Fetch the SMS password from the keychain
ingmarstein@2634
    78
	unsigned char *password;
boredzo@2402
    79
	UInt32 passwordLength;
boredzo@2402
    80
	OSStatus status;
ingmarstein@2634
    81
	status = SecKeychainFindGenericPassword(NULL,
Rudy@4246
    82
											(UInt32)strlen(keychainServiceName), keychainServiceName,
Rudy@4246
    83
											(UInt32)strlen(keychainAccountName), keychainAccountName,
ingmarstein@2634
    84
											&passwordLength, (void **)&password, NULL);
ingmarstein@2634
    85
ingmarstein@2634
    86
	CFStringRef passwordString;
boredzo@2402
    87
	if (status == noErr) {
ingmarstein@2634
    88
		passwordString = CFStringCreateWithBytes(kCFAllocatorDefault, password, passwordLength, kCFStringEncodingUTF8, false);
boredzo@2402
    89
		SecKeychainItemFreeContent(NULL, password);
boredzo@2402
    90
	} else {
boredzo@2402
    91
		if (status != errSecItemNotFound)
diggory@4143
    92
			NSLog(@"SMS display: Failed to retrieve SMS Account password from keychain. Error: %d", status);
ingmarstein@2634
    93
		passwordString = CFSTR("");
boredzo@2402
    94
	}
boredzo@2402
    95
boredzo@2402
    96
boredzo@2402
    97
	NSString *localHostName = [[NSHost currentHost] name];
boredzo@2402
    98
	NSString *smsSendCommand = [[NSString alloc] initWithFormat:
diggory@4143
    99
		@"<clickAPI><sendMsg><api_id>%@</api_id><user>%@</user><password>%@</password><to>+%@</to><text>(%@) %@ (Growl from %@)</text><from>Growl</from></sendMsg></clickAPI>",
boredzo@2402
   100
		apiIDValue,
boredzo@2402
   101
		accountNameValue,
boredzo@2402
   102
		passwordString,
boredzo@2402
   103
		destinationNumberValue,
boredzo@2402
   104
		title,
boredzo@2402
   105
		desc,
boredzo@2402
   106
		localHostName];
boredzo@2402
   107
diggory@4143
   108
//	NSLog(@"SMS Display...  %@" , smsSendCommand);
boredzo@2402
   109
	[self sendXMLCommand:smsSendCommand];
boredzo@2402
   110
	[smsSendCommand release];
boredzo@2402
   111
boredzo@2402
   112
	//	Check credit balance.
boredzo@2402
   113
	NSString *checkBalanceCommand = [[NSString alloc] initWithFormat:
boredzo@2402
   114
		@"<clickAPI><getBalance><api_id>%@</api_id><user>%@</user><password>%@</password></getBalance></clickAPI>",
boredzo@2402
   115
		apiIDValue,
boredzo@2402
   116
		accountNameValue,
boredzo@2402
   117
		passwordString];
boredzo@2402
   118
ingmarstein@2634
   119
	CFRelease(passwordString);
ingmarstein@2634
   120
boredzo@2402
   121
	[self sendXMLCommand:checkBalanceCommand];
boredzo@2402
   122
	[checkBalanceCommand release];
boredzo@2402
   123
boredzo@2402
   124
	id clickContext = [noteDict objectForKey:GROWL_NOTIFICATION_CLICK_CONTEXT];
boredzo@2402
   125
	if (clickContext) {
boredzo@2402
   126
		NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:
boredzo@2402
   127
			[noteDict objectForKey:@"ClickHandlerEnabled"], @"ClickHandlerEnabled",
boredzo@2402
   128
			clickContext,                                   GROWL_KEY_CLICKED_CONTEXT,
boredzo@2402
   129
			[noteDict objectForKey:GROWL_APP_PID],          GROWL_APP_PID,
boredzo@2402
   130
			nil];
boredzo@2402
   131
		[[NSNotificationCenter defaultCenter] postNotificationName:GROWL_NOTIFICATION_TIMED_OUT
ingmarstein@2699
   132
															object:[notification applicationName]
boredzo@2402
   133
														  userInfo:userInfo];
boredzo@2402
   134
		[userInfo release];
boredzo@2402
   135
	}
boredzo@2402
   136
boredzo@2402
   137
}
boredzo@2402
   138
boredzo@2402
   139
boredzo@2402
   140
#pragma mark -
boredzo@2402
   141
#pragma mark Accessors
boredzo@2402
   142
boredzo@2402
   143
- (NSData *) responseData {
boredzo@2402
   144
	return responseData;
boredzo@2402
   145
}
boredzo@2402
   146
boredzo@2402
   147
- (void) setResponseData:(NSData *)newResponseData {
boredzo@2402
   148
	[newResponseData retain];
boredzo@2402
   149
	[responseData release];
boredzo@2402
   150
	responseData = newResponseData;
boredzo@2402
   151
diggory@4143
   152
//	NSLog(@"SMS display: responseData:  %@", responseData);
boredzo@2402
   153
}
boredzo@2402
   154
boredzo@2402
   155
boredzo@2402
   156
#pragma mark -
boredzo@2402
   157
#pragma mark Instance Methods
boredzo@2402
   158
boredzo@2402
   159
boredzo@2402
   160
/*
boredzo@2402
   161
 <clickAPI>
boredzo@2402
   162
	 <sendMsg>
boredzo@2402
   163
		 <api_id>your_api_id</api_id>
boredzo@2402
   164
		 <user>your_user_name</user>
boredzo@2402
   165
		 <password>your_pass</password>
boredzo@2402
   166
		 <to>+12343455667</to>
boredzo@2402
   167
		 <text>Test text message.</text>
boredzo@2402
   168
		 <from>Growl</from>
boredzo@2402
   169
	 </sendMsg>
boredzo@2402
   170
 </clickAPI>
boredzo@2402
   171
boredzo@2402
   172
boredzo@2402
   173
 API URL:
boredzo@2402
   174
 ==========
boredzo@2402
   175
 https://api.clickatell.com/xml/xml
boredzo@2402
   176
 <input name="data" type="text" value="<clickAPI>$your_xml_data</clickAPI>">
boredzo@2402
   177
boredzo@2402
   178
 //	To do - use the unicode option - when needed - although, it halves the length of SMS we can send.
boredzo@2402
   179
boredzo@2402
   180
 */
boredzo@2402
   181
- (void) sendXMLCommand:(NSString *)commandString {
ingmarstein@2649
   182
	CFStringRef			dataString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("data=%@"), commandString);
ingmarstein@2649
   183
	CFDataRef			postData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, dataString, kCFStringEncodingUTF8, 0U);
ingmarstein@2649
   184
	CFURLRef			clickatellURL = CFURLCreateWithString(kCFAllocatorDefault, CFSTR("https://api.clickatell.com/xml/xml"), NULL);
ingmarstein@2649
   185
	NSMutableURLRequest	*post = [[NSMutableURLRequest alloc] initWithURL:(NSURL *)clickatellURL];
ingmarstein@2649
   186
	CFStringRef			contentLength = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"), CFDataGetLength(postData));
ingmarstein@2649
   187
diggory@4143
   188
//	NSLog(@"SMS display: Sending data: %@", postData);
ingmarstein@2649
   189
ingmarstein@2649
   190
	[post addValue:(NSString *)contentLength forHTTPHeaderField: @"Content-Length"];
boredzo@2402
   191
	[post setHTTPMethod:@"POST"];
ingmarstein@2649
   192
	[post setHTTPBody:(NSData *)postData];
boredzo@2402
   193
	[commandQueue addObject:post];
ingmarstein@2649
   194
	[post release];
ingmarstein@2649
   195
ingmarstein@2649
   196
	CFRelease(postData);
ingmarstein@2649
   197
	CFRelease(dataString);
ingmarstein@2649
   198
	CFRelease(clickatellURL);
ingmarstein@2649
   199
	CFRelease(contentLength);
boredzo@2402
   200
boredzo@2402
   201
	[self processQueue];
boredzo@2402
   202
}
boredzo@2402
   203
boredzo@2402
   204
boredzo@2402
   205
- (void) processQueue {
diggory@4143
   206
	// NSLog(@"SMS display: Processing HTTP Command Queue");
boredzo@2402
   207
	if (![commandQueue count]) {
diggory@4143
   208
		// NSLog(@"SMS display: Queue is empty...");
boredzo@2402
   209
		return;
boredzo@2402
   210
	}
boredzo@2402
   211
boredzo@2402
   212
	if (!waitingForResponse) {
boredzo@2402
   213
		waitingForResponse = YES;
diggory@4143
   214
//		NSLog(@"SMS display: Beginning Command Request Connection...");
boredzo@2402
   215
		[NSURLConnection connectionWithRequest:[commandQueue objectAtIndex:0U] delegate: self];
boredzo@2402
   216
	} else {
diggory@4143
   217
		NSLog(@"SMS display: Holding request in queue - we are still waiting for an existing command's resonse..");
boredzo@2402
   218
	}
boredzo@2402
   219
}
boredzo@2402
   220
boredzo@2402
   221
boredzo@2402
   222
- (void) connectionDidRespond {
diggory@4143
   223
//	NSLog(@"SMS display: Request/Response transaction complete...");
boredzo@2402
   224
	waitingForResponse = NO;
boredzo@2402
   225
	[commandQueue removeObjectAtIndex:0U];
boredzo@2402
   226
	[self processQueue];
boredzo@2402
   227
}
boredzo@2402
   228
boredzo@2402
   229
- (void) handleResponse {
boredzo@2402
   230
	if (responseParser)
boredzo@2402
   231
		[responseParser release];
boredzo@2402
   232
	responseParser = [[NSXMLParser alloc] initWithData:[self responseData]];
boredzo@2402
   233
	[responseParser setDelegate:self];
boredzo@2402
   234
	[responseParser setShouldResolveExternalEntities:YES];
boredzo@2402
   235
	[responseParser parse]; // return value not used
boredzo@2402
   236
							// if not successful, delegate is informed of error}
boredzo@2402
   237
}
boredzo@2402
   238
boredzo@2402
   239
boredzo@2402
   240
#pragma mark -
boredzo@2402
   241
#pragma mark NSXMLParser Delegate methods:
boredzo@2402
   242
boredzo@2402
   243
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
boredzo@2402
   244
#pragma unused(parser,namespaceURI,qName,attributeDict)
boredzo@2402
   245
	if ([elementName isEqualToString:@"clickAPI"]) {
diggory@4143
   246
//		NSLog(@"SMS display: Found the clickAPI element in the response.  That means we got the HTTP part right.");
boredzo@2402
   247
	} else if ([elementName isEqualToString:@"xmlErrorResp"]) {
diggory@4143
   248
		NSLog(@"SMS display: Oh Noes! we got an error back from clickatell - we passed them a bad XML request...");
boredzo@2402
   249
	} else if ([elementName isEqualToString:@"fault"]) {
diggory@4143
   250
		NSLog(@"SMS display: Here comes the fault:...");
boredzo@2402
   251
	} else if ([elementName isEqualToString:@"getBalanceResp"]) {
diggory@4143
   252
//		NSLog(@"SMS display: Here comes the Balance response:...");
boredzo@2402
   253
		inBalanceResponseElement = YES;
boredzo@2402
   254
	} else if ([elementName isEqualToString:@"ok"]) {
diggory@4143
   255
//		NSLog(@"SMS display: Command Success.");
boredzo@2402
   256
		if (inBalanceResponseElement) {
diggory@4143
   257
//			NSLog(@"SMS display: Here comes the Balance value:...");
boredzo@2402
   258
		}
boredzo@2402
   259
	} else if ([elementName isEqualToString:@"sendMsgResp"]) {
diggory@4143
   260
//		NSLog(@"SMS display: Here comes the Message Send response:...");
boredzo@2402
   261
		inMessageSendResponseElement = YES;
boredzo@2402
   262
	}
boredzo@2402
   263
}
boredzo@2402
   264
boredzo@2402
   265
boredzo@2402
   266
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
boredzo@2402
   267
#pragma unused(parser)
boredzo@2402
   268
	if (!xmlHoldingStringValue)
boredzo@2402
   269
		xmlHoldingStringValue = [[NSMutableString alloc] initWithCapacity:50];
boredzo@2402
   270
	[xmlHoldingStringValue appendString:string];
boredzo@2402
   271
}
boredzo@2402
   272
boredzo@2402
   273
boredzo@2402
   274
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
boredzo@2402
   275
#pragma unused(parser,namespaceURI,qName)
boredzo@2402
   276
	if (   [elementName isEqualToString:@"clickAPI"]
boredzo@2402
   277
		|| [elementName isEqualToString:@"xmlErrorResp"]) {
boredzo@2402
   278
		// nothing to do
boredzo@2402
   279
		return;
boredzo@2402
   280
	} else if ([elementName isEqualToString:@"getBalanceResp"]) {
boredzo@2402
   281
		inBalanceResponseElement = NO;
boredzo@2402
   282
		[xmlHoldingStringValue release];
boredzo@2402
   283
		xmlHoldingStringValue = nil;
boredzo@2402
   284
	} else if ([elementName isEqualToString:@"sendMsgResp"]) {
boredzo@2402
   285
		inMessageSendResponseElement = NO;
boredzo@2402
   286
		[xmlHoldingStringValue release];
boredzo@2402
   287
		xmlHoldingStringValue = nil;
boredzo@2402
   288
	} else if ([elementName isEqualToString:@"fault"]) {
diggory@4143
   289
		NSLog(@"SMS display: The fault was: %@" , [xmlHoldingStringValue stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]] );
boredzo@2402
   290
		[xmlHoldingStringValue release];
boredzo@2402
   291
		xmlHoldingStringValue = nil;
boredzo@2402
   292
	} else if ([elementName isEqualToString:@"ok"]) {
boredzo@2402
   293
		if (inBalanceResponseElement) {
boredzo@2402
   294
			creditBalance = [[xmlHoldingStringValue stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]] floatValue];
diggory@4143
   295
			NSLog(@"SMS display: Your Balance is: %4.1f 'credits'" , creditBalance);
boredzo@2402
   296
			[xmlHoldingStringValue release];
boredzo@2402
   297
			xmlHoldingStringValue = nil;
boredzo@2402
   298
		}
boredzo@2402
   299
	} else if ([elementName isEqualToString:@"apiMsgId"]) {
boredzo@2402
   300
		if (inMessageSendResponseElement) {
diggory@4143
   301
			NSLog(@"SMS display: Your SMS Message has been sent by Clickatell (messageId: %@)" , [xmlHoldingStringValue stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]);
diggory@4143
   302
			[xmlHoldingStringValue release];
diggory@4143
   303
			xmlHoldingStringValue = nil;
diggory@4143
   304
		}
diggory@4143
   305
	} else if ([elementName isEqualToString:@"sequence_no"]) {
diggory@4143
   306
		if (inMessageSendResponseElement) {
diggory@4143
   307
//			NSLog(@"SMS display: sequence_no: %@" , [xmlHoldingStringValue stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]);
boredzo@2402
   308
			[xmlHoldingStringValue release];
boredzo@2402
   309
			xmlHoldingStringValue = nil;
boredzo@2402
   310
		}
boredzo@2402
   311
	} else {
boredzo@2402
   312
		NSLog(@"SMS display: unknown XML element: %@", elementName);
boredzo@2402
   313
	}
boredzo@2402
   314
}
boredzo@2402
   315
boredzo@2402
   316
- (void) parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
diggory@4143
   317
	NSLog(@"SMS display: Error Parsing XML response from SMS Gateway - %i, Description: %@, Line: %i, Column: %i",	[parseError code],
boredzo@2402
   318
		  [[parser parserError] localizedDescription],
boredzo@2402
   319
		  [parser lineNumber],
boredzo@2402
   320
		  [parser columnNumber]);
boredzo@2402
   321
}
boredzo@2402
   322
boredzo@2402
   323
boredzo@2402
   324
#pragma mark -
boredzo@2402
   325
#pragma mark NSURLConnection Delegate methods:
boredzo@2402
   326
boredzo@2402
   327
boredzo@2402
   328
/*
boredzo@2402
   329
	The delegate receives this message if connection has cancelled the authentication challenge specified by challenge.
boredzo@2402
   330
 */
boredzo@2402
   331
- (void) connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
boredzo@2402
   332
#pragma unused(connection,challenge)
diggory@4143
   333
	NSLog(@"SMS display: didCancelAuthenticationChallenge:");
boredzo@2402
   334
	[self connectionDidRespond];
boredzo@2402
   335
}
boredzo@2402
   336
boredzo@2402
   337
boredzo@2402
   338
/*
boredzo@2402
   339
	The delegate receives this message if connection has failed to load the request successfully. The details of the failure are specified in error.
boredzo@2402
   340
	Once the delegate receives this message, it will receive no further messages for connection.
boredzo@2402
   341
 */
boredzo@2402
   342
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
boredzo@2402
   343
#pragma unused(connection)
diggory@4143
   344
	NSLog(@"SMS display: Connection to SMS Web API failed: (%@)", [error localizedDescription]);
boredzo@2402
   345
boredzo@2402
   346
	[self connectionDidRespond];
boredzo@2402
   347
}
boredzo@2402
   348
boredzo@2402
   349
boredzo@2402
   350
/*
boredzo@2402
   351
 The delegate receives this message when connection must authenticate challenge in order to download the request. This method gives the delegate the opportunity to determine the course of action taken for the challenge: provide credentials, continue without providing credentials or cancel the authentication challenge and the download.
boredzo@2402
   352
 The delegate can determine the number of previous authentication challenges by sending the message previousFailureCount to challenge.
boredzo@2402
   353
boredzo@2402
   354
 If the previous failure count is 0 and the value returned by proposedCredential is nil, the delegate can create a new NSURLCredential object, providing a user name and password, and send a useCredential:forAuthenticationChallenge: message to [challenge sender], passing the credential and challenge as parameters. If proposedCredential is not nil, the value is a credential from the URL or the shared credential storage that can be provided to the user as feedback.
boredzo@2402
   355
 The delegate may decide to abandon further attempts at authentication at any time by sending [challenge sender] a continueWithoutCredentialForAuthenticationChallenge: or a cancelAuthenticationChallenge: message. The specific action will be implementation dependent.
boredzo@2402
   356
boredzo@2402
   357
 If the delegate implements this method, the download will suspend until [challenge sender] is sent one of the following messages: useCredential:forAuthenticationChallenge:, continueWithoutCredentialForAuthenticationChallenge: or cancelAuthenticationChallenge:.
boredzo@2402
   358
 If the delegate does not implement this method the default implementation is used. If a valid credential for the request is provided as part of the URL, or is available from the NSURLCredentialStorage the [challenge sender] is sent a useCredential:forAuthenticationChallenge: with the credential. If the challenge has no credential or the credentials fail to authorize access, then continueWithoutCredentialForAuthenticationChallenge: is sent to [challenge sender] instead.
boredzo@2402
   359
evands@3706
   360
 See Also: – cancelAuthenticationChallenge:, – continueWithoutCredentialForAuthenticationChallenge:, – useCredential:forAuthenticationChallenge:
boredzo@2402
   361
 */
boredzo@2402
   362
- (void) connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
diggory@4143
   363
	NSLog(@"SMS display: didReceiveAuthenticationChallenge: %@", challenge);
boredzo@2402
   364
	//	It doesn't need web auth currently - so we're not going to handle this case.
boredzo@2402
   365
	[connection cancel];
boredzo@2402
   366
	//	[self connectionDidRespond];
boredzo@2402
   367
}
boredzo@2402
   368
boredzo@2402
   369
boredzo@2402
   370
/*
boredzo@2402
   371
	The delegate receives this message as connection loads data incrementally. The delegate should concatenate the contents of each data object delivered to build up the complete data for a URL load.
boredzo@2402
   372
	This method provides the only way for an asynchronous delegate to retrieve the loaded data. It is the responsibility of the delegate to retain or copy this data as it is delivered.
boredzo@2402
   373
 */
boredzo@2402
   374
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
boredzo@2402
   375
#pragma unused(connection)
diggory@4143
   376
	//	NSLog(@"SMS display: didReceiveData:  %@", data);
boredzo@2402
   377
	[self setResponseData: data];
boredzo@2402
   378
	[self handleResponse];
boredzo@2402
   379
}
boredzo@2402
   380
boredzo@2402
   381
boredzo@2402
   382
/*
boredzo@2402
   383
	The delegate receives this message when the URL loading system has received sufficient load data for connection to construct the NSURLResponse object, response.
boredzo@2402
   384
 The response is immutable and will not be modified by the URL loading system once it is presented to the delegate.
boredzo@2402
   385
boredzo@2402
   386
 In rare cases, for example in the case of a HTTP load where the content type of the load data is multipart/x-mixed-replace, the delegate will receive more than one connection:didReceiveResponse: message.
boredzo@2402
   387
 In the event this occurs, delegates should discard all data previously delivered by connection:didReceiveData:, and should be prepared to handle the, potentially different, MIME type reported by the NSURLResponse.
boredzo@2402
   388
boredzo@2402
   389
 Note that the only case where this message is not sent to the delegate is when the protocol implementation encounters an error before a response could be created.
boredzo@2402
   390
boredzo@2402
   391
 */
boredzo@2402
   392
boredzo@2402
   393
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
boredzo@2402
   394
#pragma unused(connection,response)
diggory@4143
   395
//	NSLog(@"SMS display: didReceiveResponse:  URL(%@) expectedDataLength:(%d)", [response URL], [response expectedContentLength]  );
boredzo@2402
   396
boredzo@2402
   397
//	NSLog(@" MIME:(%@)" , [response MIMEType]);
boredzo@2402
   398
//	NSLog(@" textEncoding:(%@)" , [response textEncodingName]);
boredzo@2402
   399
}
boredzo@2402
   400
boredzo@2402
   401
boredzo@2402
   402
- (NSCachedURLResponse *) connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
boredzo@2402
   403
#pragma unused(connection,cachedResponse)
boredzo@2402
   404
	//	No Caching please...  Since we're using HTTPS none should occur - but no harm in being cautious.
boredzo@2402
   405
	return nil;
boredzo@2402
   406
}
boredzo@2402
   407
boredzo@2402
   408
boredzo@2402
   409
/*
boredzo@2402
   410
boredzo@2402
   411
 The delegate receives this message when connection determines that it must change URLs in order to continue loading a request.
boredzo@2402
   412
 The delegate should inspect the redirected request specified by request and copy and modify request as necessary to change its attributes, or return request unmodified.
boredzo@2402
   413
 The NSURLResponse that caused the redirect is specified by redirectResponse.
boredzo@2402
   414
 The redirectResponse will be nil in cases where this method is not being sent as a result of involving the delegate in redirect processing.
evands@3706
   415
 If the delegate wishes to cancel the redirect, it should call the connection object’s cancel method.
boredzo@2402
   416
 Alternatively, the delegate method can return nil to cancel the redirect, and the connection will continue to process.
boredzo@2402
   417
 This has special relevance in the case where redirectResponse is not nil.
boredzo@2402
   418
 In this case, any data that is loaded for the connection will be sent to the delegate, and the delegate will receive a connectionDidFinishLoading or connection:didFailLoadingWithError: message, as appropriate.
boredzo@2402
   419
evands@3706
   420
 The delegate can receive this message as a result of transforming a request’s URL to its canonical form, or for protocol-specific reasons, such as an HTTP redirect.
boredzo@2402
   421
 The delegate implementation should be prepared to receive this message multiple times.
boredzo@2402
   422
boredzo@2402
   423
 */
boredzo@2402
   424
boredzo@2402
   425
- (NSURLRequest *) connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse {
diggory@4143
   426
#pragma unused(request,redirectResponse, connection)
diggory@4143
   427
//	NSLog(@"SMS display: redirectResponse:");
diggory@4143
   428
//	[connection cancel];
diggory@4143
   429
	return request;
boredzo@2402
   430
}
boredzo@2402
   431
boredzo@2402
   432
boredzo@2402
   433
// This delegate method is called when connection has finished loading successfully. The delegate will receive no further messages for connection.
boredzo@2402
   434
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
boredzo@2402
   435
#pragma unused(connection)
diggory@4143
   436
	// NSLog(@"SMS display: connectionDidFinishLoading:");
boredzo@2402
   437
	[self connectionDidRespond];
boredzo@2402
   438
}
boredzo@2402
   439
bgannin@3280
   440
bgannin@3280
   441
- (BOOL) requiresPositioning {
bgannin@3280
   442
	return NO;
bgannin@3280
   443
}
bgannin@3280
   444
boredzo@2402
   445
@end