0

I send a few strings to my server which works perfectly fine but for some reason when i try to send a link as an NSString it doesn't send correctly.

For example the NSString PDF_URL variable is equal to:

https://s3.amazonaws.com/the+PDFs/email%40hotmail.ca_product+name+is+something_the+keycode.PDF

In my myRequestString PDF_URL is formatted correctly. But when I check my email (in my case i send the url to my email) the url ends up like this:

https://s3.amazonaws.com/the PDFs/email@hotmail.ca_product name is something_the keycode.PDF

I have no idea why objective C replaces those character's but it does it while POST to my server because I breakpoint right before it sends to check my variable and its formatted correctly.

my code:

-(void)sendPDFtoEmail{

NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];

NSURL * url = [NSURL URLWithString:@"my url"];
NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:url];



NSString *PDF_URL = [NSString stringWithFormat:@"%@%@%@%@%@%@%@", @"https://s3.amazonaws.com/the+PDFs/", email, @"_", name, @"_", keycode, @".PDF"]; 


// Create your request string with parameter name as defined in PHP file
NSString *myRequestString = [NSString stringWithFormat:@"name=%@&email=%@&keycode=%@&PDF_URL=%@", Name, email, keycode, PDF_URL];

[urlRequest setHTTPMethod:@"POST"];
[urlRequest setHTTPBody:[myRequestString dataUsingEncoding:NSUTF8StringEncoding]];

NSURLSessionDataTask * dataTask =[defaultSession dataTaskWithRequest:urlRequest
                                                   completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                       NSLog(@"Response:%@ %@\n", response, error);
                                                       if(error == nil)
                                                       {
                                                           NSString *response = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];


                                                       }

                                                   }];
[dataTask resume];

}

Also its not my PHP because i send the same string URL in Android to the same PHP and when i check my email the link isn't formatted.

Lazar Kukolj
  • 696
  • 3
  • 15
  • 43
  • 1
    You want to percent escape the parameter in the URL. What's confusing is that it looks like you did percent escape part of it. Anyway, in Objective-C, the easiest was to percent escape properly is with `CFURLCreateStringByAddingPercentEscapes`. See http://stackoverflow.com/a/25702239/1271826. Note, you should be percent escaping the values in the body of your request, too. – Rob Sep 03 '16 at 22:10
  • Unrelated, but you probably shouldn't include anything confidential in the URL (e.g. the email, keycode, etc.). If you're OK with that not being secured, fine, but it's generally not prudent to include any identifying information in the URL itself. Only in the body of the request, secured by HTTPS. – Rob Sep 03 '16 at 22:13
  • By the way, you say "when I check my email ... the url ends up [with a space]". This begs the question: Is the folder on AWS was really "the PDFs" (in which case the `+` in the URL is fine and the problem rests in how you built the URL string shown in the email, something you didn't share with us) or whether it was "the+PDFs" (in which case you should be doing percent escaping)? – Rob Sep 04 '16 at 18:15
  • I ran into way too many problems (eg. `CFURLCreateStringByAddingPercentEscapes ` is deprecated, when i call your `httpBodyForParamsDictionary ` method i doesnt work becasue i am trying to encode the URL differently and its a NSSting, `[urlRequest setHTTPBody:` expects a NSdata type and the `percentEscapeString ` retunrs a NSString, etc) inevitably i am just going to correct the URL in the PHP script. Also thanks for the advice and help! – Lazar Kukolj Sep 05 '16 at 20:14
  • 1
    Yeah, `CFURLCreateStringByAddingPercentEscapes` is deprecated, so you have to use `stringByAddingPercentEncodingWithAllowedCharacters`, but none of the standard character sets are up to the job, so you have to create your own (often by taking mutable copy of `URLQueryAllowedCharacterSet` and removing some reserved characters). But, I'm glad you solved your issue! – Rob Sep 05 '16 at 20:22
  • glad i learned a little more from you! – Lazar Kukolj Sep 05 '16 at 20:39

1 Answers1

0

Well, when you www-form-urlencode strings spaces get converted to + signs (you can check this here : http://www.url-encode-decode.com/). So if you want to actually pass + sign you need to encode your string first. It seems that Android does it itself, and iOS does not. That's why you got different results from both platforms.

This should help you :

NSCharacterSet *allowedChars = [NSCharacterSet URLQueryAllowedCharacterSet];
NSString *PDF_URL = [NSString stringWithFormat:@"%@%@%@%@%@%@%@", @"https://s3.amazonaws.com/the+PDFs/", email, @"_", name, @"_", keycode, @".PDF"];
NSString *encodedPDF_URL = [PDF_URL stringByAddingPercentEncodingWithAllowedCharacters:allowedChars];

This piece of wikipedia article is also worth reading : https://en.wikipedia.org/wiki/Percent-encoding#The_application.2Fx-www-form-urlencoded_type

It is also worth checking the documentation, as there are other predefined sets for encoding other URL components -> https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSCharacterSet_Class/#//apple_ref/occ/clm/NSCharacterSet/URLQueryAllowedCharacterSet

Losiowaty
  • 7,911
  • 2
  • 32
  • 47
  • 1
    You don't want to use `alphanumericCharacterSet`, because that includes a ton of international characters that are not permitted. And if you use this, it will also escapes some characters that don't need to be escaped, too. – Rob Sep 03 '16 at 22:08
  • @Rob - You are right, didn't think of that, thanks! I've updated my answer. – Losiowaty Sep 04 '16 at 17:57
  • 1
    `URLQueryAllowedCharacterSet` is much closer. But that now sadly still lets `&` and `+` pass unescaped (because those characters _are_ allowed in a URL query, but just have special meanings in `x-www-form-urlencoded` request and thus need to be percent escaped when used within that context). See the caveat about using `URLQueryAllowedCharacterSet` in http://stackoverflow.com/a/22725563/1271826. – Rob Sep 04 '16 at 18:07
  • Wow, thanks! That's what I like about SO - you never stop learning :) – Losiowaty Sep 04 '16 at 18:11