tags:

views:

55

answers:

1

Hey all! I read an article from http://deusty.blogspot.com/2006/11/sending-http-get-and-post-from-cocoa.html , but I quite didn't get some things. I tried to establish NSURLConnection with it and some how it won't receive data at all? If you are interested here is the site I am trying to login www.lockerz.com .

http://pastebin.com/8fP9TX8q . Fix the links as I can't post more than 1.

It actually says connection failed and I have no idea why...

+3  A: 

Problem #1

Something that immediately strikes me as wrong are the first two lines:

NSString *post = @"[email protected]&password-password=testpassword";
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

When submitting POST forms (and GET parameters in the URL), only the keys and the values should be URL encoded. Here you're not only encoding the keys and the values, but also the = and &, which is just plain wrong. I usually do something like this:

NSMutableDictionary * parameters = [NSMutableDictionary dictionary];
[parameters setObject:@"[email protected]" forKey:@"email-email"];
[parameters setObject:@"testpassword" forKey:@"password-password"];

NSMutableArray * encodedParameters = [NSMutableArray array];
for (NSString * key in parameters) {
  NSString * value = [parameters objectForKey:key];
  NSString * encoded = [NSString stringWithFormat:@"%@=%@", [key stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding], [value stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
  [encodedParameters addObject:encoded];
}

NSString * post = [encodedParameters componentsJoinedByString:@"&"];
NSData * postData = [post dataUsingEncoding:NSASCIIStringEncoding];

You may also run into problems using stringByAddingPercentEscapesUsingEncoding:. I wrote an NSString category on how to URL encode strings here.

Problem #2

You're never waiting for the connection to send. NSURLConnection, in the way that you're using it, is an asynchronous API. Thus, the following will fail:

NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (theConnection) {
  NSLog(@"Connection succeeded!");
}

What you're testing there is not the successful completion of the connection, but the successful instantiation of a connection object. That's a very very different thing. The connection itself may not actually finish for several spins of the run loop. If you want the connection to be synchronous (ie, the connection is done before the next line of code is executed), then you need to use NSURLConnection's synchronous API.

Problem #3

These lines are full of fail:

receivedData = [[NSMutableData data] retain];
NSString *text = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];

[NSMutableData data] returns an empty data object. It contains nothing. So if you create an empty data object, and then create a string out of the data, then (surprise surprise) you're going to get an empty string.

Plus you're leaking the data object (since you retain it [which is unnecessary], but never release it).

Edit since I'm feeling generous....

The following works properly (although I just hardcoded the HTTPBody string instead of building it as recommended above):

NSURL * url = [NSURL URLWithString:@"http://www.lockerz.com/auth/login/"];
NSMutableURLRequest * r = [[NSMutableURLRequest alloc] initWithURL:url];
[r setHTTPMethod:@"POST"];
[r setHTTPBody:[@"email%2Demail=test%40email%2Ecom&password%2Dpassword=testpassword" dataUsingEncoding:NSASCIIStringEncoding]];
[r setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

NSHTTPURLResponse * response = nil;
NSError * error = nil;
NSData * responseData = [NSURLConnection sendSynchronousRequest:r returningResponse:&response error:&error];
NSString * responseString = [[[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding] autorelease];
NSLog(@"%@", responseString);
[r release];

This correctly executes, and the responseString logs some HTML which describes an error page. This, however, is unsurprising, since the URL itself (http://www.lockerz.com/auth/login) produces an error when attempting to use the credentials provided in the original question.

Dave DeLong
I tried that, but now I am taken to their error page telling something went wrong, if you're so kind that could you look the website start page and see how should I make the form?
Samuli Lehtonen
Wow this is one of the coolest answers on so
Vojto
I have fixed those things now and implemented delegates, but it will put me to error page instead and not move me to the mainpage, how do I actually handle a redirect if the connection wants to do it.
Samuli Lehtonen
@Samuli edited answer
Dave DeLong
I have also tried it with the right credentials and I am still receiving the same error page in result, here is the code I got atm. Most of it is from apple reference library thing
Samuli Lehtonen
Edit: code here http://pastebin.com/SqkjzDFb
Samuli Lehtonen
I also tried you're code with right credentials and it still gives the error page, I don't get what I am doing wrong.
Samuli Lehtonen
I've tried various ways now, but I always get the same error page. Am I sending the form wrong or what?
Samuli Lehtonen
@Samuli maybe your script on the server is wrong?
Dave DeLong
Can you elaborate I didn't quite get it, you mean that I enter wrong information to the form? I checked the ID:s of the input fields from the source code.
Samuli Lehtonen
@Samuli maybe it's the script that's on the server that has the bug, because the code I wrote is correct.
Dave DeLong
I have no idea, but is there any other way archieve the same result if this one doesn't work? In all sense this should work..
Samuli Lehtonen