Objective-c URL encode Cloudstack [duplicate] - objective-c

This question already has answers here:
Objective-C and Swift URL encoding
(13 answers)
Closed 9 years ago.
I am working on an IOS application that needs to communicate with an API (CloudStack). The API requires that each request is signed.
I need to URL encode the parameters and create an HMAC SHA1 hash. Everything works fine until I pass an parameter that contains an plus sign or an colon.
So I guess it is the URL encoding part of my application that isn't working correct. I've searched several sites and tried the provided solutions but without any results.
One of the API specifications is that all the spaces needs to be encoded as "%20" rather than "+".
The API signing guide: http://cloudstack.apache.org/docs/en-US/Apache_CloudStack/4.1.0/html/Developers_Guide/signing-api-requests.html
Currently I am using the following code to URL encode the URL:
-(NSString *)urlenc:(NSString *)val
{
NSString *result = [(NSString *)val stringByReplacingOccurrencesOfString:#"+" withString:#" "];
result = [result stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
return result;
}
I call the method like this:
[self urlenc#"2014-01-20T14:02:48+0100"]

In your case the problem probably is both the "+" and ":" character that stringByAddingPercentEscapesUsingEncoding does not encode.
You need to use an encoder that supports more characters, see this SO answer for more complete information.
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding encodes 14 characrters:
`#%^{}[]|\"<> plus the space character as percent escaped.
Here is sample code (iOS7 and above, otherwise see this SO answer):
You may need to change the characters that are encoded.
NSString *testString = #"2014-01-20T14:02:48+0100";
NSString *encodedString1 = [testString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"encodedString1: %#", encodedString1);
NSString *charactersToEscape = #"!*'();:#&=+$,/?%#[]\" ";
NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:charactersToEscape] invertedSet];
NSString *encodedString2 = [testString stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
NSLog(#"encodedString2: %#", encodedString2);
NSLog output:
encodedString1: 2014-01-20T14:02:48+0100
encodedString2: 2014-01-20T14%3A02%3A48%2B0100

Related

NSURL: Escape Backslash using NSCharacterSet

This may be a duplicate question, but I have checked all over and can't find a working answer for iOS9. -stringByAddingPercentEscapesUsingEncoding has been deprecated. I need to use -stringByAddingPercentEncodingWithAllowedCharacters
Below is the string that needs the backslashes escaped so that the API can authenticate the session and return a response.
NSString *base = #"http://domain.com/interface/?end=imember";
NSCharacterSet *set = [NSCharacterSet URLQueryAllowedCharacterSet];
NSString *key = [#"&client_key=KOB3N6KX9JXF2MRPO5U.BRFYM7TYVE\/16KIJVXZA6R7H\/1LD1K\/JYIYG7IZP2HA7NUYOVNT3CJG==&token=SGD7E9B29TQ.8HIITZ37XW3GLK5OGLZNLCDM=" stringByAddingPercentEncodingWithAllowedCharacters:set];
The standard URL Character sets don't escape the backslashes, I have tried them all:
URLUserAllowedCharacterSet
URLPasswordAllowedCharacterSet
URLHostAllowedCharacterSet
URLPathAllowedCharacterSet
URLQueryAllowedCharacterSet
URLFragmentAllowedCharacterSet
Please if someone could assist, I am rather new to development. Is it possible to create a custom allowed set which includes the backslash?
EDIT:
This is what the url should look like:
http://domain.com/interface/?end=imember&client_key=KOB3N6KX9JXF2MRPO5U.BRFYM7TYVE\/16KIJVXZA6R7H\/1LD1K\/JYIYG7IZP2HA7NUYOVNT3CJG==&token=SGD7E9B29TQ.8HIITZ37XW3GLK5OGLZNLCDM=
The exact solution for you answer is below.I got it from Zaph's answer.That is the better answer than other answer.
NSString *unescaped = #"http://domain.com/interface/?end=imember"];
NSString *escapedString = [unescaped stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
NSLog(#"escapedString: %#", escapedString);
URL Encoding Character Sets are
URLFragmentAllowedCharacterSet "#%<>[\]^`{|}
URLHostAllowedCharacterSet "#%/<>?#\^`{|}
URLPasswordAllowedCharacterSet "#%/:<>?#[\]^`{|}
URLPathAllowedCharacterSet "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet "#%<>[\]^`{|}
URLUserAllowedCharacterSet "#%/:<>?#[\]^`

Objective-C Base64 decoding returns nil

I have downloaded and added the following category into my project: https://github.com/nicklockwood/Base64
NSString *secret = #"7pgj8Dm6";
NSString *decodedSecret = [secret base64DecodedString];
NSLog(#"decoded Secret = %#", decodedSecret);
This however, always turns out to be nil. What is happening here ?
I hope it will helpful to you
NSString *decodeString = #"Raja";
Encode String
NSData *encodeData = [decodeString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [encodeData base64EncodedStringWithOptions:0];
DLog(#"Encode String Value: %#", base64String);
Decode String
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
NSString *decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
DLog(#"Decode String Value: %#", base64String);
Thanks
I've failed to relax iOS native base64 decoder enough with NSDataBase64DecodingIgnoreUnknownCharacters to process jwt payloads
so I had to revert to a 3rdparty MF_Base64Codec
Sadly you might want to consider doing the 3rdparty route
until Apple will have fixed the bug or relaxed the decoder further to
accept what it currently considers crap input
Your input 7pgj8Dm6is an Invalid base64 encoded string. So the result will be always nil since the method base64DecodedString used only for UTF8 encoding.
As of iOS 7 and Mac OS 10.9, this library is not longer needed.
You can use initWithBase64EncodedString:options:
The default implementation of this method will reject non-alphabet characters, including line break characters. To support different encodings and ignore non-alphabet characters, specify an options value of NSDataBase64DecodingIgnoreUnknownCharacters.

-[NSString stringByAppendingPathComponent:] or just -[NSString stringByAppendingFormat:] for NSStrings for NSURLs?

When calling +[NSURL URLWithString:] I have two options for building my URLs:
[[#"http://example.com" stringByAppendingPathComponent:#"foo"] stringByAppendingPathComponent:#"bar"]
or
[#"http://example.com" stringByAppendingFormat:#"/%#/%#",#"foo",#"bar"];
-[NSString stringByAppendingPathComponent:] seems like the more correct answer, but do I lose anything using -[NSString stringByAppendingFormat:] besides handling double-slashes as in the following case?
// http://example.com/foo/bar
[[#"http://example.com/" stringByAppendingPathComponent:#"/foo"] stringByAppendingPathComponent:#"bar"]
// http://example.com//foo/bar oops!
[#"http://example.com/" stringByAppendingFormat:#"/%#/%#",#"foo",#"bar"];
As you're working with URLS, you should use the NSURL methods:
NSURL * url = [NSURL URLWithString: #"http://example.com"];
url = [[url URLByAppendingPathComponent:#"foo"] URLByAppendingPathComponent:#"bar"]
or in Swift
var url = NSURL.URLWithString("http://example.com")
url = url.URLByAppendingPathComponent("foo").URLByAppendingPathComponent(".bar")
I just ran into a problem with stringByAppendingPathComponent: it removes double slashes everywhere!:
NSString* string1 = [[self baseURL] stringByAppendingString:partial];
NSString* string2 = [[self baseURL] stringByAppendingPathComponent:partial];
NSLog(#"string1 is %s", [string1 UTF8String]);
NSLog(#"string2 is %s", [string2 UTF8String]);
for a baseURl of https://blah.com
and a partial of /moreblah
Produces the two strings:
2012-09-07 14:02:09.724 myapp string1 is https://blah.com/moreblah
2012-09-07 14:02:09.749 myapp string2 is https:/blah.com/moreblah
But for some reason my calls to blah.com to get resource work with the single slash. But it indicates to me that stringByAppendingPathComponent is for paths - NOT urls.
This is on iPhone 4 hardware running iOS 5.1.
I outputted the UTF8 strings as I wanted to make sure that the debugger output I was seeing was believable.
So I guess I am saying - don't use path stuff on URLs, use some home brew or a library.
How about:
[NSString pathWithComponents:#[#"http://example.com", #"foo", #"bar"]]
As pointed out in the comments a / gets stripped from protocol when using the methods from NSPathUtitlites.h, so that is the obvious downfall. The solution I could come up with that is closest to the original one I posted is:
[#[ #"http://example.com", #"foo", #"bar" ] componentsJoinedByString:#"/"]
You will just need to use a literal for the path separator which is what NSString does.
NSString represents paths generically with ‘/’ as the path separator
and ‘.’ as the extension separator.
the point of stringByAppendingPathComponent is to handle double slashes, however, you could do something like:
[[#"http://example.com/" stringByAppendingPathComponent:[NSString stringWithFormat:#"%#/%#", #"foo", #"bar"]]

How to encode or decode URL in objective-c

Is there something like
+(NSString *) URLencode: (NSString *) someString
+(NSString *) URLdecode: (NSString *) someString
If so, how to implement it?
Note to downvoters. This is NOT a simple question. I need something that can comprehensively do this. For example:
NSString * test = #"汉字马拉松是";
NSString * encoded = [test stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
PO(encoded);
PO(test);
Will yield the following:
2012-06-04 16:04:22.709 BadgerNew[2266:17003] <0xcd890 GrabClass.m:(930)> encoded (null)
2012-06-04 16:04:22.710 BadgerNew[2266:17003] <0xcd890 GrabClass.m:(931)> test 汉字马拉松是
I want my encoding to be able to URL encode EVERYTHING including japanese language, etc.
So I want encoded to contain something along %E6%B1%89%E5%AD%97%E9%A9%AC%E6%8B%89%E6%9D%BE%E6%98%AF
There are 2 different methods in http://mobiledevelopertips.com/networking/a-better-url-encoding-method.html
None are good enough.
I need to be able to encode ALL strings, including japanese/chinese characters.
Update: I followed H2CO3 answer and do this:
NSString * test = #"汉字马拉松是";
NSString * encoded = [test stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
PO(encoded);
PO(test);
PO(encoded);
Work as expected.
You probably want to take a look at the stringByAddingPercentEscapesUsingEncoding and stringByReplacingPercentEscapesUsingEncoding methods.
Encoding example (using ASCII):
NSString* encodedString =
[originalString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
Decoding example (using ASCII):
NSString* originalString =
[encodedString stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
EDIT:
If this doesn't give the desired results try replacing NSASCIIStringEncoding with NSUTF8StringEncoding.
Also you might want to try the variant of above methods :
NSString * encodedString =
(NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)originalString,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8 );
Which will work better in some cases
It's natural that Chinese and Japanese characters don't work with ASCII string encoding. If you try to escape the string by Apple's methods, which you definitely should to avoid code duplication, store the result as a Unicode string. Use one of the following encodings:
NSUTF8StringEncoding
NSUTF16StringEncoding
NSShiftJISStringEncoding (not Unicode, Japanese-specific)

How to URL Decode in iOS - Objective C

The stringByReplacingPercentEscapesUsingEncoding method is not working properly as it's not decoding special symbols that dont start with a % character, i.e., the + character. Does anyone know of a better method to do this in iOS?
Here's what I'm currently using:
NSString *path = [#"path+with+spaces"
stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
And here's an example of the output:
path+with+spaces
NSString *path = [[#"path+with+spaces"
stringByReplacingOccurrencesOfString:#"+" withString:#" "]
stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
Note that the plus-for-space substitution is only used in application/x-www-form-urlencoded data - the query string part of a URL, or the body of a POST request.
// Decode a percent escape encoded string.
- (NSString*) decodeFromPercentEscapeString:(NSString *) string {
return (__bridge NSString *) CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL,
(__bridge CFStringRef) string,
CFSTR(""),
kCFStringEncodingUTF8);
}
http://cybersam.com/ios-dev/proper-url-percent-encoding-in-ios
This seems to be the preferred way because...
"Apparently" this is a "bug" apple is aware of, but they haven't done anything about it yet... ( http://simonwoodside.com/weblog/2009/4/22/how_to_really_url_encode/ )
If you are trying to replace the plus sign with percent escapes, perform a string replacement from "+" to " " (single space). Then use stringByAddingPercentEscapesUsingEncoding: to add the percent escapes.
The plus sign is one of many reserved URL characters that is never encoded.
(stringByReplacingPercentEscapesUsingEncoding: decodes the percent escapes)
swift 2 :
extension String {
func uriDecodedString() -> String? {
return self.stringByReplacingOccurrencesOfString("+", withString: " ").stringByRemovingPercentEncoding
}
}
Also you can use the PercentEncoder library from Cocoapods.
Swift 4
Include the library to your Podfile:
pod PercentEncoder
Import the library PercentEncoder
import PercentEncoder
class ViewController{
...
}
Replace the "+" character by "%20" and use the method "ped_decodeURI"
"path+with+spaces".replacingOccurrences(of: "+", with: "%20").ped_decodeURI()
It will return "path with spaces"
Here the link for reference: https://cocoapods.org/pods/PercentEncoder