383 lines
16 KiB
Objective-C
383 lines
16 KiB
Objective-C
//
|
|
// OpenPhotoService.m
|
|
// iPhone and iPad Example
|
|
//
|
|
// Created by Patrick Santana on 20/03/12.
|
|
// Copyright 2013 Trovebox
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#import "WebService.h"
|
|
@interface WebService()
|
|
|
|
- (ASIHTTPRequest *) sendSynchronousRequest:(NSString *) request httpMethod:(NSString*) method;
|
|
- (void) validateCredentials;
|
|
- (OAMutableURLRequest*) getUrlRequest:(NSURL *) url;
|
|
- (NSArray *) parseResponse:(ASIHTTPRequest *) response;
|
|
- (NSDictionary *) parseResponseAsNSDictionary:(ASIHTTPRequest *) response;
|
|
|
|
@property (nonatomic, retain, readwrite) NSString *server;
|
|
@property (nonatomic, retain, readwrite) NSString *oAuthKey;
|
|
@property (nonatomic, retain, readwrite) NSString *oAuthSecret;
|
|
@property (nonatomic, retain, readwrite) NSString *consumerKey;
|
|
@property (nonatomic, retain, readwrite) NSString *consumerSecret;
|
|
|
|
@end
|
|
|
|
@implementation WebService
|
|
|
|
@synthesize server=_server, oAuthKey=_oAuthKey, oAuthSecret=_oAuthSecret, consumerKey = _consumerKey, consumerSecret=_consumerSecret;
|
|
|
|
- (id)init
|
|
{
|
|
self = [super init];
|
|
if (self) {
|
|
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
|
|
self = [[WebService alloc] initForServer:[standardUserDefaults valueForKey:kTroveboxServer]
|
|
oAuthKey:[standardUserDefaults valueForKey:kAuthenticationOAuthToken]
|
|
oAuthSecret:[standardUserDefaults valueForKey:kAuthenticationOAuthSecret]
|
|
consumerKey:[standardUserDefaults valueForKey:kAuthenticationConsumerKey]
|
|
consumerSecret:[standardUserDefaults valueForKey:kAuthenticationConsumerSecret]] ;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
-(id)initForServer:(NSString *) server
|
|
oAuthKey:(NSString *) oAuthKey
|
|
oAuthSecret:(NSString *) oAuthSecret
|
|
consumerKey:(NSString *) consumerKey
|
|
consumerSecret:(NSString *) consumerSecret{
|
|
|
|
self = [super init];
|
|
|
|
if (self) {
|
|
// set the objects
|
|
self.server = server;
|
|
self.oAuthKey = oAuthKey;
|
|
self.oAuthSecret = oAuthSecret;
|
|
self.consumerKey = consumerKey;
|
|
self.consumerSecret = consumerSecret;
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (NSArray*) fetchNewestPhotosMaxResult:(int) maxResult{
|
|
NSMutableString *request = [NSMutableString stringWithFormat: @"%@%i%@",@"/v1/photos/list.json?sortBy=dateUploaded,DESC&pageSize=", maxResult, @"&returnSizes="];
|
|
|
|
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] == YES && [[UIScreen mainScreen] scale] == 2.00) {
|
|
// retina display
|
|
[request appendString:@"610x530xCR,610x530"];
|
|
}else{
|
|
// not retina display
|
|
[request appendString:@"305x265xCR,305x265"];
|
|
}
|
|
|
|
return [self parseResponse:[self sendSynchronousRequest:request httpMethod:@"GET"]];
|
|
}
|
|
|
|
|
|
- (NSDictionary*) uploadPicture:(NSData*) data metadata:(NSDictionary*) values fileName:(NSString *)fileName delegate:(id) delegate
|
|
{
|
|
[self validateCredentials];
|
|
|
|
NSMutableString *urlString = [NSMutableString stringWithFormat: @"%@/v1/photo/upload.json", self.server];
|
|
NSURL *url = [NSURL URLWithString:urlString];
|
|
|
|
#ifdef DEVELOPMENT_ENABLED
|
|
NSLog(@"Url upload = [%@]. Execute OAuth and Multipart",urlString);
|
|
NSLog(@"Title = %@",[values objectForKey:@"title"] );
|
|
NSLog(@"Permission = %@",[values objectForKey:@"permission"]);
|
|
NSLog(@"Tags = %@",[values objectForKey:@"tags"]);
|
|
#endif
|
|
|
|
OAMutableURLRequest *oaUrlRequest = [self getUrlRequest:url];
|
|
[oaUrlRequest setHTTPMethod:@"POST"];
|
|
|
|
OARequestParameter *titleParam = [[OARequestParameter alloc] initWithName:@"title"
|
|
value:[values objectForKey:@"title"]];
|
|
OARequestParameter *permissionParam = [[OARequestParameter alloc] initWithName:@"permission"
|
|
value:[NSString stringWithFormat:@"%@",[values objectForKey:@"permission"]]];
|
|
|
|
OARequestParameter *tagParam = [[OARequestParameter alloc] initWithName:@"tags"
|
|
value:[values objectForKey:@"tags"]];
|
|
NSArray *params = [NSArray arrayWithObjects:titleParam, permissionParam, tagParam, nil];
|
|
[oaUrlRequest setParameters:params];
|
|
|
|
// prepare the request. This will be used to get the Authorization header and add in the multipart component
|
|
[oaUrlRequest prepare];
|
|
|
|
/*
|
|
*
|
|
* Using ASIHTTPRequest for Multipart. The authentication come from the OAMutableURLRequest
|
|
*
|
|
*/
|
|
ASIFormDataRequest *asiRequest = [ASIFormDataRequest requestWithURL:url];
|
|
asiRequest.userAgentString=@"OpenPhoto iOS";
|
|
|
|
// set the authorization header to be used in the OAuth
|
|
NSDictionary *dictionary = [oaUrlRequest allHTTPHeaderFields];
|
|
[asiRequest addRequestHeader:@"Authorization" value:[dictionary objectForKey:@"Authorization"]];
|
|
|
|
// set the parameter already added in the signature
|
|
[asiRequest addPostValue:[values objectForKey:@"title"] forKey:@"title"];
|
|
[asiRequest addPostValue:[values objectForKey:@"permission"] forKey:@"permission"];
|
|
[asiRequest addPostValue:[values objectForKey:@"tags"] forKey:@"tags"];
|
|
|
|
if (delegate){
|
|
// set the progress bar
|
|
[asiRequest setUploadProgressDelegate:delegate];
|
|
}
|
|
|
|
// add the file in the multipart. This file is stored locally for perfomance reason. We don't have to load it
|
|
// in memory. If it is a picture with filter, we just send without giving the name
|
|
// and content type
|
|
[asiRequest addData:data withFileName:fileName andContentType:[ContentTypeUtilities contentTypeForImageData:data] forKey:@"photo"];
|
|
// timeout 4 minutes. TODO. Needs improvements.
|
|
[asiRequest setTimeOutSeconds:240];
|
|
[asiRequest startSynchronous];
|
|
|
|
return [self parseResponseAsNSDictionary:asiRequest];
|
|
}
|
|
|
|
// get all tags. It brings how many images have this tag.
|
|
- (NSArray*) getTags
|
|
{
|
|
return [self parseResponse:[self sendSynchronousRequest:@"/v1/tags/list.json" httpMethod:@"GET"]];
|
|
}
|
|
|
|
// get details from the system
|
|
- (NSArray*) getSystemVersion
|
|
{
|
|
return [self parseResponse:[self sendSynchronousRequest:@"/v1/system/version.json" httpMethod:@"GET"]];
|
|
}
|
|
|
|
// get user details
|
|
- (NSDictionary*) getUserDetails
|
|
{
|
|
return [self parseResponseAsNSDictionary:[self sendSynchronousRequest:@"/v1/user/profile.json" httpMethod:@"GET"]];
|
|
}
|
|
|
|
- (NSArray*) removeCredentialsForKey:(NSString *) consumerKey
|
|
{
|
|
return [self parseResponse:[self sendSynchronousRequest:[NSString stringWithFormat:@"/oauth/%@/delete.json",consumerKey] httpMethod:@"POST"]];
|
|
}
|
|
|
|
|
|
- (NSArray*) loadGallery:(int) pageSize onPage:(int) page
|
|
{
|
|
return [self parseResponse:[self sendSynchronousRequest:[NSString stringWithFormat: @"%@%@%@%@%@",
|
|
@"/v1/photos/list.json?pageSize=",
|
|
[NSString stringWithFormat:@"%d", pageSize],
|
|
@"&page=",[NSString stringWithFormat:@"%d", page],
|
|
@"&returnSizes=200x200,640x960"] httpMethod:@"GET"]];
|
|
}
|
|
|
|
- (NSArray *) loadGallery:(int) pageSize onPage:(int) page tag:(Tag*) tag
|
|
{
|
|
return [self parseResponse:[self sendSynchronousRequest:[NSString stringWithFormat: @"%@%@%@%@%@%@%@",
|
|
@"/v1/photos/list.json?pageSize=",
|
|
[NSString stringWithFormat:@"%d", pageSize],
|
|
@"&page=",[NSString stringWithFormat:@"%d", page],
|
|
@"&returnSizes=200x200,640x960",
|
|
@"&tags=", [tag.name stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] httpMethod:@"GET"]];
|
|
}
|
|
|
|
- (NSArray *) loadGallery:(int) pageSize onPage:(int) page album:(Album *)album
|
|
{
|
|
return [self parseResponse:[self sendSynchronousRequest:[NSString stringWithFormat: @"%@%@%@%@%@%@%@",
|
|
@"/v1/photos/list.json?pageSize=",
|
|
[NSString stringWithFormat:@"%d", pageSize],
|
|
@"&page=",[NSString stringWithFormat:@"%d", page],
|
|
@"&returnSizes=200x200,640x960",
|
|
@"&album=",[album.identification stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] httpMethod:@"GET"]];
|
|
}
|
|
|
|
- (NSArray*) loadAlbums:(int) pageSize
|
|
{
|
|
return [self parseResponse:[self sendSynchronousRequest:@"/v1/albums/list.json" httpMethod:@"GET"]];
|
|
}
|
|
|
|
|
|
- (ASIHTTPRequest *) sendSynchronousRequest:(NSString *) request httpMethod:(NSString*) method{
|
|
[self validateCredentials];
|
|
|
|
// create the url to connect to OpenPhoto
|
|
NSString *urlString = [NSString stringWithFormat: @"%@%@", self.server, request];
|
|
|
|
#ifdef DEVELOPMENT_ENABLED
|
|
NSLog(@"Request to be sent = [%@]",urlString);
|
|
NSLog(@"Request http method = [%@]",method);
|
|
|
|
#endif
|
|
|
|
// transform in URL for the request
|
|
NSURL *url = [NSURL URLWithString:urlString];
|
|
|
|
OAMutableURLRequest *oaUrlRequest = [self getUrlRequest:url];
|
|
[oaUrlRequest setHTTPMethod:method];
|
|
|
|
// prepare the Authentication Header
|
|
[oaUrlRequest prepare];
|
|
|
|
// set the authorization header to be used in the OAuth
|
|
NSDictionary *dictionary = [oaUrlRequest allHTTPHeaderFields];
|
|
|
|
if ([method isEqualToString:@"GET"]){
|
|
// GET
|
|
ASIHTTPRequest *asiHttpRequest = [ASIHTTPRequest requestWithURL:url];
|
|
[asiHttpRequest addRequestHeader:@"Authorization" value:[dictionary objectForKey:@"Authorization"]];
|
|
asiHttpRequest.userAgentString=@"OpenPhoto iOS";
|
|
[asiHttpRequest setTimeOutSeconds:60];
|
|
|
|
// send the request synchronous
|
|
[asiHttpRequest startSynchronous];
|
|
|
|
return asiHttpRequest;
|
|
}else{
|
|
// POST
|
|
ASIFormDataRequest *asiRequest = [ASIFormDataRequest requestWithURL:url];
|
|
[asiRequest addRequestHeader:@"Authorization" value:[dictionary objectForKey:@"Authorization"]];
|
|
asiRequest.userAgentString=@"OpenPhoto iOS";
|
|
[asiRequest setTimeOutSeconds:60];
|
|
|
|
[asiRequest startSynchronous];
|
|
|
|
return asiRequest;
|
|
}
|
|
}
|
|
|
|
- (NSDictionary *) parseResponseAsNSDictionary:(ASIHTTPRequest *) response
|
|
{
|
|
#ifdef DEVELOPMENT_ENABLED_JSON_RETURN
|
|
NSLog(@"Response = %@",response);
|
|
#endif
|
|
#ifdef DEVELOPMENT_ENABLED
|
|
NSLog(@"responseStatusMessage = %@", [response responseStatusMessage]);
|
|
NSLog(@"responseStatusCode = %i", [response responseStatusCode]);
|
|
#endif
|
|
|
|
NSError *error = [response error];
|
|
if (error) {
|
|
NSLog(@"Error: %@", error);
|
|
NSException *exception = [NSException exceptionWithName: @"Response error"
|
|
reason: [error localizedDescription]
|
|
userInfo: nil];
|
|
@throw exception;
|
|
}
|
|
|
|
if ( [response responseStatusCode] != 200){
|
|
// there is an error with the request
|
|
NSException *exception = [NSException exceptionWithName: @"Response error"
|
|
reason: [NSString stringWithFormat:@"%d - %@",[response responseStatusCode],[response responseStatusMessage]]
|
|
userInfo: nil];
|
|
@throw exception;
|
|
}
|
|
|
|
// parse response
|
|
SBJsonParser *parser =[[SBJsonParser alloc] init];
|
|
NSDictionary *result = [parser objectWithString:[response responseString]];
|
|
|
|
// check the valid result
|
|
if (![WebService isMessageValid:result]){
|
|
// invalid message
|
|
NSException *exception = [NSException exceptionWithName: @"Incorrect request"
|
|
reason: [NSString stringWithFormat:@"%@ - %@",[result objectForKey:@"code"],[result objectForKey:@"message"]]
|
|
userInfo: nil];
|
|
@throw exception;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
- (NSArray *) parseResponse:(ASIHTTPRequest *) response
|
|
{
|
|
|
|
NSDictionary *result = [self parseResponseAsNSDictionary:response];
|
|
NSArray *array = [result objectForKey:@"result"] ;
|
|
|
|
// check if user has photos
|
|
if ([array class] == [NSNull class]){
|
|
// if it is null, return an empty array
|
|
return [NSArray array];
|
|
}else {
|
|
return array;
|
|
}
|
|
}
|
|
|
|
- (BOOL) isPhotoAlreadyOnServer:(NSString *) sha1{
|
|
NSArray *result = [self parseResponse:[self sendSynchronousRequest:[NSString stringWithFormat:@"/v1/photos/list.json?hash=%@",sha1] httpMethod:@"GET"]];
|
|
|
|
// result can be null
|
|
if ([result class] != [NSNull class]) {
|
|
NSDictionary *photo = [result objectAtIndex:0];
|
|
int totalRows = [[photo objectForKey:@"totalRows"] intValue];
|
|
return (totalRows > 0);
|
|
}
|
|
|
|
|
|
return NO;
|
|
}
|
|
|
|
- (void) validateCredentials{
|
|
// validate if the service has all details for the account
|
|
if (self.oAuthKey == nil ||
|
|
self.oAuthSecret == nil ||
|
|
self.consumerKey == nil ||
|
|
self.consumerSecret == nil){
|
|
NSException *exception = [NSException exceptionWithName: @"Unathorized Access"
|
|
reason: @"Credentials is not configured correct"
|
|
userInfo: nil];
|
|
@throw exception;
|
|
}
|
|
}
|
|
|
|
- (OAMutableURLRequest*) getUrlRequest:(NSURL *) url
|
|
{
|
|
|
|
#ifdef DEVELOPMENT_CREDENTIALS_LOG_ENABLED
|
|
NSLog(@"auth key = %@",self.oAuthKey);
|
|
NSLog(@"auth secret = %@",self.oAuthSecret);
|
|
NSLog(@"consumer key = %@",self.consumerKey);
|
|
NSLog(@"consumer key = %@",self.consumerSecret);
|
|
#endif
|
|
|
|
// token to send. We get the details from the user defaults
|
|
OAToken *token = [[OAToken alloc] initWithKey:self.oAuthKey
|
|
secret:self.oAuthSecret];
|
|
|
|
// consumer to send. We get the details from the user defaults
|
|
OAConsumer *consumer = [[OAConsumer alloc] initWithKey:self.consumerKey
|
|
secret:self.consumerSecret];
|
|
|
|
return [[OAMutableURLRequest alloc] initWithURL:url
|
|
consumer:consumer
|
|
token:token
|
|
realm:nil
|
|
signatureProvider:nil];
|
|
}
|
|
|
|
+ (BOOL) isMessageValid:(NSDictionary *)response{
|
|
// get the content of code
|
|
NSString* code = [response objectForKey:@"code"];
|
|
NSInteger icode = [code integerValue];
|
|
|
|
// is it different than 200, 201, 202, 204
|
|
if (icode != 200 && icode != 201 && icode != 202 && icode != 204)
|
|
return NO;
|
|
|
|
// another kind of message
|
|
return YES;
|
|
}
|
|
|
|
@end
|