What's the right way to base64 Encoding in Cococa? - objective-c

I'm enconding this data with this line:
NSString *authString = [[[NSString stringWithFormat:#"%#:%#", email, password] dataUsingEncoding:NSUTF8StringEncoding] base64Encoding];
for a basic HTTP Authentication
It works quite perfect but i'm getting this warning:
warning: 'NSData' may not respond to '-base64Encoding'
is there other way for encoding or how do i remove this warning?

The warning is correct: NSData does not respond to that message. As you can see in the documentation, NSData does not implement base-64 encoding and decoding.
You'll need to either use OpenSSL's BIO API to do the job, or use a third-party framework or library that wraps that (or a separate encoder/decoder) in an easy Cocoa API. A Google search for “Cocoa Base64” will turn up some options.

Related

What is the correct way of sending large file through HTTP POST, without loading the whole file into ram?

I'm currently working on an application for uploading large video files from the iPhone to a webservice through simple http post. As of right now, I build an NSURLRequest and preload all of the video file data before loading the request. This naturally eats a ton of ram if the file is considerably big, in some cases it's not even possible.
So basically my question is: Is there a correct way of streaming the data or loading it in chunks without applying any modifications to the webserver?
Thanks.
EDIT for clarification: I am searching for a way to stream large multipart/form data FROM the iPhone TO a webserver. Not the other way arround.
EDIT after accepting answer: I just found out that apple has some nifty source code written for this exact purpose and it shows appending additional data to the post not just the big file itself. Incase anyone ever needs it: SimpleURLConnections - PostController.m
Yet another EDIT: While using that piece of source code from apple I encountered a very stupid and ugly problem that even wireshark couldn't help me debug. Some webservers don't understand the boundary string when it's declared in between quotes (like in apples example). I had problems with it on Apache Tomcat and removing the quotes worked just wonderful.
You can use NSInputStream on NSMutableURLRequest. For example:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:uploadURL];
NSInputStream *stream = [[NSInputStream alloc] initWithFileAtPath:filePath];
[request setHTTPBodyStream:stream];
[request setHTTPMethod:#"POST"];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSLog(#"Finished with status code: %i", [(NSHTTPURLResponse *)response statusCode]);
}];
You can use a NSInputStream to provide the data to post via -[NSMutableURLRequest setHTTPBodyStream:]. This could be an input stream that reads from a file. You might need to implement the connection:needNewBodyStream: method in your URL connection delegate to provide a new, unopened stream in case the system needs to retransmit the data.
One way to do this is to use an asynchronous NSInputStream in concert with a file. When the asynchronous connection asks you to provide more data, you read in the data from a file. You have a few ways to do this:
UNIX/BSD interface. use open (or fopen), malloc, read, and create a NSData object from the malloced data
use the above with mmap() if you know it
use the Foundation class NSFileHandle APIs to do more or less the same using ObjectiveC
You can read up on streams in the 'Stream Programming Guide'. If this doesn't work for you there are lots of open source projects that can upload files, for instance MKNetworkKit

Returning two strings from php to ios

I'm creating an app that gets some values from a mysql database via php.
I've gone as far as returning a string that's echoed via php and using it in objective C.
Here's what I have so far:
NSString * strURL = [NSString stringWithFormat:#"http://localhost/search.php?name=%#",name];
NSData * dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
NSString * result = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
NSLog(#"%#", result);
Is it possible to return 2 different strings from php and using them separately in xcode or do I have to make 2 different calls to the php file?
Thank you very much for your help!
Great start!
Consider using some structured way to return data from PHP. One easy format that you can learn, which will help with other API integration later, would be JSON.
Apple ships some simple code to to the conversion in iOS5 with NSJSONSerialization
On the PHP side, play around with json_encode. You can pass in an indexed array, for example, which will give you an NSArray on the iOS side.
Some more examples for the iOS side:
How to use NSJSONSerialization

Cocoa HTTP PUT with content-range

Is it possible to use an NSURLConnection/NSURLRequest combination to send a PUT request to a server with a Content-Range header? By that I mean I want to resume an upload to the server which can accept a byte range in the request to resume the upload.
I see you can set an NSInputStream as the request body so I figured that I could subclass that and override the the open/seek functions and set the request header but it seems to call on undocumented selectors and break the implementation.
I'm sure I could do this with CFNetwork but it just seems like there must be a way to do it with the higher level APIs.
Any ideas on where to start?
EDIT:
To answer my own question, this is indeed possible after reading a blog [http://bjhomer.blogspot.com/2011/04/subclassing-nsinputstream.html] which details the undocumented callbacks which relate to CFStream. Once those are implemented I can call the following in the open callback to skip ahead:
CFReadStreamSetProperty((CFReadStreamRef)parentStream, kCFStreamPropertyFileCurrentOffset, (CFNumberRef)[NSNumber numberWithUnsignedLongLong:streamOffset]);
Thanks,
J
I think the server needs to supports put method combines with range but this will be the way to do it with high level Objective-C API
NSURL *URL = [NSURL URLWithString:strURL];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:URL];
NSString *range = [NSString stringWithFormat:#"bytes=%lld-%lld",bytesUploaded,uploadSize];
[urlRequest addValue:range forHTTPHeaderField:#"Range"];
[urlRequest setHTTPMethod:#"PUT"];
self.connection = [NSURLConnection connectionWithRequest:urlRequest delegate:self];
Cheers
First, if you want to do fancy work with HTTP, I typically recommend ASIHTTPRequest. It's solid stuff that simplifies a lot of more complicated HTTP problems. It's not really needed for setting a simple header, but if you're starting to build something more complex, it can be nice to move over to ASI sooner rather than later.
With an NSMutableURLRequest, you can set any header you want using addValue:forHTTPHeaderField:. You can use that to set your Content-Range.
Like I posted in my comment, you can facilitate what you want without dropping down to the CoreFoundation level:
As NSInputStream inherits NSStream, it is possible to prepare the stream as follows:
NSNumber *streamOffset = [NSNumber numberWithUnsignedInteger:lastOffset];
[inputStream setProperty:streamOffset forKey: NSStreamFileCurrentOffsetKey];
(Assuming lastOffset is an NSUInteger representation of your last file offset in bytes and inputStream is the stream you want to set as the request's HTTPBodyStream.)

ios read content from private network address

I need to read a file that come for example:
\\192.168.0.1\Folder\Readme.txt
how can I read this file from my app into the iPhone
NSString *pathToTextFile;
NSError *readError;
NSString *fileData = [NSString stringWithContentsOfFile:pathToTextFile
encoding:NSUTF8StringEncoding
error:*readError]
NSLog(#"here is your file as string = %#",fileData);
I think in this case you can use a library like ASIHTTP. Link
It should be possible to download the file into a NSString object, and then store this object into a file.
[nsStringObject writeToFile:pathToFile atomically:YES encoding:stringEncoding error:errorHandler];
As you suggest in your question, you need to access your file over SMB protocol (samba or windows share). I don't think iOS supports smb out of the box, however, i stumbled across tango library on github some time ago. The library claims to be a SMB/CIFS implementation for iOS, so i guess you might give it a try.

Send data from an iPhone to a Web service

I'm developing an iPad application in which a user fills in their details and presses a submit button, which sends the information to a specific Web server (which will later be viewed by a person)
As far as protocols for Web services are concerned, I know JSON and XML. Are there any other protocols that I should be looking into? (or perhaps by a different method completely)
I'd be very grateful for any help.
If you just want to send text info to server you can try this code:
NSString *textdata = [YourTextField text];
NSString *anotherTextdata = [YourAnotherTextField text];
NSString *urlpath;
urlpath = [#"http://yoursiteapiurl.com/" stringByAppendingString:#"yourserverfile.php?textdata="];
urlpath = [urlpath stringByAppendingString:textdata];
urlpath = [urlpath stringByAppendingString:#"&anotherTextData="];
urlpath = [urlpath stringByAppendingString:anotherTextdata];
NSURL *url=[[NSURL alloc] initWithString:[urlpath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSString *a = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
The variable a will have the response of this URL. The server could send XML and then you can parse that XML using any XML parsing technique.
you can use tbxml for it, its very easy to implement. Follow the link
http://www.tbxml.co.uk/TBXML/TBXML_Free.html
If sending the data over HTTP is an option, I would recommend you look into the excellent ASIHTTPRequest library. As for encoding, I've found the json-framework library to be good.
Use AFNetworking for this.
AFNetworking is smart enough to load and process structured data over the network, as well as plain old HTTP requests. In particular, it supports JSON, XML and Property Lists (plists).