How to pass * () $ etc in NSUrl? - ios

I tried to pass these characters to server, for example *()$
I have coded the NSUrl this way:
NSString *partialURL = [NSString stringWithFormat:#"/%#", commentBody];
NSString *fullURL = [NSString stringWithFormat:#"%#%#", CONST_URL, partialURL];
NSString *encStr = [fullURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:encStr];
But then, the commentBody passed in the url still has *()$ things and not encoded into utf8.
What is the correct way to do it?
Thanks!

NSString * test = (NSString *) CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)validUrl,
NULL,
(CFStringRef)#";/?:#&=$+{}<>,",
kCFStringEncodingUTF8);
UPDATE
Hi #Rendy. Sorry for the quickie reply yesterday. I only had time to past a 1-liner before jumping off and had hoped it would be enough for you to correct the issue you were having.
You always want to encode the parameters of the URL. IF you have a URL that is a parameter to another URL or embedded in some XML; you'll want to encode the entire url (which means parameters get double-encoded - because you take a "valid" URL and escape it so it becomes a valid parameter in another URL (ie, : and & get escaped, so parameters don't mix together.)
If you like, you can add additional chars to the string below and they'll be replaced with percent-encoded values. I believe the string below already has you covered for the invalid values.
Here's a category on NSString:
#implementation NSString (encode)
+ (NSString*)stringEncodedAsUrlParameter:(NSString *)string
{
NSString *newString = NSMakeCollectable(
[(NSString *)CFURLCreateStringByAddingPercentEscapes(
kCFAllocatorDefault,
(CFStringRef)string,
NULL, /* charactersToLeaveUnescaped */
CFSTR(":/?#[]#!$ &'()*+,;=\"<>%{}|\\^~`"),
kCFStringEncodingUTF8
) autorelease]
);
if (newString) {
return newString;
}
return #"";
}
- (NSString*)stringByEncodingAsUrlParameter
{
return [NSString stringEncodedAsUrlParameter:self];
}
#end
Call it like this:
NSString * escapedParameters = [NSString stringEncodedAsUrlParameter:unescapedParameters];
Or:
NSString * escapedParameters = [unescapedParameters stringByEncodingAsUrlParameter];
Then add your properly escaped parameters to the end of your URL. If you encode the whole URL, you'll encode the "http://" portion and it won't work.
I originally copied the above from ASIHttpRequest, but any bugs added are mine.
Hope that helps! Best of luck!!

Related

String encode in objective c

I am very new to Objective-C.
I want to get the encoded content for a NSString. In java I can do that as follows,
String str = "https://www.google.co.in/#q=ios+sqlite+crud+example";
String encodedParam = URLEncoder.encode(str, "UTF-8");
I am using http://www.tutorialspoint.com/compile_objective-c_online.php to test the codes posted in stackoverflow. There is no solution yet. I know its trivial one. Struggling to find a way though.
tried with following function, and it says following error while compile,
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(encoding));
}
Error,
sh-4.3$ gcc `gnustep-config --objc-flags` -L/usr/GNUstep/System/Library/Libraries -lgnustep-base -lobjc *.m -o main
main.m: In function 'main':
main.m:7:14: error: 'urlEncodeUsingEncoding' undeclared (first use in this function)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
^
main.m:7:14: note: each undeclared identifier is reported only once for each function it appears in
main.m:7:36: error: expected ';' before ':' token
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
Edit as per the answers,
Suggested by Patrick, I used the code as follows,
NSString *storedURL = #"google.com/?search&q=this";
NSString *urlstring = [NSString stringWithFormat:#"http://%#/",storedURL];
NSURL *url = [NSURL URLWithString:urlstring];
NSError *error = nil;
NSStringEncoding encoding;
NSString *my_string = [[NSString alloc] initWithContentsOfURL:url
usedEncoding:&encoding
error:&error];
NSLog (my_string);
Nothing printed in console... Is it my NSLog is right?
Suggested by lightwolf, my code is looks like below,
NSString *str = #"https://www.google.co.in/#q=ios+sqlite+crud+example";
NSString *encodedParam = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog (encodedParam);
it prints the log, but value is same as the str..... not encoded... I want this str as
https%3A%2F%2Fwww.google.co.in%2F%23q%3Dios%2Bsqlite%2Bcrud%2Bexample
If you want to encode a specific range of characters you chould use
NSString *str = #"https://www.google.co.in/#q=ios+sqlite+crud+example";
NSString *encodedParam = [str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]];
NSLog (#"%#", encodedParam);
Note the invertedSet; In that way, you are encoding all characters except the set specified (all alphanumeric ones)
The result is
https%3A%2F%2Fwww%2Egoogle%2Eco%2Ein%2F%23q%3Dios%2Bsqlite%2Bcrud%2Bexample
If you want to use a specific set of characters you should use
NSString *str = #"https://www.google.co.in/#q=ios+sqlite+crud+example";
NSCharacterSet* set = [NSCharacterSet characterSetWithCharactersInString:#"!*'();#&=+$,?%#[]"];
NSString *encodedParam = [str stringByAddingPercentEncodingWithAllowedCharacters:[set invertedSet]];
NSLog (#"%#", encodedParam);
In this case I intentionally missed / and : so the result is
https://www.google.co.in/%23q%3Dios%2Bsqlite%2Bcrud%2Bexample
Maybe this is what you want
NSString *str = #"<html><head><title>First</title></head><body><p>Parsed HTML into a doc.</p></body></html>";
NSString *encodedParam = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
You have to encode only the params, not the entire URL of course

iOS: NSASCIIStringEncoding doesn't encode certain characters correctly

I have url that I am going to request data from. Here is the code.
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:
NSASCIIStringEncoding];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:urlStr]];
This works except when I have certain characters such as ş. The urlstr will return null. Is there a way around this to except certain character types? Any tips or suggestions are appreciated.
I've used the following method with success in many applications:
- (NSString *)urlEncode:(NSString *)str {
return (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)str, NULL, CFSTR("!*'();:#&=+$,/?%#[]"), kCFStringEncodingUTF8));
}
Note that I use this on only the params of the URL, so the following would work (notice I added the ş, which seemed to work, although I'm not familiar with that character):
NSString *baseURL = #"http://www.google.com";
NSString *paramsString = #"testKey=test value_with some (weirdness)!___ş";
NSString *resultingURLString = [NSString stringWithFormat:#"%#?%#", baseURL, [self urlEncode:paramsString]];
Which produces the result:
http://www.google.com?testKey%3Dtest%20value_with%20some%20%28weirdness%29%21___%C5%9F

Percent escaping query url strings

I am getting NSString as given http://maps.apple.com/maps?saddr=41.447910,-74.357881&daddr=719 Old Route 9 North, Wappingers Falls, NY 12590
However i need to covert the above string into this one given for showing location in map
http://maps.apple.com/maps?saddr=41.447910,-74.357881&daddr=719+Old%20Route+9+North%2CWappingers+Falls%2CNY+12590
Please let me know.
You can do this with the following...
NSString *theOrigString = #"http://maps.apple.com/maps?saddr=41.447910,-74.357881&daddr=719 Old Route 9 North, Wappingers Falls, NY 12590";
NSString *formattedString = [theOrigString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%#", formattedString);
Output
http://maps.apple.com/maps?saddr=41.447910,-74.357881&daddr=719%20Old%20Route%2‌​09%20North,%20Wappingers%20Falls,%20NY%2012590
This will replace spaces with %20 and so on.
You can then use this as a url string.
An old question but this is what you need:
-(NSString*) encodeToPercentEscapeString:(NSString *)string {
return (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef) string,
NULL,
(CFStringRef) #"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8)); }
-(NSString*) decodeFromPercentEscapeString:(NSString *)string {
return (NSString *)CFBridgingRelease(CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL,
(CFStringRef) string,
CFSTR(""),
kCFStringEncodingUTF8)); }
Take a look at NSString's stringByAddingPercentEscapesUsingEncoding:
NSString *urlString = #"http://maps.apple.com/maps?saddr=41.447910,-74.357881&daddr=719 Old Route 9 North, Wappingers Falls, NY 12590";
NSString *encodedString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
The reason behind the percent encoding simply comes down from the RFC 3986. In a nutshell, you should percent escape values of your URI query params to escape the reserved characters ("!*'();:#&=+$,/?%#[]"). Doing so it is possible to properly decoding the encoded URI - supposing for the sake of simplicity same encoding on the both sides.
As pointed out by Duncan and Fogmeister, Apple's stringByAddingPercentEscapesUsingEncoding is very friendly but, in general, wrong - or, at least, say, not compliant with RFC 3986 - since doesn't percent escape chars like "/:&%?".
A more general and robust solution would be something like
NSString * HKObjectToString(id object) {
return [NSString stringWithFormat:#"%#", object];
}
NSString * HKPercentEscapedString(id object, CFStringEncoding encoding) {
NSString *string = HKObjectToString(object);
return ((NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (__bridge CFStringRef) string, NULL,
CFSTR("!*'();:#&=+$,/?%#[]"),
encoding)));
}
...
#implementation NSDictionary (URLAdditions)
...
- (NSString *)percentEscapedQueryStringWithEncoding:(CFStringEncoding)encoding
{
NSMutableArray *queryParts = [[NSMutableArray alloc] init];
for (NSString *key in [self allKeys]) {
NSString *part = [NSString stringWithFormat:#"%#=%#", HKPercentEscapedString(key, encoding), HKPercentEscapedString(HKObjectToString(self[key]), encoding)];
[queryParts addObject:part];
}
return [queryParts componentsJoinedByString:#"&"];
}
...
#end
...
#implementation NSString (StringHelper)
...
+ (NSString *)URIEncodedWithStringURI:(NSString *)baseURI queryParameters:(NSDictionary *)queryParams URIEncoding:(CFStringEncoding)encoding
{
return [NSString stringWithFormat:#"%#?%#", baseURI, [queryParams percentEscapedQueryStringWithEncoding:encoding]];
}
...
#end
For more details try to give a look at this public repo on github.
This question is problematic because the input data is damaged. At some earlier point in the code, this URL got decoded as a single string. You should never do that, because it can lead to situations where the distinction between different parts of the URL is lost and can never be recovered. For example, suppose I have this URL:
http://www.example.com/folder/this%2Fthat.html
When decoded, this becomes
http://www.example.com/folder/this/that.html
and there's no way to turn that back into the original, because there's no way to know which of those slashes is real and which should be encoded as %2F. The distinction is simply lost.
For this reason, when you work with URLs, it is important to always preserve them in their original form whenever possible, and when you have to decode a URL, to do so piecewise—that is, to start by splitting apart all of the path components, the query string, and so on, then pulling apart the fields in the query string (where applicable), and finally decoding each part individually.
After that, you would need to reencode each part by using CFURLCreateStringByReplacingPercentEscapesUsingEncoding, because the NSString method above doesn't do percent encoding of slashes, ampersands, and other special URL characters.
But in your case, your best bet is to find the code that is decoding the URL, and rip it out so that you have the original, undamaged URL. If and only if that is not possible, the stringByAddingPercentEscapesUsingEncoding: method can make a "best guess" about what to encode, so long as you understand that for arbitrary URLs, that solution won't necessarily work.
Edited:
Sulthan has a point. You can't percent encode the whole URL if the string portion (like the address in this case) might contain reserved URL characters ("/", ":", "&", "%", "?", etc.)
The stringByAddingPercentEscapesUsingEncoding method encodes spaces, but not slashes, colons, etc. Thus if the address string contains any of those, the receiver of the URL can't tell what's part of the syntax of the URL and what's data.
I have a category of NSString that escapes these characters as well:
The header
#import <Foundation/Foundation.h>
#interface NSString (URLEncoding)
- (NSString *)stringByAddingPercentEscapes;
- (NSString *)stringByReplacingPercentEscapes;
#end
NSString *mapURLStringTemplate =
#"http://maps.apple.com/maps?saddr=%f,%f&daddr=%#";
The body:
#import "StringCategory.h"
CFStringRef charsToEscape = CFSTR(":/&=");
#implementation NSString (URLEncoding)
- (NSString *)stringByAddingPercentEscapes
{
return (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self, NULL, charsToEscape,
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)));
}
- (NSString *)stringByReplacingPercentEscapes
{
return (NSString *)CFBridgingRelease(CFURLCreateStringByReplacingPercentEscapes(kCFAllocatorDefault,(CFStringRef)self, CFSTR("")));
}
#end
And to use it:
NSString *escapedAddressString =
[addressString stringByAddingPercentEscapes];
NSString *mapURLString =
[NSString stringWithFormat: mapURLStringTemplate,
latitude,
longitude,
escapedAddressString];

Creating NSURL with custom query parameter returns nil

I have a UISearchBar from which I'm extracting the text that represents an address and building from it a JSON URL for Google Geocoder.
NSString* address = searchbar.text;
NSString* url = [NSString stringWithFormat:#"http://maps.google.com/maps/api/geocode/json?address=%#&sensor=false", address];
If I copy & paste the url from debug window to the browser it works like a charm but when I try to convert it to NSURL i get nil
NSURL* theUrl = [NSURL URLWithString:url];
Any ideas?
I added the encoding to the address prior to concatenating the url and that fixed the problem so now the code looks like this:
NSString* address = searchbar.text;
NSString *encodedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, CFBridgingRetain(address), NULL, (CFStringRef)#"!*'();:#&=+$,/?%#[]", kCFStringEncodingUTF8));
NSString* url = [NSString stringWithFormat:#"http://maps.google.com/maps/api/geocode/json?address=%#&sensor=false", encodedString];

URL for GET request

To get the JSON I was using this answer SBJsonWriter Nested NSDictionary
Now I have a sting {"key1":"bla1","key2":{"a":"a1","b":"b1","c":"c1","d":"d1"},"key3":"bla3"} that I've called theString
and I need to add it to a url http://mysyte.net:8888/JSON?
and to receive something like this http://lcwebtest.sytes.net:8888/JSON?{"key1":"bla1","key2":{"a":"a1","b":"b1","c":"c1","d":"d1"},"key3":"bla3"}
Here is what I do:
NSString *urlString = [NSString stringWithFormat:#"http://mysyte.net:8888/JSON?%#",theString];
NSLog gives http://mysyte.net:8888/JSON?{"key2":{"d":"d1","b":"b1","c":"c1","a":"a1"},"key1":"bla1","key3":"bla3"}
Then I make a url from it by
NSURL *url1 = [NSURL URLWithString:urlString];
BUT NSLog(#"%#",url1); gives me {null}
I assume NSURL does not want to read the "{" or "}" and thinks that the url was malformed.
How can I receive the url to make a GET request?
I assume NSURL does not want to read the "{" or "}" and thinks that the url was malformed.
That's right, you're not allowed to put some special characters in a URL. You want to escape the JSON string like this:
CFStringRef escaped = CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)theString, // (__bridge CFStringRef)theString if you use ARC
CFSTR(""),
CFSTR("?&=%,:+-"),
kCFStringEncodingUTF8
);
NSString *urlString = [NSString stringWithFormat:#"http://mysyte.net:8888/JSON?%#", (NSString *)escaped];
CFRelease(escaped);

Resources