How to use stringWithContentsOfFile:usedEncoding:error: - ios

I've tried to load a file with unknown encoding. This is because I dont always have control over the file that I will load. I assumed that the method stringWithContentsOfFile:usedEncoding:error: will do this and will let me know the file encoding. Unfortunately following code doesn't provide the encoding I want - it always return 0.
NSStringEncoding *encoding = nil;
NSError *error = nil;
NSString *json = [NSString stringWithContentsOfFile:path
usedEncoding:encoding
error:&error];
NSLog(#"\n%lu\n%#",(unsigned long)encoding,error);
It returns content of file, so you may wonder why I need this encoding, well that string is JSON that I want to serialize it into NSDictionary and the dataUsingEncoding: method requires encoding. I tried to pass encoding variable but this throws an error. So I tried fail safe UTF8 encoding and then it worked.
NSData *jsonData = [json dataUsingEncoding:NSUTF8StringEncoding];
So I must using this incorrect as encoding equals to 0 instead of 4 (UTF8). Can someone help me with that?

Try that :
NSStringEncoding encoding;
NSError *error = nil;
NSString *json = [NSString stringWithContentsOfFile:path
usedEncoding:&encoding
error:&error];
NSLog(#"\n%lu\n%#",(unsigned long)encoding,error);
To be clearer, you can't receive the encoding value in your pointer, you need to give a plain NSStringEncoding address

Since you are not aware of the encoding of the file, I will suggest you to see this link.
Its basically String Programming Guide which will let you know in depth what to do.
Below is the snapshot for which you are looking into:
Hope this will help you. Happy coding :)

Related

How do I urlencode this NSString that contains a JSON inside it?

I have the following json string that should be sent to the backend
{
id = "MU_200255802";
keywords = (
Talk,
games,
meetup,
time,
meet,
"Time for Another Game"
);
}
So before this JSON I have the java servlet URL something like
http://....net/servletName?
How should I urlencode the json string and the url because even after trying several options, I keep getting bad url as an error back in the delegate method. What is the right way to do it/
I tried encoding using
NSString *urlStringEncoded = [[NSString stringWithString:urlString] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
and also used other encoding formats too.
Use this to create json string
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:#"Your object" options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
You can use Google Toolbox for Mac, check it out here, https://code.google.com/p/google-toolbox-for-mac/source/checkout
There are Classes named GTMNSString+HTML,GTMNSString+XML,GTMNSString+URLArguments, which contains many encoding methods for you.

Encode JSON data for URL

In iOS, I want to send JSON data in URL to make service call. I tried following code snipped but Encoded URL seems wrong. Because in JSON there is a colon character (:) between key and value and comma character (,) for separation. But, i am not able to encode colon(:) as %3A and comma(,) as %2C
Code Snippet:
- (NSURL *)getEncodedUrl {
// Build dictionnary with parameters
NSString *abc = #"abc";
NSNumber *limitNumber = [NSNumber numberWithInt:2];
NSMutableDictionary *dictionnary = [NSMutableDictionary dictionary];
[dictionnary setObject:limitNumber forKey:#"limit"];
[dictionnary setObject:abc forKey:#"abc"];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionnary options:0 error:&error];
if (!jsonData) {
debug("Json error %#",error);
return nil;
} else {
NSString *JSONString = [[NSString alloc] initWithBytes:[jsonData bytes] length:[jsonData length] encoding:NSUTF8StringEncoding];
debug("Json op %#",JSONString);
NSString* params = [JSONString stringByAddingPercentEscapesUsingEncoding:
NSASCIIStringEncoding];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://baseUrl.com?param=#",params]];
debug("URL = %#",url);
return url;
}
}
OUTPUT:~
URL = http://baseUrl.com?param=%7B%22abc%22:%22abc%22,%22limit%22:2%7D
(Include colon and comma characters)
But I want following o/p:
http://baseUrl.com?param=%7B%22abc%22%3A%22abc%22%2C%22limit%22%3A2%7D
(No colon and comma characters)
Online Encoding-Decoding Site that I am referring as of now.
http://www.url-encode-decode.com/
you can simply use
NSString *url = #"http://baseUrl.com?param=%7B%22abc%22:%22abc%22,%22limit%22:2%7D";
NSString *encodeImgUrl = [url stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
I'd recommend that you send the JSON as POST data instead of the GET that you're using. It'd be more straightforward to package it as MIME data and any encoding you do would be easier to understand.
So you are trying to generate the query portion of a URL here. Colons are a perfectly legitimate character to include in URL queries. I wrote an article covering the intricacies of escaping URL queries in Cocoa:
http://www.mikeabdullah.net/escaping-url-queries-in-cocoa.html
Since you're keen to perform extra escaping, I suggest taking my sample code and extending it to specially ask for : and ; characters to be escaped too.
I made small mistake in API call that is why I am getting wrong result. There is no need to encode colon(:) as %3A and comma(,) as %2C.
One more thing I would like to share with you. You can use base64 string instead of encoding JSON part.

RNCryptor not working with JSON string

Here are my method's to use RNCryptor to encrypt/decrypt a JSON string that I am sending to the web service. I am using a static IV variable which may be bad practice but please don't focus on that. Here is how I'm doing it:
Note: I'm using Matt Gallagher's NSData+Base64 category found here (at bottom of page)
-(NSString*)encryptString:(NSString*)plaintext withKey:(NSString*)key error:(NSError**)error{
NSData *data = [plaintext dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptionKey = [NSData dataFromBase64String:key];
NSData *IV = [NSData dataFromBase64String:ENCRYPTION_IV];
RNCryptorEngine *engine = [[RNCryptorEngine alloc] initWithOperation:kCCEncrypt settings:kRNCryptorAES256Settings key:encryptionKey IV:IV error:error];
[engine addData:data error:error];
NSData *encryptedData = [engine finishWithError:error];
NSString *based64Encrypted = [encryptedData base64EncodedString];
NSLog(#"Encrytped: %#", based64Encrypted);
return based64Encrypted;
}
-(NSString*) decryptString:(NSString*)cipherText withKey:(NSString*)key error:(NSError**)error;{
NSData *data = [NSData dataFromBase64String:cipherText];
NSData *encryptionKey = [NSData dataFromBase64String:key];
NSData *IV = [NSData dataFromBase64String:ENCRYPTION_IV];
RNCryptorEngine *engine = [[RNCryptorEngine alloc] initWithOperation:kCCDecrypt settings:kRNCryptorAES256Settings key:encryptionKey IV:IV error:error];
[engine addData:data error:error];
NSData *decryptedData = [engine finishWithError:error];
NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
NSLog(#"Decrypted: %#", decryptedString);
return decryptedString;
}
When I use a string like hello world it works fine. When I use a string like {"username":"developer","password":"abcdefG*12"} I imagine it hase something to do with the encoding but I really know what to use.
when I encrypt that string I get a base64 string and when I try to decrypt that I get an empty string.
UPDATE
It looks like it's failing because of the : in the json string.
What's weirder is it only fails with the string is in json format, I thought it was the : cause I tried that first but upon further investigation if I broke any of the JSON requirements ,'s {'s }'s it stopped working. It works with the RNEncryptor however so I'm not sure what I'm doing wrong. Either way, I think we may redesign the current flow
UPDATE 2
Here is where I am calling these methods:
NSDictionary *credentials = #{#"username":#"developer",#"password":#"abcdefG*12"};
NSString *jsonString = [ credentials JSONStringWithOptions:JKSerializeOptionNone error:&error];
NSLog(#"json string: %#", jsonString); //OUTPUTS: {"username":"developer","password":"abcdefG*12"}
CCGEncryption *encryptionObject = [[CCGEncryption alloc] init]; //THIS IS THE OBJECT WHERE THE encrypt/decrypt methods are
NSString *encrypted = [encryptionObject encryptString:jsonString withKey:ENCRYPTION_KEY error:&error];
if(error){
NSLog(#"Error:%#", error); //NO ERROR
}
NSString *decrypted = [encryptionObject decryptString:encrypted withKey:ENCRYPTION_KEY error:&error];
if(error){
NSLog(#"Error:%#", error); //NO ERROR
}
NSLog(#"decrypted: %#", decrypted); //OUTPUT: decrypted:
You're not collecting the data returned by addData:. The engine encrypts/decrypts as you go so that you don't have to hold the entire plaintext and ciphertext in memory. It doesn't accumulate the data unless it has to (for padding reasons). I suspect that the tests that are working are of different lengths than the ones that aren't.
You are correct that using a fixed IV is bad practice. If you use the same IV and key in multiple messages, then it is possible for attackers to recover parts of your messages by comparing the ciphertexts. If you are using AES-CBC without a random IV and an HMAC, then your AES is insecure in several ways. That is the problem RNCryptor was built to address and why the data format looks the way it does.
#jbtule is correct that I didn't particularly mean for people to use the engine directly and haven't heavily documented it, but there's no problem using it, and I can document it better to support that. That said, the engine itself is insanely simple; I just created it as a way to share code between the encryptor and decryptor. There's not much reason to use RNCryptor if you're going to bypass most of the security it provides. For the above code, it'd be a lot simpler to just call the one-shot CCCrypt().

Encrypted twitter feed

I'm developing an iOS application , that will take a twits from twitter,
I'm using the following API
https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&count=2&screen_name=TareqAlSuwaidan
The problem are feed in Arabic Language ,
i.e the text feed appears like this
\u0623\u0646\u0643 \u0648\u0627\u0647\u0645
How can i get the real text (or how to encode this to get real text) ?
This is not encrypted, it is unicode. The codes 0600 - 06ff is Arabic. NSString handles unicode.
Here is an example:
NSString *string = #"\u0623\u0646\u0643 \u0648\u0627\u0647\u0645";
NSLog(#"string: '%#'", string);
NSLog output:
string: 'أنك واهم'
The only question is exactly what problem are you seeing, are you getting the Arabic text? Are you using NSJSONSerialization to deserialize the JSON? If so there should be no problem.
Here is an example with the question URL (don't use synchronous requests in production code):
NSURL *url = [NSURL URLWithString:#"https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&count=2&screen_name=TareqAlSuwaidan"];
NSData *data = [NSData dataWithContentsOfURL:url];
NSError *error;
NSArray *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
NSDictionary *object1 = [jsonObject objectAtIndex:0];
NSString *text = [object1 objectForKey:#"text"];
NSLog(#"text: '%#'", text);
NSLog output:
text: '#Naser_Albdya أيدت الثورة السورية منذ بدايتها وارجع لليوتوب واكتب( سوريا السويدان )
Those are Unicode literals. I think all that's needed is to use NSString's stringWithUTF8String: method on the string you have. That should use NSString's native Unicode handling to convert the literals to the actual characters. Example:
NSString *directFromTwitter = [twitterInterface getTweet];
// directFromTwitter contains "\u0623\u0646\u0643 \u0648\u0627\u0647\u0645"
NSString *encodedString = [NSString stringWithUTF8String:[directFromTwitter UTF8String]];
// encodedString contains "أنك واهم", or something like it
The method call inside the conversion call ([directFromTwitter UTF8String]) is to get access to the raw bytes of the string, that are used by stringWithUTF8String. I'm not exactly sure on what those code points come out to, I just relied on Python to do the conversion.

NSJSONSerialization from NSString

Is it possible if I have a NSString and I want to use NSJSONSerialization? How do I do this?
First you will need to convert your NSString to NSData by doing the following
NSData *data = [stringData dataUsingEncoding:NSUTF8StringEncoding];
then simply use the JSONObjectWithData method to convert it to JSON
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
You need to convert your NSString to NSData, at that point you can use the +[NSJSONSerialization JSONObjectWithData:options:error:] method.
NSString * jsonString = YOUR_STRING;
NSData * data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError * error = nil;
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (!json) {
// handle error
}
You can convert your string to NSData by saying:
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
You can then use it with NSJSONSerialization. Note however that NSJSONSerialization is iOS5 only, so you might be better off using a library like TouchJSON or JSONKit, both of which let you work directly with strings anyway, saving you the step of converting to NSData.
I wrote a blog post that demonstrates how to wrap the native iOS JSON class in a general protocol together with an implementation that use the native iOS JSON class.
This approach makes it a lot easier to use the native functionality and reduces the amount of code you have to write. Furthermore, it makes it a lot easier to switch out the native implementation with, say, JSONKit, if the native one would prove to be insufficient.
http://danielsaidi.com/blog/2012/07/04/json-in-ios
The blog post contains all the code you need. Just copy / paste :)
Hope it helps!

Resources