5

I have created one user enquiry form in ios. I'm using php as a server side. I constructed query string like bellow in IOS

http://www.mydomain.in/androidmail_enquiry.php?name=Vinoth Kumar&phone=04259280244&[email protected]&address=Coimbatore&comments=Sample Enquiry&mobile=xxxxxxxx

Code:

-(void)sendEnquiryDetails
{
    cmttextview.text = @"Sample Enquiry";
    NSString *siteurl = @"http://www.mydomain.in/androidmail_enquiry.php?";
    NSString *name = txtName.text;
    NSString *phone = txtPhone.text;
    NSString *email = txtEmail.text;
    NSString *address = txtAddress.text;
    NSString *comments = cmttextview.text;
    NSString *mobile = txtMobile.text;
    NSString *enquiryurl = [NSString stringWithFormat:@"%@name=%@&phone=%@&email=%@&address=%@&comments=%@&mobile=%@",siteurl,name,phone,email,address,comments,mobile];

    NSLog(enquiryurl);

   NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:enquiryurl]];
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request  delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    //NSLog(@"didReceiveResponse");
    [self.responseData setLength:0];
}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.responseData appendData:data];
}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"%@",[NSString stringWithFormat :@"didfailwitherror: %@", [error description]]);
}

-(void)connectionDidFinishLoading: (NSURLConnection *)connection{
    NSLog(@"Success Code:%@",self.responseData);
}

But when i submit this by using NSURLRequest getting error like invalid url(URL Forming error) in didFailWithError method.

1
  • 1
    post your code what you did... Commented Oct 9, 2013 at 4:32

3 Answers 3

7

Make sure You have added stringByAddingPercentEscapesUsingEncoding , because in your url there is space in name , so in browser it is replaced with %20 you have to add programmatically in code,

Try this

-(void)sendEnquiryDetails
{
    cmttextview.text = @"Sample Enquiry";
    NSString *siteurl = @"http://www.mydomain.in/androidmail_enquiry.php?";
    NSString *name = txtName.text;
    NSString *phone = txtPhone.text;
    NSString *email = txtEmail.text;
    NSString *address = txtAddress.text;
    NSString *comments = cmttextview.text;
    NSString *mobile = txtMobile.text;
    NSString *enquiryurl = [NSString stringWithFormat:@"%@name=%@&phone=%@&email=%@&address=%@&comments=%@&mobile=%@",siteurl,name,phone,email,address,comments,mobile];

    NSLog(enquiryurl);

 NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[enquiryurl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request  delegate:self];
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks i corrected my mistake, now it's working by added stringByAddingPercentEscapesUsingEncoding
@VinothKumar This only works if the password (and any of the other fields) do not contain any of the other reserved characters (e.g. &, + and others). You should use CFURLCreateStringByAddingPercentEscapes if you want this to be more robust.
4

You have to percent escape reserved characters. If nothing else, you have to replace those spaces with + (or %20).

Unfortunately, the standard stringByAddingPercentEscapesUsingEncoding is not up to the job, as it leaves some characters unescaped. Your sample doesn't include any of them, but if the person's name was entered as "Bill & Melinda Gates" or "Bill + Melinda Gates", stringByAddingPercentEscapesUsingEncoding would not handle that properly. You really should use CFURLCreateStringByAddingPercentEscapes to percent escape the values, for example using this category:

@implementation NSString (URLEncode)

- (NSString *)stringForHTTPRequest
{
    NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                 (CFStringRef)self,
                                                                                 (CFStringRef)@" ",
                                                                                 (CFStringRef)@":/?@!$&'()*+,;=",
                                                                                 kCFStringEncodingUTF8));
    return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
}

@end

This properly escapes all reserved characters, but replaces spaces with + characters (which you should do if your request type is application/x-www-form-urlencoded).

Alternatively, you can also replace the space characters with %20 like so:

- (NSString *)stringForHTTPRequest
{
    return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                     (CFStringRef)self,
                                                                     NULL,
                                                                     (CFStringRef)@":/?@!$&'()*+,;=",
                                                                     kCFStringEncodingUTF8));
}

With that, you could modify that line of code that builds the URL string:

NSString *enquiryurl = [NSString stringWithFormat:@"%@name=%@&phone=%@&email=%@&address=%@&comments=%@&mobile=%@",
                        siteurl, 
                        [name stringForHTTPRequest],
                        [phone stringForHTTPRequest],
                        [email stringForHTTPRequest],
                        [address stringForHTTPRequest],
                        [comments stringForHTTPRequest],
                        [mobile stringForHTTPRequest]];

7 Comments

Finally, I can agree with most of your statements. :) The "application/x-www-form-urlencoded" encoding algorithm can be implemented using CFURLCreateStringByAddingPercentEscapes and stringByReplacingOccurrencesOfString: the way you suggested, just with a slightly different set of legalURLCharactersToBeEscaped. But eventually, after decoding, both resulting strings are equal again anyway. I will edit may answer and remove the other irrelevant stuff.
@Rob AFNetworking converts the characters :/?&=;+!@#$()',* are you missing some \?
@DavidCaunt Yes, that is correct. That escapes all of the reserved characters listed in RFC 3986 (though the # is not needed, because that's already escaped). I've updated my answer accordingly.
What's about the * which is element of the sub-delims set? According RFC 3986, in a query component, characters from the sub-delims set don't need to be encoded. The "application/x-www-form-urlencoded" does also not require to encode it. :)
@CouchDeveloper I agree that you might not have to escape the sub-delim, but I see no reason not to, and it seems more future-proof to include it. I don't know why you'd escape some of the sub-delim, but single out the asterisk for exclusion. If this still troubles you, I'd suggest you ask a new S.O. question on the topic, or submit an issue to AFNetworking and ask there. But the convention of AFNetworking (which I've adopted here) is to escape all of the RFC3986 reserved characters.
|
2

According the docs, if a NSURL object is initialized with a string, the string must conform to RFC 2396 (see official Apple docs URLWithString).

The most recent RFC however is RFC 3986 which obsoletes RFC 2396.

Caution:

Neither Cocoa nor Core Foundation will have a function which out of the box returns a properly encoded URL string conforming to RFC 2396 or RFC 3986, though.

Different components of a URL have varying percent encoding requirements.

Edit:

In order to transmit structured parameters in a unstructured query component of a URL, an encoding scheme equal to the application/x-www-form-urlencoded encoding algorithm can be applied to the query component.

A helper function which encodes the name or value and which conforms to that encoding can be implemented as:

static NSString* urlformdata_encode(NSString* s) {
    CFStringRef charactersToLeaveUnescaped = CFSTR(" ");
    CFStringRef legalURLCharactersToBeEscaped = CFSTR("!$&'()+,/:;=?@~");
    
    NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
                             kCFAllocatorDefault,
                             (__bridge CFStringRef)s,
                             charactersToLeaveUnescaped,
                             legalURLCharactersToBeEscaped,
                             kCFStringEncodingUTF8));
    return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
}

(Note: this code depends on the current implementation of CFURLCreateStringByAddingPercentEscapes, especially its default escaping. If those change, the code may not correctly implement the algorithm.)

According RFC 3986, the query component of the URL is treated as an unstructured percent encoded byte stream containing only ASCII characters.

Originally, the "application/x-www-form-urlencoded" encoding scheme has been defined for transmitting form-data from a browser to a server which becomes the payload of a body. That is, the context is totally different than for URLs. Nonetheless, even this encoding scheme is not defined in RFC 3986, it is finally compatible with the URL encoding scheme.

Caveats

The "application/x-www-form-urlencoded" encoding scheme may produce percent escapes for characters that are now in the "Unreserved" character set according RFC 3986, namely the tilde ~ character. Characters in the "Unreserved" character set don't need to be escaped. More strictly, due to implications in URI comparison implementations, RFC 3986 makes this recommendation:

"For consistency, percent-encoded octets in the ranges of ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E), underscore (%5F), or tilde (%7E) should not be created by URI producers".

In order to not escape the tilde ~ in query parameters, one can remove the tilde ~ from the set of legal URL characters to be escaped legalURLCharactersToBeEscaped:

CFStringRef legalURLCharactersToBeEscaped = CFSTR("!$&'()+,/:;=?@");

Not escaping the tilde should not cause issues, even though it is not strict according the "application/x-www-form-urlencoded encoding" algorithm.

Differences to the other suggested algorithms to this question:

Since the "application/x-www-form-urlencoded" decoding algorithm decodes any percent decoded character sequence into its corresponding Unicode code unit, differences in the set of legalURLCharactersToBeEscaped specified in CFURLCreateStringByAddingPercentEscapes during encoding may eventually yield equal strings.

(Edit: removed helper functions which encode components of a URL, which are not relevant when a query string should be encoded via application/x-www-form-urlencoded)

2 Comments

We should probably not use that ancient "application/x-www-form-urlencoded" encoding in URL params. It's perfectly valid to use JSON for example, and percent encode that according a query component defined in RFC 3986.
@Rob Thanks for hint about the tilde! Added a "Caveat" section explaining the issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.