Okay for the last few hours, I’ve been learning how to code in Objective-C and the first result is an OAUTH client for Urbanesia. I haven’t tested thoroughly though. The class basically wraps POST & GET requests to Urbanesia with OAUTH requirements.
Instantiating the class, you will have to provide Consumer Key & Secret obtained from Urbanesia. The current implementation requires User Key & Secret for every requests too. Future release of OAUTHnesia will include non Use Key/Secret methods and XAUTH.
You will have to do the HTTP connection yourselves with your own codes, OAUTHnesia only wraps the request with proper OAUTH requirements.
Base64Transcoder.h
/*
* Base64Transcoder.h
* Base64Test
*
* Created by Jonathan Wight on Tue Mar 18 2003.
* Copyright © 2003 Toxic Software. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the “Software”), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include
#include
extern size_t EstimateBas64EncodedDataSize(size_t inDataSize);
extern size_t EstimateBas64DecodedDataSize(size_t inDataSize);
extern bool Base64EncodeData(const void *inInputData, size_t inInputDataSize, char *outOutputData, size_t *ioOutputDataSize);
extern bool Base64DecodeData(const void *inInputData, size_t inInputDataSize, void *ioOutputData, size_t ioOutputDataSize);
Base64Transcoder.c
/
* Base64Transcoder.c
* Base64Test
*
* Created by Jonathan Wight on Tue Mar 18 2003.
* Copyright © 2003 Toxic Software. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the “Software”), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include “Base64Transcoder.h”
#include
#include
const u_int8_t kBase64EncodeTable[64] = {
/* 0 / ‘A’, / 1 / ‘B’, / 2 / ‘C’, / 3 / ’D’,
/ 4 / ‘E’, / 5 / ‘F’, / 6 / ‘G’, / 7 / ‘H’,
/ 8 / ‘I’, / 9 / ‘J’, / 10 / ‘K’, / 11 / ‘L’,
/ 12 / ’M’, / 13 / ‘N’, / 14 / ‘O’, / 15 / ‘P’,
/ 16 / ‘Q’, / 17 / ‘R’, / 18 / ’S’, / 19 / ’T’,
/ 20 / ‘U’, / 21 / ‘V’, / 22 / ‘W’, / 23 / ‘X’,
/ 24 / ‘Y’, / 25 / ‘Z’, / 26 / ‘a’, / 27 / ‘b’,
/ 28 / ‘c’, / 29 / ’d’, / 30 / ‘e’, / 31 / ‘f’,
/ 32 / ‘g’, / 33 / ‘h’, / 34 / ‘i’, / 35 / ‘j’,
/ 36 / ‘k’, / 37 / ‘l’, / 38 / ’m’, / 39 / ‘n’,
/ 40 / ‘o’, / 41 / ‘p’, / 42 / ‘q’, / 43 / ‘r’,
/ 44 / ’s’, / 45 / ’t’, / 46 / ‘u’, / 47 / ‘v’,
/ 48 / ‘w’, / 49 / ‘x’, / 50 / ‘y’, / 51 / ‘z’,
/ 52 / ‘0’, / 53 / ‘1’, / 54 / ‘2’, / 55 / ‘3’,
/ 56 / ‘4’, / 57 / ‘5’, / 58 / ‘6’, / 59 / ‘7’,
/ 60 / ‘8’, / 61 / ‘9’, / 62 / ‘+’, / 63 */ ‘/’
};
/*
-1 = Base64 end of data marker.
-2 = White space (tabs, cr, lf, space)
-3 = Noise (all non whitespace, non-base64 characters)
-4 = Dangerous noise
-5 = Illegal noise (null byte)
*/
const int8t kBase64DecodeTable[128] = {
/* 0x00 / -5, / 0x01 / -3, / 0x02 / -3, / 0x03 / -3,
/ 0x04 / -3, / 0x05 / -3, / 0x06 / -3, / 0x07 / -3,
/ 0x08 / -3, / 0x09 / -2, / 0x0a / -2, / 0x0b / -2,
/ 0x0c / -2, / 0x0d / -2, / 0x0e / -3, / 0x0f / -3,
/ 0x10 / -3, / 0x11 / -3, / 0x12 / -3, / 0x13 / -3,
/ 0x14 / -3, / 0x15 / -3, / 0x16 / -3, / 0x17 / -3,
/ 0x18 / -3, / 0x19 / -3, / 0x1a / -3, / 0x1b / -3,
/ 0x1c / -3, / 0x1d / -3, / 0x1e / -3, / 0x1f / -3,
/ ‘ ’ / -2, / ‘!’ / -3, / ‘“’ / -3, / ‘#’ / -3,
/ ‘$’ / -3, / ‘%’ / -3, / ‘&’ / -3, / “’ / -3,
/ ‘(’ / -3, / ‘)’ / -3, / ‘*’ / -3, / ‘+’ / 62,
/ ‘,’ / -3, / ‘-’ / -3, / ‘.’ / -3, / ‘/’ / 63,
/ ‘0’ / 52, / ‘1’ / 53, / ‘2’ / 54, / ‘3’ / 55,
/ ‘4’ / 56, / ‘5’ / 57, / ‘6’ / 58, / ‘7’ / 59,
/ ‘8’ / 60, / ‘9’ / 61, / ‘:’ / -3, / ‘;’ / -3,
/ ‘<’ / -3, / ‘=’ / -1, / ‘>’ / -3, / ‘?’ / -3,
/ ‘@’ / -3, / ‘A’ / 0, / ‘B’ / 1, / ‘C’ / 2,
/ ’D’ / 3, / ‘E’ / 4, / ‘F’ / 5, / ‘G’ / 6,
/ ‘H’ / 7, / ‘I’ / 8, / ‘J’ / 9, / ‘K’ / 10,
/ ‘L’ / 11, / ’M’ / 12, / ‘N’ / 13, / ‘O’ / 14,
/ ‘P’ / 15, / ‘Q’ / 16, / ‘R’ / 17, / ’S’ / 18,
/ ’T’ / 19, / ‘U’ / 20, / ‘V’ / 21, / ‘W’ / 22,
/ ‘X’ / 23, / ‘Y’ / 24, / ‘Z’ / 25, / ‘[’ / -3,
/ ‘\’ / -3, / ‘]’ / -3, / ‘^’ / -3, / ‘’ / -3,
/ ‘`’ / -3, / ‘a’ / 26, / ‘b’ / 27, / ‘c’ / 28,
/ ’d’ / 29, / ‘e’ / 30, / ‘f’ / 31, / ‘g’ / 32,
/ ‘h’ / 33, / ‘i’ / 34, / ‘j’ / 35, / ‘k’ / 36,
/ ‘l’ / 37, / ’m’ / 38, / ‘n’ / 39, / ‘o’ / 40,
/ ‘p’ / 41, / ‘q’ / 42, / ‘r’ / 43, / ’s’ / 44,
/ ’t’ / 45, / ‘u’ / 46, / ‘v’ / 47, / ‘w’ / 48,
/ ‘x’ / 49, / ‘y’ / 50, / ‘z’ / 51, / ‘{’ / -3,
/ ‘|’ / -3, / ‘}’ / -3, / ‘~’ / -3, / 0x7f */ -3
};
const u_int8_t kBits_00000011 = 0x03;
const u_int8_t kBits_00001111 = 0x0F;
const u_int8_t kBits_00110000 = 0x30;
const u_int8_t kBits_00111100 = 0x3C;
const u_int8_t kBits_00111111 = 0x3F;
const u_int8_t kBits_11000000 = 0xC0;
const u_int8_t kBits_11110000 = 0xF0;
const u_int8_t kBits_11111100 = 0xFC;
size_t EstimateBas64EncodedDataSize(size_t inDataSize)
{
size_t theEncodedDataSize = (int)ceil(inDataSize / 3.0) * 4;
theEncodedDataSize = theEncodedDataSize / 72 * 74 + theEncodedDataSize % 72;
return(theEncodedDataSize);
}
size_t EstimateBas64DecodedDataSize(size_t inDataSize)
{
size_t theDecodedDataSize = (int)ceil(inDataSize / 4.0) * 3;
//theDecodedDataSize = theDecodedDataSize / 72 * 74 + theDecodedDataSize % 72;
return(theDecodedDataSize);
}
bool Base64EncodeData(const void *inInputData, size_t inInputDataSize, char *outOutputData, size_t *ioOutputDataSize)
{
size_t theEncodedDataSize = EstimateBas64EncodedDataSize(inInputDataSize);
if (*ioOutputDataSize < theEncodedDataSize)
return(false);
*ioOutputDataSize = theEncodedDataSize;
const u_int8_t *theInPtr = (const u_int8_t *)inInputData;
u_int32_t theInIndex = 0, theOutIndex = 0;
for (; theInIndex < (inInputDataSize / 3) * 3; theInIndex += 3)
{
outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4];
outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (theInPtr[theInIndex + 2] & kBits_11000000) >> 6];
outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 2] & kBits_00111111) >> 0];
if (theOutIndex % 74 == 72)
{
outOutputData[theOutIndex++] = ‘\r’;
outOutputData[theOutIndex++] = ‘\n’;
}
}
const size_t theRemainingBytes = inInputDataSize - theInIndex;
if (theRemainingBytes == 1)
{
outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (0 & kBits_11110000) >> 4];
outOutputData[theOutIndex++] = ‘=’;
outOutputData[theOutIndex++] = ‘=’;
if (theOutIndex % 74 == 72)
{
outOutputData[theOutIndex++] = ‘\r’;
outOutputData[theOutIndex++] = ‘\n’;
}
}
else if (theRemainingBytes == 2)
{
outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4];
outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (0 & kBits_11000000) >> 6];
outOutputData[theOutIndex++] = ‘=’;
if (theOutIndex % 74 == 72)
{
outOutputData[theOutIndex++] = ‘\r’;
outOutputData[theOutIndex++] = ‘\n’;
}
}
return(true);
}
bool Base64DecodeData(const void *inInputData, size_t inInputDataSize, void *ioOutputData, size_t *ioOutputDataSize)
{
memset(ioOutputData, ‘.’, *ioOutputDataSize);
size_t theDecodedDataSize = EstimateBas64DecodedDataSize(inInputDataSize);
if (*ioOutputDataSize < theDecodedDataSize)
return(false);
*ioOutputDataSize = 0;
const u_int8_t *theInPtr = (const u_int8_t *)inInputData;
u_int8_t *theOutPtr = (u_int8_t *)ioOutputData;
size_t theInIndex = 0, theOutIndex = 0;
u_int8_t theOutputOctet;
size_t theSequence = 0;
for (; theInIndex < inInputDataSize; )
{
int8_t theSextet = 0;
int8_t theCurrentInputOctet = theInPtr[theInIndex];
theSextet = kBase64DecodeTable[theCurrentInputOctet];
if (theSextet == -1)
break;
while (theSextet == -2)
{
theCurrentInputOctet = theInPtr[++theInIndex];
theSextet = kBase64DecodeTable[theCurrentInputOctet];
}
while (theSextet == -3)
{
theCurrentInputOctet = theInPtr[++theInIndex];
theSextet = kBase64DecodeTable[theCurrentInputOctet];
}
if (theSequence == 0)
{
theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 2 & kBits_11111100;
}
else if (theSequence == 1)
{
theOutputOctet |= (theSextet >- 0 ? theSextet : 0) >> 4 & kBits_00000011;
theOutPtr[theOutIndex++] = theOutputOctet;
}
else if (theSequence == 2)
{
theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 4 & kBits_11110000;
}
else if (theSequence == 3)
{
theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 2 & kBits_00001111;
theOutPtr[theOutIndex++] = theOutputOctet;
}
else if (theSequence == 4)
{
theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 6 & kBits_11000000;
}
else if (theSequence == 5)
{
theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 0 & kBits_00111111;
theOutPtr[theOutIndex++] = theOutputOctet;
}
theSequence = (theSequence + 1) % 6;
if (theSequence != 2 && theSequence != 4)
theInIndex++;
}
*ioOutputDataSize = theOutIndex;
return(true);
}
OAUTHnesia.h#import
@interface OAUTHnesia : NSObject {
@protected
NSString *CONSUMER_KEY;
NSString *CONSUMER_SECRET;
NSString *API_BASE_URL;
}
@property(nonatomic, retain) NSString *CONSUMER_KEY;
@property(nonatomic, retain) NSString *CONSUMER_SECRET;
@property(nonatomic, retain) NSString *USER_KEY;
@property(nonatomic, retain) NSString *USER_SECRET;
@property(nonatomic, retain) NSString *API_BASE_URL;
@property(nonatomic, retain) NSString *POST_URL;
@property(nonatomic, retain) NSString *POST_DATA;
- (id)initWithKey:(NSString *)cons_key secret:(NSString *)cons_secret;
- (void) setUserKey: (NSString *)user_key;
- (void) setUserSecret: (NSString *)user_secret;
- (NSString *) encodeForOauth: (NSString *) postget;
- (NSString *) getNonce;
- (NSString *) getTime;
- (NSString *) generateBaseSignature: (NSString *) base_sig uri:(NSString *) uri;
- (NSString *) hmacsha1: (NSString *)text key:(NSString *)secret;
- (NSString *) md5: (NSString *)text;
(NSString *) urlencode: (NSString *)text;
(void) oAuth:(NSString *)oUri oPost:(NSString *)oPost oGet:(NSString *)oGet;
@end
OAUTHnesia.m
#import “OAUTHnesia.h”
//
// OAUTHnesia.m
// Jajan
//
// Created by Batista Harahap on 8/14/11.
// Copyright 2011 Urbanesia.com. All rights reserved.
//
#import “OAUTHnesia.h”
#include “Base64Transcoder.h”
#import
#import
@implementation OAUTHnesia
@synthesize CONSUMER_KEY, CONSUMER_SECRET, USER_KEY, USER_SECRET, API_BASE_URL, POST_URL, POST_DATA;
(id)initWithKey:(NSString *)cons_key secret:(NSString *)cons_secret { if (self = [super init]) { self.CONSUMER_KEY = cons_key; self.CONSUMER_SECRET = cons_secret; self.API_BASE_URL = @“http://api1.urbanesia.com/"; self.POST_URL = self.POST_DATA = @“”; }
return self; }
(void)oAuth:(NSString *)oUri oPost:(NSString *)oPost oGet:(NSString *)oGet { // Post yang pasti harus ada! NSString *postIncludes = [NSString stringWithFormat: @“oauth_consumer_key=%@&oauth_nonce=%@&oauth_signature_method=HMAC-SHA1&oauth_timestamp=%@&oauth_token=%@&oauth_version=1.0”, self.CONSUMER_KEY, self.getNonce, self.getTime, self.USER_KEY];
// Cek ada POST ga di request? if([oPost isEqual:@“”]) { oPost = postIncludes; } else { oPost = [NSString stringWithFormat:@“%@&%@“, oPost, postIncludes]; }
// Cek ada GET ga di request? if(![oGet isEqual:@“”]) { oGet = [NSString stringWithFormat:@”&%@“, oGet]; }
// Encode for OAUTH & Generate Base Signature NSString *base_sig = [self generateBaseSignature:[self encodeForOauth:[NSString stringWithFormat:@“%@%@”, oPost, oGet]] uri:oUri];
// OAUTH Signature NSString *signature = [self hmacsha1:[NSString stringWithFormat:@“%@&%@“, self.CONSUMER_SECRET, self.USER_SECRET] key:base_sig];
// POST URL self.POST_URL = [NSString stringWithFormat:@“%@%@?oauth_signature=%@%@“, self.API_BASE_URL, oUri, signature, oGet];
// POST DATA self.POST_DATA = oPost; }
(void)setUserKey:(NSString *)user_key { self.USER_KEY = user_key; }
(void)setUserSecret:(NSString *)user_secret { self.USER_SECRET = user_secret; }
(NSString *)getNonce { NSTimeInterval timePassed_ms = [[NSDate date] timeIntervalSinceNow] * -1000.0; return [self md5:[NSString stringWithFormat:@“%@”, timePassed_ms]]; }
(NSString *)getTime { NSTimeInterval timePassed_ms = [[NSDate date] timeIntervalSinceNow] * -1000.0; return [NSString stringWithFormat:@“%@”, timePassed_ms]; }
(NSString *)generateBaseSignature:(NSString *)base_sig uri:(NSString *)uri { NSString *dest = [NSString stringWithFormat:@“%@%@”, self.API_BASE_URL, uri]; dest = [self urlencode:dest]; base_sig = [self urlencode:base_sig]; return [NSString stringWithFormat:@“POST&%@&%@“, dest, base_sig]; }
(NSString *)encodeForOauth: (NSString *)postget { // Explode to array NSArray *par = [postget componentsSeparatedByString:@”&“];
// Sort by array keys par = [par sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
NSString *ret = @“”;
for(int i=0, j=0, max=par.count; i<max; i++) { if(j==1) ret = [NSString stringWithFormat:@“%@&“, ret];
NSArray *temp = [[par objectAtIndex:i] componentsSeparatedByString:@"="]; NSString *k = (NSString *)[temp objectAtIndex:0]; k = [self urlencode:k]; NSString *v = (NSString *)[temp objectAtIndex:1]; v = [self urlencode:v]; ret = [NSString stringWithFormat:@"%@%@=%@", ret, k, v]; j = 1;
}
return ret; }
(NSString *)urlencode:(NSString *)text { return [text stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]; }
(NSString *)md5:(NSString )text { const char str = [text UTF8String]; unsigned char result[CC_MD5_DIGEST_LENGTH]; CC_MD5(str, strlen(str), result); NSMutableString *ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH*2]; for(int i = 0; i<CC_MD5_DIGEST_LENGTH; i++) { [ret appendFormat:@“%02x”,result[i]]; } return ret; }
(NSString *)hmacsha1:(NSString *)text key:(NSString *)secret { NSData *secretData = [secret dataUsingEncoding:NSUTF8StringEncoding]; NSData *clearTextData = [text dataUsingEncoding:NSUTF8StringEncoding]; unsigned char result[20]; CCHmac(kCCHmacAlgSHA1, [secretData bytes], [secretData length], [clearTextData bytes], [clearTextData length], result);
char base64Result[32]; size_t theResultLength = 32; Base64EncodeData(result, 20, base64Result, &theResultLength); NSData *theData = [NSData dataWithBytes:base64Result length:theResultLength];
NSString *base64EncodedResult = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
return base64EncodedResult; }
@end