How to modify the cookies of a request during redirect in objective-c? - objective-c

I'm doing a simple login and noticed that during the redirect I only have 2 of the 3 required cookies to get in correctly. I captured the other cookie and put them together but for some reason I can't modify the headers on the fly?
- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSHTTPURLResponse *)response {
NSURL* redirected_url = [request URL];
NSString* querystr = [redirected_url absoluteString];
if (response != nil) {
NSArray* zzzz = [NSHTTPCookie
cookiesWithResponseHeaderFields:[response allHeaderFields]
forURL:[NSURL URLWithString:#""]];
if ([zzzz count] > 0) {
if ([querystr isEqualToString:#"https://www.localhost.com/specificurl.aspx"]) {
NSMutableArray* actualCookies = [[NSMutableArray alloc] init];
NSHTTPCookie* obj = [self.tmpCookies objectAtIndex:0];
[actualCookies addObject:obj];
[actualCookies addObject:zzzz];
NSArray* authToken = [[NSArray alloc] initWithArray:actualCookies];
//BLOWS UP HERE ?? NSDictionary* headers = [NSHTTPCookie requestHeaderFieldsWithCookies:authToken];
//[request setAllHTTPHeaderFields:authToken];
[viewController setAuthCookieAfterValidLogin:zzzz];
}
}
}
return request;
}
The general idea is to set this header to have the value of my combined cookies

I found that although I couldn't modify the existing request, that didn't stop me from creating a new request and simply returning that one :)
- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSHTTPURLResponse *)response {
NSURL* redirected_url = [request URL];
NSString* querystr = [redirected_url absoluteString];
if (response != nil) {
NSArray* zzzz = [NSHTTPCookie
cookiesWithResponseHeaderFields:[response allHeaderFields]
forURL:[NSURL URLWithString:#""]];
if ([zzzz count] > 0) {
if ([querystr isEqualToString:#"https://www.localhost.com/specificurl.aspx"]) {
NSMutableArray* actualCookies = [[NSMutableArray alloc] init];
NSUInteger i, count = [zzzz count];
for (i = 0; i < count; i++) {
NSHTTPCookie* xxx = [zzzz objectAtIndex:i];
[actualCookies addObject:xxx];
}
NSHTTPCookie* obj = [self.tmpCookies objectAtIndex:0];
[actualCookies addObject:obj];
NSDictionary * headers = [NSHTTPCookie requestHeaderFieldsWithCookies:actualCookies];
NSURL *url = [NSURL URLWithString:#"https://www.localhost.com/specificurl.aspx"];
NSMutableURLRequest* xrequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[xrequest setHTTPMethod:#"GET"];
[xrequest setAllHTTPHeaderFields:headers];
[xrequest setValue:#"https://www.localhost.com/Default.aspx?Site_ID=500000" forHTTPHeaderField: #"Referer"];
[viewController setAuthCookieAfterValidLogin:zzzz];
return xrequest;
}
}
}
return request;
}

Related

Check auto-renewable subscription expire date from validate receipt

I am calling receipt validation method in app delegate to check the renewable process. Its working fine in development mode but after releasing from app store its always returning yes, even though user have not purchase the product. Please Suggest what wrong I am doing. In sandbox mode its working fine but after release I found the issue that its always returning true. For validating receipt I am using below code
// Validate the receipt
+(BOOL ) getStoreReceipt:(BOOL)sandbox andTrasaction:(SKPaymentTransaction *)tractaion{
NSArray *objects;
NSArray *keys;
NSDictionary *dictionary;
BOOL gotreceipt = false;
#try {
NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
if ([[NSFileManager defaultManager] fileExistsAtPath:[receiptUrl path]]) {
NSData *receiptData = [NSData dataWithContentsOfURL:receiptUrl];
NSString *receiptString = [self base64forData:receiptData];
NSLog(#"receiptString Value---->= %#",receiptString);
NSString *encReceipt = [receiptData base64EncodedStringWithOptions:0];
NSLog(#"receiptString Value ======>= %#",encReceipt);
if (receiptString != nil) {
NSString *strSharedSecrect = #"MY_Secrect_Key";
objects = [[NSArray alloc] initWithObjects:receiptString,strSharedSecrect, nil];
keys = [[NSArray alloc] initWithObjects:#"receipt-data",#"password", nil];
dictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
NSString *postData = [self getJsonStringFromDictionary:dictionary];
NSLog(#"postData Value---->= %#",receiptString);
NSString *urlSting = #"https://buy.itunes.apple.com/verifyReceipt";
// if (sandbox) urlSting = #"https://sandbox.itunes.apple.com/verifyReceipt";
dictionary = [self getJsonDictionaryWithPostFromUrlString:urlSting andDataString:postData];
NSLog(#"dictionary Value for receipt---->= %#",dictionary);
if ([dictionary objectForKey:#"status"] != nil) {
if ([[dictionary objectForKey:#"status"] intValue] == 0) {
gotreceipt = true;
}
}
}
}//623065
} #catch (NSException * e) {
gotreceipt = false;
return NO;
NSLog(#"NSException---->= %#",e);
}
if (!gotreceipt) {
NSLog(#"Not gotreceipt---->=");
objects = [[NSArray alloc] initWithObjects:#"-1", nil];
keys = [[NSArray alloc] initWithObjects:#"status", nil];
dictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
return NO;
}else{
BOOL isPurchased = [self PurchasedSubscriptionStatues:dictionary];
return isPurchased;
}
return NO;
}
Checking if pending for renewable is there or not...
+(BOOL)PurchasedSubscriptionStatues:(NSDictionary *)transactionReceipt
{
if ([[transactionReceipt allKeys] containsObject:#"pending_renewal_info"]) {
NSArray *arrData = [transactionReceipt objectForKey:#"pending_renewal_info"];
NSDictionary *dicPendinRenew = [arrData objectAtIndex:0];
if ([[dicPendinRenew allKeys] containsObject:#"expiration_intent"] || [[dicPendinRenew objectForKey:#"auto_renew_status"] integerValue]==0) {
return NO;
}else if ([[dicPendinRenew objectForKey:#"auto_renew_status"] integerValue]==1) {
return YES;
}else{
return NO;
}
}else{
return YES;
}
return NO;
}
Convert String To Dictionary
+(NSString *)getJsonStringFromDictionary:(NSDictionary *)dicVal
{
NSError *error = nil;
NSData *postData = [NSJSONSerialization dataWithJSONObject:dicVal options:NSJSONWritingPrettyPrinted error:&error];
NSString *postString = #"";
if (! postData) {
NSLog(#"Got an error: %#", error);
return nil;
}
else { postString = [[NSString alloc] initWithData:postData encoding:NSUTF8StringEncoding];
return postString;
}
}
Convert Dictionary to string
+(NSDictionary *) getJsonDictionaryWithPostFromUrlString:(NSString *)urlString andDataString:(NSString *)dataString {
NSString *jsonString = [self getStringWithPostFromUrlString:urlString andDataString:dataString];
NSLog(#"getJsonDictionaryWithPostFromUrlString-->%#", jsonString); // see what the response looks like
return [self getDictionaryFromJsonString:jsonString];
}
+ (NSDictionary *) getDictionaryFromJsonString:(NSString *)jsonstring {
NSError *jsonError;
NSDictionary *dictionary = (NSDictionary *) [NSJSONSerialization JSONObjectWithData:[jsonstring dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&jsonError];
if (jsonError) {
dictionary = [[NSDictionary alloc] init];
}
return dictionary;
}
//Request for post method to get the recipt
+ (NSString *) getStringWithPostFromUrlString:(NSString *)urlString andDataString:(NSString *)dataString {
NSString *s = #"";
#try {
NSData *postdata = [dataString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postlength = [NSString stringWithFormat:#"%d", [postdata length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:urlString]];
[request setTimeoutInterval:60];
[request setHTTPMethod:#"POST"];
[request setValue:postlength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postdata];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
if (data != nil) {
s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
}
#catch (NSException *exception) {
s = #"";
}
return s;
}
// from https://stackoverflow.com/questions/2197362/converting-nsdata-to-base64
+ (NSString*)base64forData:(NSData*)theData {
const uint8_t* input = (const uint8_t*)[theData bytes];
NSInteger length = [theData length];
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t* output = (uint8_t*)data.mutableBytes;
NSInteger i;
for (i=0; i < length; i += 3) {
NSInteger value = 0;
NSInteger j;
for (j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
NSInteger theIndex = (i / 3) * 4;
output[theIndex + 0] = table[(value >> 18) & 0x3F];
output[theIndex + 1] = table[(value >> 12) & 0x3F];
output[theIndex + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '=';
output[theIndex + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '=';
}
return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}
------------------------------------------------------------------------
I think your PurchasedSubscriptionStatues method has an error: if the receipt does not contain pending_renewal_info key, it returns YES. Try creating a new sandbox user and see if the receipt contains this key, if not - then this method should return NO in such case.
Also, you can try using some library that can manage InApp purchases, like RMStore, to ease on the receipt verification.

Fetch only MyContacts from gmail account in iOS

I am trying to fetch gmail & yahoo contacts in my iPhone application.
For Gmail I have used GTMOauth2.0. I can see all contacts but when I want only contacts from MyContacts group. I have used following code to get contacts:
-(void)signInToGoogle:(id)sender
{
[self signOutFromGoogle];
NSString *keychainItemName = nil;
NSString *scope = #"https://www.google.com/m8/feeds/contacts/default/full";
NSString *clientID = #"CLIENTID";
NSString *clientSecret = #"CLIENTSECRETID";
SEL finishedSel = #selector(viewController:finishedWithAuth:error:);
GTMOAuth2ViewControllerTouch *viewController;
viewController = [GTMOAuth2ViewControllerTouch controllerWithScope:scope
clientID:clientID
clientSecret:clientSecret
keychainItemName:keychainItemName
delegate:self
finishedSelector:finishedSel];
NSDictionary *params = [NSDictionary dictionaryWithObject:#"en" forKey:#"hl"];
viewController.signIn.additionalAuthorizationParameters = params;
NSString *html = #"<html><body bgcolor=silver><div align=center>Loading sign-in page...</div></body></html>";
viewController.initialHTMLString = html;
[[self navigationController] pushViewController:viewController animated:YES];
}
- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController
finishedWithAuth:(GTMOAuth2Authentication *)auth
error:(NSError *)error {
[[NSNotificationCenter defaultCenter] removeObserver:self];
if (error != nil) {
[processObj removeFromSuperview];
self.view.userInteractionEnabled = YES;
NSLog(#"Authentication error: %#", error);
NSData *responseData = [[error userInfo] objectForKey:#"data"]; // kGTMHTTPFetcherStatusDataKey
if ([responseData length] > 0) {
// show the body of the server's authentication failure response
NSString *str = [[NSString alloc] initWithData:responseData
encoding:NSUTF8StringEncoding];
NSLog(#"%#", str);
}
self.auth = nil;
} else {
self.auth = auth;
[self doAnAuthenticatedAPIFetch];
}
}
- (void)doAnAuthenticatedAPIFetch {
NSString *urlStr = #"https://www.google.com/m8/feeds/groups/default/full/Contacts";
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.auth authorizeRequest:request
completionHandler:^(NSError *error) {
NSString *output = nil;
if (error) {
output = [error description];
} else {
NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (data) {
// API fetch succeeded :Here I am getti
output = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
} else {
// fetch failed
output = [error description];
}
}
}];
}
In the API I am passing "Contacts" as a group id but it is returning error "Group Id Not Found". I have the google document from
https://developers.google.com/google-apps/contacts/v3/?csw=1
but still can't solve the problem. Help me on these.
You'll need to fetch the groups feed to get the ID for a group. See the groups feed documentation, or try the ContactsSample app provided with the Google Data APIs Objective-C Client Library.

how can I use NSURLConnection Asynchronously?

I am using this code to load data to my App, can you tell me how can I make this asynchronously?
NSMutableURLRequest *request2 = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:requestString] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10.0];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request2 delegate:self];
if (connection)
{
NSLog(#"NSURLConnection connection==true");
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request2 returningResponse:&response error:&err];
self.news =[NSJSONSerialization JSONObjectWithData:responseData options:nil error:nil];
NSLog(#"responseData: %#", self.news);
}
else
{
NSLog(#"NSURLConnection connection==false");
};
I think you should be bothered reading the documentation. There's a sendAsynchronousRequest:queue:completionHandler: method.
Create the connection with initWithRequest:delegate:startImmediately:, set yourself as its delegate and implement the delegate methods.
Block code is your friend. I have created a class which does this for you
Objective-C Block code. Create this class here
Interface class
#import <Foundation/Foundation.h>
#import "WebCall.h"
#interface WebCall : NSObject
{
void(^webCallDidFinish)(NSString *response);
}
#property (nonatomic, retain) NSMutableData *responseData;
-(void)setWebCallDidFinish:(void (^)(NSString *))wcdf;
-(void)webServiceCall :(NSString *)sURL_p : (NSMutableArray *)valueList_p : (NSMutableArray *)keyList_p;
#end
Implementation class
#import "WebCall.h"
#import "AppDelegate.h"
#implementation WebCall
#synthesize responseData;
-(void)setWebCallDidFinish:(void (^)(NSString *))wcdf
{
webCallDidFinish = [wcdf copy];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
int responseStatusCode = [httpResponse statusCode];
NSLog(#"Response Code = %i", responseStatusCode);
if(responseStatusCode < 200 || responseStatusCode > 300)
{
webCallDidFinish(#"failure");
}
[responseData setLength:0];
}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"WebCall Error: %#", error);
webCallDidFinish(#"failure");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *response = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
response = [response stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
webCallDidFinish(response);
}
-(void)webServiceCall :(NSString *)sURL_p : (NSMutableArray *)valueList_p : (NSMutableArray *)keyList_p
{
NSMutableString *sPost = [[NSMutableString alloc] init];
//If any variables need passed in - append them to the POST
//E.g. if keyList object is username and valueList object is adam will append like
//http://test.jsp?username=adam
if([valueList_p count] > 0)
{
for(int i = 0; i < [valueList_p count]; i++)
{
if(i == 0)
{
[sPost appendFormat:#"%#=%#", [valueList_p objectAtIndex:i],[keyList_p objectAtIndex:i]];
}
else
{
[sPost appendFormat:#"&%#=%#", [valueList_p objectAtIndex:i], [keyList_p objectAtIndex:i]];
}
}
}
NSData * postData = [sPost dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:NO];
NSString * postLength = [NSString stringWithFormat:#"%d",[postData length]];
NSURL * url = [NSURL URLWithString:sURL_p];
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:5];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postData];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
if (theConnection)
{
self.responseData = [NSMutableData data];
}
}
#end
Then you to make this web call, you call it like this
WebCall *webCall = [[WebCall alloc] init];
[webCall setWebCallDidFinish:^(NSString *response){
//This method is called as as soon as the web call is finished
NSString *trimmedString = [response stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if([trimmedString rangeOfString:#"failure"].location == NSNotFound)
{
//Successful web call
}
else
{
//If the webcall failed due to an error
}
}];
//Make web call here
[webCall webServiceCall:#"http://www.bbc.co.uk/" :nil :nil];
See the setWebCallDidFinish method, it will not be called until the webcall has finished.
Hope that helps!!
Here is some code which I am using in my app:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:yourURL]];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
NSLog(#"Error loading data from %#. Error Userinfo: %#",yourURL, [error userInfo]);
} else {
NSDictionary *dataFromServer = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
contentAsString = [[[dataFromServer objectForKey:#"page"] objectForKey:#"content"] stripHtml];
completionHandler(contentAsString);
}];
fyi: stripHTML is a NSString Category to remove HTML tags from JSON --> Found it Here
you can call your content in your class like that:
[yourClass getDataWithcompletionHandler:^(NSString *content) {
yourObject.content = content;
[yourClass saveManagedObjectContext];
}];
if you implement it once, you won't want to use synchronous connection again...
Check this out: HTTPCachedController
It will help you send POST and GET requests, while it will cache the response and after that it will return the cached data when no internet connection is available.
HTTPCachedController *ctrl = [[[HTTPCachedController alloc] initWithRequestType:1 andDelegate:self] autorelease];
[ctrl getRequestToURL:#"https://api.github.com/orgs/twitter/repos?page=1&per_page=10"];
You will get notified when the data are fetched through a delegate method:
-(void)connectionFinishedWithData:(NSString*)data andRequestType:(int)reqType

Upload Video to Vimeo in Objective C on iPhone

I am developing an app from which I want to upload Videos to Vimeo, Facebook and Youtube. Facebook and Youtube have pretty straightforward apis, Vimeo has a good developer documentation, but no Objective C framework. I have seen a couple of Apps which use Vimeo, so I was wondering if there is some kind of Framework out there I'm not aware of.
OK everybody. If you're still interested in how to upload a video to vimeo, here's the code. First you need to register an App with vimeo and obtain your secret and consumer key. Then you need to get the GTMOAuth framework from Google and possibly the SBJson framework. At the moment I unfortunately don't have the time to clean up the below code, but I thought this may be better than nothing for those, who need some help with vimeo. Essentially you authenticate with vimeo, get an upload ticket, upload the video with this ticket and then ad a title and some text.
The code below won't work out of the box, because there are a couple of view elements connected, but it should give you an understanding of what is happening.
#define VIMEO_SECRET #"1234567890"
#define VIMEO_CONSUMER_KEY #"1234567890"
#define VIMEO_BASE_URL #"http://vimeo.com/services/auth/"
#define VIMEO_REQUEST_TOKEN_URL #"http://vimeo.com/oauth/request_token"
#define VIMEO_AUTHORIZATION_URL #"http://vimeo.com/oauth/authorize?permission=write"
#define VIMEO_ACCESS_TOKEN_URL #"http://vimeo.com/oauth/access_token"
#import "MMVimeoUploaderVC.h"
#import "GTMOAuthAuthentication.h"
#import "GTMOAuthSignIn.h"
#import "GTMOAuthViewControllerTouch.h"
#import "JSON.h"
#interface MMVimeoUploaderVC ()
#property (retain) GTMOAuthAuthentication *signedAuth;
#property (retain) NSString *currentTicketID;
#property (retain) NSString *currentVideoID;
#property (assign) BOOL isUploading;
#property (retain) GTMHTTPFetcher *currentFetcher;
#end
#implementation MMVimeoUploaderVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
first = YES;
[GTMOAuthViewControllerTouch removeParamsFromKeychainForName:#"Vimeo"];
}
return self;
}
- (void)stopUpload {
if ( self.isUploading || self.currentFetcher ) {
[self.currentFetcher stopFetching];
}
}
- (void) setProgress:(float) progress {
// Connect to your views here
}
#pragma mark - handle error
- (void) handleErrorWithText:(NSString *) text {
//notify your views here
self.currentFetcher = nil;
self.isUploading = NO;
self.progressBar.alpha = 0;
self.uploadButton.alpha = 1;
}
#pragma mark - interface callbacks
//step one, authorize
- (void)startUpload {
if ( self.signedAuth ) {
//authentication present, start upload
} else {
//get vimeo authentication
NSURL *requestURL = [NSURL URLWithString:VIMEO_REQUEST_TOKEN_URL];
NSURL *accessURL = [NSURL URLWithString:VIMEO_ACCESS_TOKEN_URL];
NSURL *authorizeURL = [NSURL URLWithString:VIMEO_AUTHORIZATION_URL];
NSString *scope = #"";
GTMOAuthAuthentication *auth = [self vimeoAuth];
// set the callback URL to which the site should redirect, and for which
// the OAuth controller should look to determine when sign-in has
// finished or been canceled
//
// This URL does not need to be for an actual web page
[auth setCallback:#"http://www.....com/OAuthCallback"];
// Display the autentication view
GTMOAuthViewControllerTouch *viewController;
viewController = [[[GTMOAuthViewControllerTouch alloc] initWithScope:scope
language:nil
requestTokenURL:requestURL
authorizeTokenURL:authorizeURL
accessTokenURL:accessURL
authentication:auth
appServiceName:#"Vimeo"
delegate:self
finishedSelector:#selector(viewController:finishedWithAuth:error:)] autorelease];
[[self navigationController] pushViewController:viewController
animated:YES];
}
}
//step two get upload ticket
- (void)viewController:(GTMOAuthViewControllerTouch *)viewController
finishedWithAuth:(GTMOAuthAuthentication *)auth
error:(NSError *)error {
if (error != nil) {
[self handleErrorWithText:nil];
} else {
self.signedAuth = auth;
[self startUpload];
}
}
- (void) startUpload {
self.isUploading = YES;
NSURL *url = [NSURL URLWithString:#"http://vimeo.com/api/rest/v2?format=json&method=vimeo.videos.upload.getQuota"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.signedAuth authorizeRequest:request];
GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
[myFetcher beginFetchWithDelegate:self
didFinishSelector:#selector(myFetcher:finishedWithData:error:)];
self.currentFetcher = myFetcher;
}
- (void) myFetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *) error {
if (error != nil) {
[self handleErrorWithText:nil];
NSLog(#"error %#", error);
} else {
NSString *info = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSDictionary *result = [info JSONValue];
//quota
int quota = [[result valueForKeyPath:#"user.upload_space.max"] intValue];
//get video file size
NSString *path;
path = #"local video path";
NSFileManager *manager = [NSFileManager defaultManager];
NSDictionary *attrs = [manager attributesOfItemAtPath:path error: NULL];
UInt32 size = [attrs fileSize];
if ( size > quota ) {
[self handleErrorWithText:#"Your Vimeo account quota is exceeded."];
return;
}
//lets assume we have enough quota
NSURL *url = [NSURL URLWithString:#"http://vimeo.com/api/rest/v2?format=json&method=vimeo.videos.upload.getTicket&upload_method=streaming"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.signedAuth authorizeRequest:request];
GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
[myFetcher beginFetchWithDelegate:self
didFinishSelector:#selector(myFetcher2:finishedWithData:error:)];
self.currentFetcher = myFetcher;
}
}
- (void) myFetcher2:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *) error {
if (error != nil) {
[self handleErrorWithText:nil];
NSLog(#"error %#", error);
} else {
NSString *info = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSDictionary *result = [info JSONValue];
//fail here if neccessary TODO
NSString *urlString = [result valueForKeyPath:#"ticket.endpoint"];
self.currentTicketID = [result valueForKeyPath:#"ticket.id"];
if ( [self.currentTicketID length] == 0 || [urlString length] == 0) {
[self handleErrorWithText:nil];
return;
}
//get video file
// load the file data
NSString *path;
path = [MMMovieRenderer sharedRenderer].localVideoURL;
//get video file size
NSFileManager *manager = [NSFileManager defaultManager];
NSDictionary *attrs = [manager attributesOfItemAtPath:path error: NULL];
UInt32 size = [attrs fileSize];
//insert endpoint here
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"PUT"];
[request setValue:[NSString stringWithFormat:#"%i", size] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"video/mp4" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:[NSData dataWithContentsOfFile:path]];
[self.signedAuth authorizeRequest:request];
GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
myFetcher.sentDataSelector = #selector(myFetcher:didSendBytes:totalBytesSent:totalBytesExpectedToSend:);
[myFetcher beginFetchWithDelegate:self
didFinishSelector:#selector(myFetcher3:finishedWithData:error:)];
self.currentFetcher = myFetcher;
}
}
- (void)myFetcher:(GTMHTTPFetcher *)fetcher
didSendBytes:(NSInteger)bytesSent
totalBytesSent:(NSInteger)totalBytesSent
totalBytesExpectedToSend:(NSInteger)totalBytesExpectedToSend {
NSLog(#"%i / %i", totalBytesSent, totalBytesExpectedToSend);
[self setProgress:(float)totalBytesSent / (float) totalBytesExpectedToSend];
self.uploadLabel.text = #"Uploading to Vimeo...";
}
- (void) myFetcher3:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *) error {
if (error != nil) {
[self handleErrorWithText:nil];
} else {
NSString *info = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
//finalize upload
NSString *requestString = [NSString stringWithFormat:#"http://vimeo.com/api/rest/v2?format=json&method=vimeo.videos.upload.complete&ticket_id=%#&filename=%#", self.currentTicketID, #"movie.mov"];
NSURL *url = [NSURL URLWithString:requestString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.signedAuth authorizeRequest:request];
GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
[myFetcher beginFetchWithDelegate:self
didFinishSelector:#selector(myFetcher4:finishedWithData:error:)];
self.currentFetcher = myFetcher;
}
}
- (void) myFetcher4:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *) error {
if (error != nil) {
[self handleErrorWithText:nil];
} else {
//finish upload
NSString *info = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSDictionary *result = [info JSONValue];
self.currentVideoID = [result valueForKeyPath:#"ticket.video_id"];
if ( [self.currentVideoID length] == 0 ) {
[self handleErrorWithText:nil];
return;
}
//set title
NSString *title = [MMMovieSettingsManager sharedManager].movieTitle;
title = [title stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString *requestString = [NSString stringWithFormat:#"http://vimeo.com/api/rest/v2?format=json&method=vimeo.videos.setTitle&video_id=%#&title=%#", self.currentVideoID, title];
NSLog(#"%#", requestString);
NSURL *url = [NSURL URLWithString:requestString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.signedAuth authorizeRequest:request];
GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
[myFetcher beginFetchWithDelegate:self
didFinishSelector:#selector(myFetcher5:finishedWithData:error:)];
}
}
- (void) myFetcher5:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *) error {
if (error != nil) {
[self handleErrorWithText:nil];
NSLog(#"error %#", error);
} else {
//set description
NSString *desc = #"Video created with ... iPhone App.";
desc = [desc stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString *requestString = [NSString stringWithFormat:#"http://vimeo.com/api/rest/v2?format=json&method=vimeo.videos.setDescription&video_id=%#&description=%#", self.currentVideoID, desc];
NSURL *url = [NSURL URLWithString:requestString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[self.signedAuth authorizeRequest:request];
GTMHTTPFetcher* myFetcher = [GTMHTTPFetcher fetcherWithRequest:request];
[myFetcher beginFetchWithDelegate:self
didFinishSelector:#selector(myFetcher6:finishedWithData:error:)];
}
}
- (void) myFetcher6:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *) error {
if (error != nil) {
[self handleErrorWithText:nil];
NSLog(#"error %#", error);
} else {
//done
//alert your views that the upload has been completed
}
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[self setProgress:0];
}
- (void) viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[GTMOAuthViewControllerTouch removeParamsFromKeychainForName:#"Vimeo"];
}
#pragma mark - oauth stuff
- (GTMOAuthAuthentication *)vimeoAuth {
NSString *myConsumerKey = VIMEO_CONSUMER_KEY; // pre-registered with service
NSString *myConsumerSecret = VIMEO_SECRET; // pre-assigned by service
GTMOAuthAuthentication *auth;
auth = [[[GTMOAuthAuthentication alloc] initWithSignatureMethod:kGTMOAuthSignatureMethodHMAC_SHA1
consumerKey:myConsumerKey
privateKey:myConsumerSecret] autorelease];
// setting the service name lets us inspect the auth object later to know
// what service it is for
auth.serviceProvider = #"Vimeo";
return auth;
}
#end
#import <Foundation/Foundation.h>
#protocol vimeodelagate;
#interface Vimeo_uploader : NSObject<NSURLSessionDelegate, NSURLSessionTaskDelegate>
#property(weak) id<vimeodelagate> delegate;
+(id)SharedManger;
-(void)pass_data_header:(NSData *)videoData;
- (void)Give_title_to_video:(NSString *)VIdeo_id With_name:(NSString *)name ;
#end
#protocol vimeodelagate <NSObject>
-(void)vimeouploader_succes:(NSString *)link methodName:(NSString *)methodName;
-(void)vimeouploader_progress:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalByte;
-(void)vimeouploader_error:(NSError *)error methodName:(NSString *)methodName;
#end
#define Aurtorizartion #"bearer 123456789" // replace 123456789 with your token, bearer text will be there
#define accept #"application/vnd.vimeo.*+json; version=3.2"
#import "Vimeo_uploader.h"
#implementation Vimeo_uploader
+(id)SharedManger{
static Vimeo_uploader *Vimeouploader = nil;
#synchronized (self) {
static dispatch_once_t oncetoken;
dispatch_once(&oncetoken, ^{
Vimeouploader = [[self alloc] init];
});
}
return Vimeouploader;
}
-(id)init{
if (self = [super init]) {
}
return self;
}
- (void)pass_data_header:(NSData *)videoData{
NSString *tmpUrl=[[NSString alloc]initWithFormat:#"https://api.vimeo.com/me/videos?type=streaming&redirect_url=&upgrade_to_1080=false"];
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:tmpUrl] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:0];
[request setHTTPMethod:#"POST"];
[request setValue:Aurtorizartion forHTTPHeaderField:#"Authorization"];
[request setValue:accept forHTTPHeaderField:#"Accept"];//change this according to your need.
NSError *error;
NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: &error];
NSDictionary * json = [NSJSONSerialization JSONObjectWithData:returnData options:kNilOptions error:&error];
if (!error) {
[self call_for_ticket:[json valueForKey:#"upload_link_secure"] complet_url:[json valueForKey:#"complete_uri"] videoData:videoData];
}else{
NSLog(#"RESPONSE--->%#",json);
}
}
- (void)call_for_ticket:(NSString *)upload_url complet_url:(NSString *)complet_uri videoData:(NSData *)videoData{
NSURLSessionConfiguration *configuration;
//configuration.timeoutIntervalForRequest = 5;
//configuration.timeoutIntervalForResource = 5;
configuration.HTTPMaximumConnectionsPerHost = 1;
configuration.allowsCellularAccess = YES;
// configuration.networkServiceType = NSURLNetworkServiceTypeBackground;
configuration.discretionary = NO;
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
delegate:self
delegateQueue:[NSOperationQueue mainQueue]];
NSURL *url = [NSURL URLWithString:upload_url];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setHTTPMethod:#"PUT"];
[urlRequest setTimeoutInterval:0];
[urlRequest setValue:Aurtorizartion forHTTPHeaderField:#"Authorization"];
[urlRequest setValue:accept forHTTPHeaderField:#"Accept"];
NSError *error;
NSString *str_lenth = [NSString stringWithFormat:#"%lu",(unsigned long)videoData.length];
NSDictionary *dict = #{#"str_lenth":str_lenth,
#"Content-Type":#"video/mp4"};
NSData *postData12 = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];
[urlRequest setHTTPBody:postData12];
// [urlRequest setHTTPBody:videoData];
// You could try use uploadTaskWithRequest fromData
NSURLSessionUploadTask *taskUpload = [session uploadTaskWithRequest:urlRequest fromData:videoData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;
if (!error && httpResp.statusCode == 200) {
[self call_complete_uri:complet_uri];
} else {
if([self.delegate respondsToSelector:#selector(vimeouploader_error:methodName:)]){
[self.delegate vimeouploader_error:error methodName:#"vimeo"];}
NSLog(#"ERROR: %# AND HTTPREST ERROR : %ld", error, (long)httpResp.statusCode);
}
}];
[taskUpload resume];
}
-(void)call_complete_uri:(NSString *)complettion_url{
NSString *str_url =[NSString stringWithFormat:#"https://api.vimeo.com%#",complettion_url];
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:str_url] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:0];
[request setHTTPMethod:#"DELETE"];
[request setValue:Aurtorizartion forHTTPHeaderField:#"Authorization"];
[request setValue:accept forHTTPHeaderField:#"Accept"];
//change this according to your need.
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
if ([httpResponse statusCode] == 201) {
NSDictionary *dict = [[NSDictionary alloc]initWithDictionary:[httpResponse allHeaderFields]];
if (dict) {
if([self.delegate respondsToSelector:#selector(vimeouploader_succes:methodName:)]){
// [self.delegate vimeouploader_succes:[dict valueForKey:#"Location"] methodName:#"vimeo"];
NSLog(#"sucesses");
NSString *str = [NSString stringWithFormat:#"title"];
[self Give_title_to_video:[dict valueForKey:#"Location"] With_name:str];
}else{
if([self.delegate respondsToSelector:#selector(vimeouploader_error:methodName:)]){
[self.delegate vimeouploader_error:error methodName:#"vimeo"];}
}
}
}else{
//9
if([self.delegate respondsToSelector:#selector(vimeouploader_error:methodName:)]){
[self.delegate vimeouploader_error:error methodName:#"vimeo"];}
NSLog(#"%#",error.localizedDescription);
}
}];
}
- (void)Give_title_to_video:(NSString *)VIdeo_id With_name:(NSString *)name {
NSString *tmpUrl=[[NSString alloc]initWithFormat:#"https://api.vimeo.com%#",VIdeo_id];
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:tmpUrl] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:0];
[request setHTTPMethod:#"PATCH"];
[request setValue:Aurtorizartion forHTTPHeaderField:#"Authorization"];
[request setValue:accept forHTTPHeaderField:#"Accept"];//change this according to your need.
NSError *error;
NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: &error];
NSDictionary * json = [NSJSONSerialization JSONObjectWithData:returnData options:kNilOptions error:&error];
NSString *str_description = #"description";
NSDictionary *dict = #{#"name":name,
#"description":str_description,
#"review_link":#"false"
};
NSData *postData12 = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];
[request setHTTPBody:postData12];
if (!error) {
NSLog(#"RESPONSE--->%#",json);
[self.delegate vimeouploader_succes:[json valueForKey:#"link"] methodName:#"vimeo"];
}else{
if([self.delegate respondsToSelector:#selector(vimeouploader_error:methodName:)]){
[self.delegate vimeouploader_error:error methodName:#"vimeo"];}
//NSLog(#"%#",error.localizedDescription);
NSLog(#"Give_title_to_video_error--->%#",error);
}
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
NSLog(#"didSendBodyData: %lld, totalBytesSent: %lld, totalBytesExpectedToSend: %lld", bytesSent, totalBytesSent, totalBytesExpectedToSend);
if([self.delegate respondsToSelector:#selector(vimeouploader_progress:totalBytesExpectedToSend:)]){
[self.delegate vimeouploader_progress:totalBytesSent totalBytesExpectedToSend:totalBytesExpectedToSend];}
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
if (error == nil) {
NSLog(#"Task: %# upload complete", task);
} else {
NSLog(#"Task: %# upload with error: %#", task, [error localizedDescription]);
}
}
#end
The vimeo-Api is enough. Take a closer look to the vimeo-upload-api
The interface can be used in any language which is able to send network-data. You have to create some NSURLConnections and you have to set the HTTP-Body like in their examples.
I wrote AFNetworking Client for Vimeo API - https://github.com/m1entus/RWMViemoClient

How to improve memory management when doing low level http work

I'm starting to cleanup an older prototype I worked on and it's doing a great deal of low level http work. The problem I'm having is how and when to do a release inside the "connectionDidFinishLoading" method below. I have some items only created inside the if but when I release them before the method call I get several BAD ACCESS errors and thought to ask how I should be doing memory management in this scenario.
- (void)searchForNewHats:(HatViewController *)hatVwController
{
responseData = [[NSMutableData data] retain]; //responseData is a property that I retain - fyi
hatController = hatVwController; //hatController is a property that I retain - fyi
NSURL *url = [NSURL URLWithString:#"http://localhost/jsondata"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[request setHTTPMethod:#"GET"];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSArray *json = [responseString JSONValue];
if (json != NULL) {
NSArray *items = [json valueForKeyPath:#"d"];
HatParseJson* hatParseJson = [[HatParseJson alloc] init];
NSArray* hatz = [hatParseJson parseJson:items];
NSMutableArray* newHats = [[NSMutableArray alloc] init];
NSUInteger i, count = [hatz count];
for (i = 0; i < count; i++) {
Hat* obj = [hatz objectAtIndex:i];
[newHats addObject:obj];
//[obj release]; this blows up for example ...
}
[hatParseJson release];
[hatController newHatJsonFinished:newReleases];
}else {
[hatController newHatJsonFinished:nil];
}
[responseString release];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
}
Thank you in advance
some updates and comments inline:
- (void)searchForNewHats:(HatViewController *)hatVwController
{
assert(0 == responseData);
responseData = [NSMutableData new];
assert(0 == hatController);
self.hatController = hatVwController;
NSURL * url = [NSURL URLWithString:#"http://localhost/jsondata"];
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[request setHTTPMethod:#"GET"];
/* the delegate is retained in iOS, but not necessarily in OS X so... maybe you want to make connection an ivar of self? */
NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
/* don't you want to hold on to this? */
[connection release], connection = 0;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)inConnection {
if (ConnectionIsAnIvar) {
if (self.connection != inConnection) {
assert(0 && "connection delegate messages sent to wrong instance. threading issue or worse?");
return;
}
}
else {
[connection release];
}
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSArray *json = [responseString JSONValue];
if (json != NULL) {
NSArray *items = [json valueForKeyPath:#"d"];
HatParseJson* hatParseJson = [[HatParseJson alloc] init];
NSArray* hatz = [hatParseJson parseJson:items];
NSMutableArray* newHats = [[NSMutableArray alloc] init];
/* why not simply:
NSMutableArray* newHats = [hatz mutableCopy];
*/
NSUInteger i, count = [hatz count];
for (i = 0; i < count; i++) {
Hat* obj = [hatz objectAtIndex:i];
[newHats addObject:obj];
/* [obj release]; this blows up for example ... */
/* >> it should blow up. objectAtIndex: uses a get, not retain or copy */
}
[hatParseJson release];
[hatController newHatJsonFinished:newReleases];
}
else {
[hatController newHatJsonFinished:nil];
}
[responseString release];
}
[obj release] is a wrong thing to do because you are just adding objects from one array to another. Instead you should release newHats when done because you explicitly allocate it with alloc.