iOS : How to do proper URL encoding? - ios

I'm unable to open a URL into UIWebView so I've seached & found that I need to encode URL, so I tried to encode it but, I've facing problem in URL encoding : My URL is http://somedomain.com/data/Témp%20Page%20-%20Open.html (It's not real URL).
I'm concerned with %20 that I tried to replace using stringByReplacingOccuranceOfString:#"" withString:#"" , it give me the URL I wanted like http://somedomain.com/data/Témp Page - Open.html However its not opening in UIWebView but amazingly it opens in Safari & FireFox perfect. Even I open unencoded URL its automatically converts and open the page I'm looking for.
I've google for URL encoding & it points me to different results I already checked but no results help me out!! I tried different functions answers in different URL encoding question but it just changed all special characters and make my URL like, http%3A%2F%2Fsomedomain.com%2Fdata%2FT... which can't open in UIWebView and even in any browser.
It gives the following Error Log in UIWebView delegate
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { }
Error Code : 101
& Description : Error Domain=WebKitErrorDomain Code=101 "The operation couldn’t be completed. (WebKitErrorDomain error 101.)" UserInfo=0x6e4cf60 {}

The answer #Dhaval Vaishnani provided is only partially correct. This method treats the ?, = and & characters as not to be encoded, since they're valid in an URL. Thus, to encode an arbitrary string to be safely used as a part of an URL, you can't use this method. Instead you have to fall back to using CoreFoundation and CFURLRef:
NSString *unsafeString = #"this &string= confuses ? the InTeRwEbZ";
CFStringRef safeString = CFURLCreateStringByAddingPercentEscapes (
NULL,
(CFStringRef)unsafeString,
NULL,
CFSTR("/%&=?$#+-~#<>|\\*,.()[]{}^!"),
kCFStringEncodingUTF8
);
Don't forget to dispose of the ownership of the resulting string using CFRelease(safeString);.
Also, it seems that despite the title, OP is looking for decoding and not encoding a string. CFURLRef has another, similar function call to be used for that:
NSString *escapedString = #"%32%65BCDEFGH";
CFStringRef unescapedString = CFURLCreateStringByReplacingPercentEscapesUsingEncoding (
NULL,
(CFStringRef)escapedString,
CFSTR(""),
kCFStringEncodingUTF8
);
Again, don't forget proper memory management.

I did some tests and I think the problem is not really with the UIWebView but instead that NSURL won't accept the URL because of the é in "Témp" is not encoded properly. This will cause +[NSURLRequest requestWithURL:] and -[NSURL URLWithString:] to return nil as the string contains a malformed URL. I guess that you then end up using a nil request with -[UIViewWeb loadRequest:] which is no good.
Example:
NSLog(#"URL with é: %#", [NSURL URLWithString:#"http://host/Témp"]);
NSLog(#"URL with encoded é: %#", [NSURL URLWithString:#"http://host/T%C3%A9mp"]);
Output:
2012-10-02 12:02:56.366 test[73164:c07] URL with é: (null)
2012-10-02 12:02:56.368 test[73164:c07] URL with encoded é: http://host/T%C3%A9mp
If you really really want to borrow the graceful handling of malformed URLs that WebKit has and don't want to implement it yourself you can do something like this but it is very ugly:
UIWebView *webView = [[[UIWebView alloc]
initWithFrame:self.view.frame]
autorelease];
NSString *url = #"http://www.httpdump.com/texis/browserinfo/Témp.html";
[webView loadHTMLString:[NSString stringWithFormat:
#"<script>window.location=%#;</script>",
[[[NSString alloc]
initWithData:[NSJSONSerialization
dataWithJSONObject:url
options:NSJSONReadingAllowFragments
error:NULL]
encoding:NSUTF8StringEncoding]
autorelease]]
baseURL:nil];

The most straightforward way is to use:
NSString *encodedString = [rawString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
iDhaval was close, but he was doing it the other way around (decoding instead of encoding).
Anand's way would work, but you'll most likely have to replace more characters than spaces and new lines. See the reference here:
http://en.wikipedia.org/wiki/Percent-encoding#Percent-encoding_reserved_characters
Hope that helps.

It's very simple to encode the URL in iPhone. It is as following
NSString* strURL = #"http://somedomain.com/data/Témp Page - Open.html";
NSURL* url = [NSURL URLWithString:[strURL stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
It's a perfect way to encode the URL, I am using it and it's perfectly work with me.
Hope it will help you!!!

This may useful to someone who's reach to this question for URL encoding, as my question likely different which has been solved and accepted, this is the way I used to do encoding,
-(NSString *)encodeURL:(NSString *)urlString
{
CFStringRef newString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)urlString, NULL, CFSTR("!*'();:#&=+#,/?#[]"), kCFStringEncodingUTF8);
return (NSString *)CFBridgingRelease(newString);
}

You can try this
NSString *url = #"http://www.abc.com/param=Hi how are you";
NSString* encodedUrl = [url stringByAddingPercentEscapesUsingEncoding:
NSASCIIStringEncoding];

I think this will work for you
[strUrl stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]
the Native method for URL Encoding.

Swift 4.x
let originalString = "https://www.somedomain.com/folder/some cool file.jpg"
let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
print(escapedString!)

You probably need to break the URL down into it's constituent parts and then URL encode the host and path but not the scheme. Then put it back together again.
Create an NSURL with the string and then use the methods on it such as host, scheme, path, query, etc to pull it apart. Then use CFURLCreateStringByAddingPercentEscapes to encode the parts and then you can put them back together again into a new NSURL.

can you please Try this out.
//yourURL contains your Encoded URL
yourURL = [yourURL stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
yourURL = [yourURL stringByReplacingOccurrencesOfString:#"\n" withString:#""];
NSLog(#"Keyword:%# is this",yourURL);
I am not sure,but I have solved using this in my case.
Hope this will solve yours.

Related

NSURL encoding with special characters

I am trying to submit a request using NSURL to the following:
http://api.allsaints.com/v1/product/?category=Women's Knitwear
when putting this URL in a browser with the ' and the space int the category, the browser (chrome) is modifying the request to:
http://api.allsaints.com/v1/product/?category=Women%27s%20Knitwear which works.
However, I can not get the right encoding to work as part of a NSURL and NSDATA request on iOS. I tried various encoding using stringByAddingPercentEscapesUsingEncoding to normalise the URL but it keep on failing.
Can someone point me in the right direction to an encoding that not only swaps the space to a %20 but also swaps the ' to a %27?
Refer to NSString stringByAddingPercentEscapesUsingEncoding: you should use CFURLCreateStringByAddingPercentEscapes to custom which character you want to escape.
- (NSString *) urlencodeStr:(NSString *)str
{
return (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef) str,
NULL,
CFSTR("!*'();:#+$,/?%#[]"),
kCFStringEncodingUTF8));
}
CFSTR("!*'();:#+$,/?%#[]") contains the characters will be escaped.

Not able to understand Bing JSON response

My code:
NSString *urlString = [NSString stringWithFormat:#"%#%#%#%#", #"http://api.search.live.net/json.aspx?Appid=am hiding the appid &query=",text,#"&sources=web&web.offset=",offvalue];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:url];
The JSON response:
SearchResponse = {
Errors = (
{
Code = 1002;
HelpUrl = "http://msdn.microsoft.com/en-us/library/dd251042.aspx";
Message = "Parameter has invalid value.";
Parameter = "SearchRequest.AppId";
Value = " am hiding the value";
}
);
Query = {
SearchTerms = iphone;
};
Version = "2.2";
};
}
What wrong am I doing here.Can anyone please rectify my query??How to use version 2.2 of the bing API
What is the value of 'text', is this one word or multiple words? You'll need to perform URL_Encode on the parameter 'text' in order to have a valid URL.
See Objective-C and Swift URL encoding
Be sure only to have the URL_Encoding on the text-object and not on the whole URL, otherwise "http://" will be encoded as well, resulting in an invalid URL as well
Eg a space should be %20 , you can verify this by adding a NSLog of the URL
It looks like you entered the wrong AppID judging from.
Parameter = "SearchRequest.AppId";
Make sure that the AppID matches the appID that they assigned your app with the service.
Also (and this sometimes randomly causes issues for me) make sure you put a / at the end of the URL String.

ios - problems after encoding a url string

I have some code to send a url to a remote server. If I do not encode the url, it works perfectly. But if I encode the url, it does not work. So I am pretty sure something is not right with the way I encode the url query string.
Here is my code:
// URL TO BE SUBMITTED.
NSString *urlString =
#"http://www.mydomain.com/test.php?";
// NOW CREATE URL QUERY STRING
NSString *unencoded_query_string =
#"name=%#&user_id=%#&person_name=%#&person_email=%#&privacy=%#";
// PUT PREVIOUSLY SET VALUES INTO THE QUERY STRING
NSString *unencoded_url_with_params =
[NSString stringWithFormat:unencoded_query_string, business , user_id , name , email , privacy_string];
// ENCODE THE QUERY STRING
NSString *escapedString = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef)unencoded_url_with_params,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8);
// NOW APPEND URL TO QUERY STRING
NSString *full_encoded_url_string =
[urlString stringByAppendingString: escapedString];
and then I send this string to the server, and the server does have the correct request file invoked, but isn't able to read the parameters.
Would anyone know what I doing incorrectly here? I am using arc by the way.
Thanks!
I think you probably want to escape each param, not the entire request. Basically you want to escape ampersands, spaces etc that show up in your get variables. Your encoded URL probably looks like this:
http://www.mydomain.com/test.php?name%3DPeter%20Willsey%26user_id%3DUSERID%26person_name%3DPeter%20Willsey%26person_email%3Dpeter%40test.com%26privacy%3D1
and it should look like this:
http://www.mydomain.com/test.php?name=Peter%20Willsey&user_id=25&person_name=Peter%20Willsey&person_email=peter%40test.com&privacy=1

iOS NSString in UTF16

I have a string that I fetched from an Apache server over HTTP:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
...
I need to make that string a UTF16 string. I don't want to turn it into NSData. I need to keep it NSString and I need it to be in UTF16.
I would be happy to put it in an NSData object even, if I could do it as UTF16. I'm doing something similar now:
[self.returnedData appendData:data];
But that still transfers it as UTF8.
It's probably simple and I'm missing it. But I don't find it in the Apple docs or this site, and my Google-Fu has failed me.
What am I missing? How do I do that?
Thanks for your time and help.
EDIT:
Ok. All of what you and Justin have said makes sense and makes things make more sense.
So this is what I am doing. It seems to be correct from this line but I wanted to make sure I am understanding you correctly.
NSData *resultData = [self. result dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
NSString *resultStr = [[NSString alloc] initWithData:resultData encoding:NSUTF16LittleEndianStringEncoding];
NSString *md5Result = [[NSString stringWithFormat:#"%#",[resultStr MD5]] uppercaseString];
NSLog(#"md5Result = %#",md5Result);
That last part is what I am doing with the string after it's UTF-16. I have a category that makes it an MD5 hex string similar to http://blog.blackwhale.at/?tag=hmac
Thanks again. I'll bump you guys both and say this is the right answer.
A string is a string is a string. The encoding refers to how its encoded and decoded to and from NSData. #"blah" is the same as #"blah". There is no UTF8 or UTF 16 for either of those.
Added
So you can do [#"myString" dataUsingEncoding:NSUTF16StringEncoding];
If you convert that back to a string, you'll still have #"myString"
Answer last question in comment below.
So when you POST to a server the server body is encoded data. So what you wanted to do is do what ever you want to the string. THEN convert the string to data using a particular encoding, in your case, NSUTF16StringEncoding or NSUTF16LittleEndianStringEncoding. You are NOT creating UTF-16 string. You are converting a unicode string to UTF-16 encoded data. This is what you need to do then.
NSData *postBody = [[[self.result MD5] uppercaseString] dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
If you need to add more data to the postBody create NSMutableData instead and append the new data as needed.
NSString holds a buffer of whatever encoding it chooses - that may be UTF-8, UTF-16, or something else.
If you just want to create an NSString from a UTF-16 sequence, try NSUTF16BigEndianStringEncoding or one of its relatives.

IOS affiliate link shorten with bit.ly not working

I want to use bit.ly to track my itunes affiliate links.
I get affiliate links from http://target.georiot.com.
It works when oppening the direct link (going to itunes).
But when i shorten the affiliate link with bitly, it doesn't go on the same page.
Here is the code for getting the shorten url:
NSString *longURL = link;
NSString *bitlyRequestURLString = [NSString stringWithFormat:#"http://api.bit.ly/shorten?version=2.0.1&format=xml&login=%#&apiKey=%#&longUrl=%#",
#"myappname",
#"myappidentifier",
longURL];
NSURL *bitlyURL = [NSURL URLWithString:bitlyRequestURLString];
// get the short URL from bit.ly
NSError *error;
NSString *response = [NSString stringWithContentsOfURL:bitlyURL encoding:NSUTF8StringEncoding error:&error];
NSString *shortURL = #"";
NSArray *responseParts = [response componentsSeparatedByString:#"<shortUrl>"];
if ([responseParts count] > 1) {
NSString *responsePart = [responseParts objectAtIndex:1];
responseParts = [responsePart componentsSeparatedByString:#"</shortUrl>"];
if ([responseParts count] > 0) {
shortURL = [responseParts objectAtIndex:0];
}
}
Last redirect link goes someting like "http://phobos.apple.com/WebObjects/...."
Any Ideas?
Thanks
You probably need to URL encode your longURL before sending it in the query string to bit.ly
You can use the NSString method stringByAddingPercentEscapesUsingEncoding:
NSString *longURL = [link stringByAddingPercentEscapesUsingEncoding:
NSASCIIStringEncoding];
NSString *bitlyRequestURLString = [NSString stringWithFormat:#"http://api.bit.ly/shorten?version=2.0.1&format=xml&login=%#&apiKey=%#&longUrl=%#",
#"myappname",
#"myappidentifier",
longURL];
I just tried using the bit.ly REST API to create a short url and the URL returned works as expected, see below. It looks like the prior answer suggesting encoding was on target, and standard url encoding (percent encoding, such as http://meyerweb.com/eric/tools/dencoder/) seems to do the trick.
This call (with proper API key):
https://api-ssl.bitly.com/v3/shorten?login=georiot&apiKey=R_MY_API_KEY_HERE&longUrl=http%3A%2F%2Ftarget.georiot.com%2FProxy.ashx%3Fgrid%3D64%26id%3D8i%2FET44NjHw%26offerid%3D146261%26type%3D3%26subid%3D0%26tmpid%3D1826%26RD_PARM1%3Dhttp%3A%2F%2Fitunes.apple.com%2Fus%2Falbum%2Fmetallica%2Fid278116714%3Fuo%3D4%26partnerId%3D30%2F&format=json
Returned:
{ "status_code": 200, "status_txt": "OK", "data": { "long_url": "http://target.georiot.com/Proxy.ashx?grid=64&id=8i/ET44NjHw&offerid=146261&type=3&subid=0&tmpid=1826&RD_PARM1=http://itunes.apple.com/us/album/metallica/id278116714?uo=4&partnerId=30/", "url": "http://bit.ly/zR6uzb", "hash": "zR6uzb", "global_hash": "wFpgG2", "new_hash": 1 } }
The result url works as expected (after removing the escape /'s): http:\bit.ly\zR6uzb
At GeoRiot, we have also recently added a new integrated url shortener which might be of interest to you, however we haven't exposed an API for it quite yet. If you are interested in giving this a shot when we have it available, please let us know. The big benefit here is that the extra redirect between bit.ly and georiot would be removed, speeding up the response time for your users quite a bit.
Anyway, its been a while since the original post, so hopefully you got this figured out. If not let us know and we'll help where we can!

Resources