Does anyone know whats the issue with this code - iphone

-(NSData *) decryptData:(NSData *) Data
{
NSData *iv;
NSData *salt;
NSError *error;
NSData *stringData = Data;
NSInputStream *inpStream = [[NSInputStream alloc] initWithData:stringData];
bool IVData = [inpStream _CMgetData:&iv maxLength:kAlgorithmIVSize error:&error];
bool SaltData = [inpStream _CMgetData:&salt maxLength:kPBKDFSaltSize error:&error];
}
#implementation NSInputStream (Data)
-(BOOL)_CMgetData:(NSData **)data maxLength:(NSUInteger)maxLength error:(NSError **)error {
NSMutableData *buffer = [NSMutableData dataWithLength:maxLength];
if ([self read:buffer.mutableBytes maxLength:maxLength] < 0)
{
if (error)
{
*error = [self streamError];
NSLog(#"CMgetData Error!!");
return NO;
}
}
*data = buffer;
NSLog(#"%#", buffer);
return YES;
}
#end
I always get "CMgetData Error!!" Does anyone know why this issue comming.. I believe i passed all the parameters correctly. is that right?? Please help
Thanks in advance Any help??

Any stream must be opened before you can read from or write to it:
NSInputStream *inpStream = [[NSInputStream alloc] initWithData:stringData];
[inpStream open];
// now you can read from the stream.

In decrypt data you create a pointer to an NSError. This pointer gets an adress somewhere in memory and you pass that adress to _CMgetData. That adress will always evaluate to true, therefore (when read returns a negative number) you always enter the if(error) block.
You probably want to check whether your call to read:maxLength: had an error, as it returns with a negative number. Check the specs of that function how to retrieve error information.

For non-ARC code, local variables, particularly NSError instances that you are later checking for non-nil status, must be initialised to nil, otherwise they will hold garbage. Declare as:
NSError *error = nil;
Instead.

Related

iOS parsing JSON from static library returning null

I'm trying to test out using static libraries, and am calling this method (which is in the static library)
-(NSMutableDictionary *)parseJSONfromURL:(NSURL *)url{
__strong NSMutableDictionary *json;
[self.delegate isParsing:(url != nil)];
if (url == nil) {
[NSException raise:NSArgumentDomain format:#"The passed url argument cannot be nil"];
}
NSError *err;
json = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:url] options:NSJSONReadingMutableLeaves error:&err];
if (err) {
[json setObject:err forKey:#"error"];
}
while (json == nil) {
NSLog(#"waiting...");
}
[self.delegate isParsing:NO];
[self.delegate didFinishParsing:(json != nil)];
return json;
}
I would expect the while loop to be infinite since json is returning null, but the delegate method didFinishParsing gets sent, meaning it isn't null.
like this (ACParser is a class in the library)
ACParser *p = [[ACParser alloc] initWithDelegate:self];
dictionary = [p parseJSONfromURL:[NSURL URLWithString:#"http://www.a-cstudios.com/text.json"]];
dictionary is declared like this
__strong NSMutableDictionary *dictionary;
the JSON at that URL is very simple
{
"text" : "testing"
}
however, every time this is called, in the delegate method didFinishParsing:, logging dictionary returns (null). What am I doing wrong here? Is it because I'm calling it from a static library?
Try adding this:
NSLog(#"%#", [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url]] options:NSJSONReadingAllowFragments error:nil]);
in there and see if it prints out your expected JSON. If it doesnt, your URL is wrong. If it does, then your data isnt being retained. Try instantiating your json variable like this:
NSMutableDictionary *json = [NSMutableDictionary dictionaryWithDictionary:[NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfURL:url] options:NSJSONReadingMutableLeaves error:&err]];
"json" within "parseJSONfromURL" is autoreleased / out of scope as soon as that method returns so it never has a chance to get assigned to your strong "dictionary" property.
That's why you are seeing NULL.
Try setting the property within your parseJSONfromURL method and see if that works, or create a non-autoreleased dictionary and return that.

Xcode, ensure codes after blocks run later for NSURLConnection asynchronous request

Hi there: I have been writing an iOS program which uses many http queries to the backend rails server, and hence there are tons of codes like below. In this case, it is updating a UITableView:
//making requests before this...
NSOperationQueue* queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse* response, NSData* data, NSError* error)
{
NSLog(#"Request sent!");
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
NSLog(#"Response code: %d", [httpResponse statusCode]);
if ([data length] > 0 && error == nil){
NSLog(#"%lu bytes of data was returned.", (unsigned long)[data length]); }
else if ([data length] == 0 &&
error == nil){
NSLog(#"No data was returned.");
}
else if (error != nil){
NSLog(#"Error happened = %#", error); }
id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
if (jsonObject != nil && error == nil){
NSLog(#"Successfully deserialized...");
if ([jsonObject isKindOfClass:[NSDictionary class]]){
NSDictionary *deserializedDictionary = (NSDictionary *)jsonObject;
NSLog(#"Dersialized JSON Dictionary = %#", deserializedDictionary);
[listOfItems addObject:deserializedDictionary];
}
else if ([jsonObject isKindOfClass:[NSArray class]]){
NSArray *deserializedArray = (NSArray *)jsonObject;
NSLog(#"Dersialized JSON Array = %#", deserializedArray);
[listOfItems addObjectsFromArray:deserializedArray];
}
else {
/* Some other object was returned. We don't know how to deal
with this situation as the deserializer only returns dictionaries
or arrays */ }
}
else if (error != nil){
NSLog(#"An error happened while deserializing the JSON data., Domain: %#, Code: %d", [error domain], [error code]);
}
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
}];
//the place where never runs
NSLog(#"End of function.");
Here is the problem: the last line gets executed usually before the code block. How do I ensure that the code after block actually runs after the block?
I am aware that the block uses some other threads, which is why I use performSelectorOnMainThread function instead of a direct call of [self.tableView reloadData]. But if I want to do something else afterward, how am I supposed to do?
Also, can anyone show some better ways to do this? I am trying to figure out the best way to make massive calls to the backend. There are several ways to make asynchronous requests, including this block way and another old-fashioned way invoking delegate classes. In the progress to refactor the codes, I also tried to create my own delegate class and let other classes invoke that, but it is difficult to identify the correct behaviour of callback functions for which connection's data it returns, especially for classes that use multiple functions to call different requests. And I don't want to use synchronous calls.
Thanks very much for any answers. Also welcome to point out any bugs in the code.
You can using dispatch group
Sample code:
- (void)doSomethingAndWait {
// synchronous method
// called in main thread is not good idea.
NSAssert(! [NSThread isMainThread], #"this method can't run in main thread.");
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
//making requests before this...
NSOperationQueue* queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse* response, NSData* data, NSError* error)
{
// your work here.
dispatch_group_leave(group);
}];
// wait for block finished
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
//will call until block is finished.
NSLog(#"End of function.");
}
And to call that method, you need avoid call it in main thread.
you should call it like this
dispatch_queue_t queue = dispatch_queue_create("com.COMPANYNAME.APPNAME.TASKNAME", NULL);
dispatch_async(queue, ^{
[self doSomethingAndWait];
});

how to pass NSCachedURLResponse to Parser delegates?

I am currently downloading and caching several different data sets from my server. However I am swapping all of my code from ASI over to NSURLConneciton stuff. and I am at the point where I am ready to pass my caches over to my parser delegates however they accept a NSData type as a parameter
- (void)startTheParsingProcess:(NSData *)parserData
where my cache is of type
NSCachedURLResponse
as you can see here
-(NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
if (dataSetToParse == #"a"){
NSCachedURLResponse *aCachedResponse = cachedResponse;
aCachedResponse = nil;
NSDictionary *newUserInfo;
newUserInfo = [NSDictionary dictionaryWithObject:[NSDate date] forKey:#"Cached Date"];
aCachedResponse = [[NSCachedURLResponse alloc] initWithResponse:[cachedResponse response] data:[cachedResponse data] userInfo:newUserInfo storagePolicy:[cachedResponse storagePolicy]];
NSLog(#"%#", aCachedResponse);
return aCachedResponse;
}
if (dataSetToParse == #"b"){
NSCachedURLResponse *bCachedResponse = cachedResponse;
bCachedResponse = nil;
NSDictionary *newUserInfo;
newUserInfo = [NSDictionary dictionaryWithObject:[NSDate date] forKey:#"Cached Date"];
bCachedResponse = [[NSCachedURLResponse alloc] initWithResponse:[cachedResponse response] data:[cachedResponse data] userInfo:newUserInfo storagePolicy:[cachedResponse storagePolicy]];
NSLog(#"%#", bCachedResponse);
return bCachedResponse;
}
return nil;
}
any example code would be helpfull thanks or just pointing me in the right direction :)
I am looking at the NSCachedURLResponse definition in the apple docs, and it says that NSCachedURLResponse has the data that I want I'm just not sure how I can get to it... to use with my parser delegates.
You mean something like that?
NSCachedURLResponse *cachedResponse = nil; // Put your code to get real response
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)[cachedResponse response];
NSData *responseData = [httpResponse data];
NSCachedURLResponse has also a direct method data, but I cannot test if it's the same result as the code above.
Cache suggestion
I see that you have your own methods that deal with caching. I would suggest subclassing the NSURLCache, if you need to modify caching and, say, add an offline mode. If you subclass it and implement some methods, like (but not limited to):
– cachedResponseForRequest:
– storeCachedResponse:forRequest:
life may become easier for you. You would just set global app cache in application delegate through [NSURLCache setSharedURLCache:[CustomURLCache new]]; call.
Then all your standard NSURL-whatever classes would behave as if they work with system cache, and you normally won't have to deal with direct calls to get or store the cache, the system would call them automatically.

Dictionary Getting Released?

Currently, I have a class that is parsing XML and sending the dictionary that the XML is parsed to to a view controller.
Here is a snippet of the code that sends the dictionary to the other class (where "response" is the dictionary):
if ([elementName isEqualToString:#"SessionData"])
{
// We reached the end of the XML document
// dumps dictionary into log
NSLog(#"Dump:%#", [response description]);
// sends dictionary to the VC
CardSetupViewController *setup = [[CardSetupViewController alloc]init];
setup.response = self.response;
//checks
NSLog(#"%# lololololol", [setup.response description]); //THIS WORKS FINE!!
return;
}
At that point, the code works fine. That NSLog marked with //THIS WORKS FINE!! works... obviously. Here is the method in the ViewController:
- (BOOL)authorize //this
{
AddCard *addCard = [[AddCard alloc]init];
ServerConnection *connection = [[ServerConnection alloc]init];
//XMLParser *xmlParser = [[XMLParser alloc]initXMLParser];
//serverReturn posts the data and is the ACTUAL server response in NSData form
NSData *serverReturn = [connection postData:[addCard textBoxToXml:
[self nameOnCardGet]:
[self ccNumGet]:
[self expMoGet]:
[self expYrGet]:
[self cvvGet]:
[self zipGet]:
[self nickNameGet]:
[self pinGet]]];
//This takes the information from the server and parses it to "response"
//Creates and inits NSXMLParser Object
NSXMLParser *nsXmlparser = [[NSXMLParser alloc] initWithData:serverReturn];
//Create and init our delegate
XMLParser *parser = [[XMLParser alloc] initXMLParser];
//set delegate
[nsXmlparser setDelegate:(id <NSXMLParserDelegate>) parser];
//initiates self.response THIS MAY NOT BE NEEDED
//response = [[NSMutableDictionary alloc]init];
//parsing
BOOL success = [nsXmlparser parse];
//error catch testing
if (success) {
NSLog(#"No errors");
}
else {
NSLog(#"Error parsing document!");
}
//dump
NSLog(#"ZOMG CHECK DIS OUT%#", [response description]);
return NO;
}
Basically, the NSLog that states "ZOMG CHECK DIS OUT" is returning (null) and I can't figure out why. No compilation errors, it is a property/synthesize as well. Any ideas?
Thanks in advance. Oh, and please excuse my NSLog comments. I had to differentiate from different parts of the code, and I was in a good mood.
Edit: I am using Automatic Reference Counting. Don't worry, nothing is leaking.
In your first code block, you generate a CardSetupViewController and then leak it. It is unrelated to whatever object is running the second code block. I assume that your second view controller is from your NIB?
Note that you're also leaking your NSXMLParser.
Your [response description], whatever that is, is probably an autoreleased object that gets released before ZOMG CHECK DIS OUT. Retain it and see if that works. Don't forget to release it when you're done with it.

Reading Certificates on iOS Problem

I am trying to read certificates from various URLs in iOS. My code however is not working well - the array that should return the information I need always returns null.
What am I missing?
- (void)findCertificate:(NSString *)url
{
NSInputStream*input = [[NSInputStream inputStreamWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"https://store.writeitstudios.com"]]] retain];
[input setDelegate:self];
[input scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[input open];
NSLog(#"Status: %i",[input streamStatus]);
}
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
NSLog(#"handle Event: %i",eventCode);
if (eventCode == NSStreamStatusOpen)
{
NSArray *certificates = (NSArray*)CFReadStreamCopyProperty((CFReadStreamRef)aStream, kCFStreamPropertySSLPeerCertificates);
NSLog(#"Certs: %#",CFReadStreamCopyProperty((CFReadStreamRef)aStream, kCFStreamPropertySSLPeerCertificates));
if ([certificates count] > 0) {
SecCertificateRef certificate = (SecCertificateRef)[certificates objectAtIndex:0];
NSString *description = (NSString*)SecCertificateCopySubjectSummary(certificate);
NSData *data = (NSData *)SecCertificateCopyData(certificate);
NSLog(#"Description: %#",description);
}
}
}
And yes, I am aware that I am leaking memory. This is just a snippet.
Let me explain what you're doing here and why it's wrong:
You are loading the contents of the URL https://store.writeitstudios.com (i.e. the HTML) synchronously into an NSData (a data buffer). Note that you are not loading any certificates (well, technically NSURL will load them internally, but this code is most definitely not putting them into the NSData)
You are opening an input stream and sticking the data (a bit of HTML, no certificates!) into it.
You have implemented NSStream's delegate method stream:handleEvent: and are attempting to read the kCFStreamPropertySSLPeerCertificates property. This property will be empty since the stream contains only a bit of HTML data, nothing else.
You are casting the empty property to an NSArray.
The loop is not executed because the array is NULL.
Using NSStream/CFStream is not necessary for the task at hand. And most definitely you don't have to go through NSURLConnection first and then through NSStream.
To retrieve SSL server certificates, stick to a simple, asynchronous NSURLConnection and use its delegate methods to access the certificates:
// Method to begin the asynchronous download
- (void)beginCertificateDownload:(NSURL *)url
{
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
}
// NSURLConnection Delegate Methods
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return [[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
// extract the certificates
SecTrustRef trustRef = [[challenge protectionSpace] serverTrust];
CFIndex count = SecTrustGetCertificateCount(trustRef);
for (CFIndex i = 0; i < count; i++) {
SecCertificateRef certRef = SecTrustGetCertificateAtIndex(trustRef, i);
CFStringRef certSummary = SecCertificateCopySubjectSummary(certRef);
NSLog(#"%#", certSummary);
// do whatever you need with the certificates here
// don't forget to copy them if you need to keep them
// around beyond the scope of this method
}
// I'm assuming you're not interested in actually loading the contents of the URL, so cancel
[[challenge sender] cancelAuthenticationChallenge:challenge];
// you'll also want to release the connection object at some point
}