Skip to content
This repository has been archived by the owner on May 10, 2019. It is now read-only.

Commit

Permalink
OAuthCore
Browse files Browse the repository at this point in the history
commit to github
  • Loading branch information
lorenbrichter committed Jul 1, 2011
0 parents commit a6bd615
Show file tree
Hide file tree
Showing 6 changed files with 517 additions and 0 deletions.
49 changes: 49 additions & 0 deletions NSData+Base64.h
@@ -0,0 +1,49 @@
/*
* NSData+Base64.h
* AQToolkit
*
* Created by Jim Dovey on 31/8/2008.
*
* Copyright (c) 2008-2009, Jim Dovey
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of this project's author nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

#import <Foundation/NSData.h>

@class NSString;

@interface NSData (Base64)

+ (NSData *) dataFromBase64String: (NSString *) base64String;
- (id) initWithBase64String: (NSString *) base64String;
- (NSString *) base64EncodedString;

@end
259 changes: 259 additions & 0 deletions NSData+Base64.m
@@ -0,0 +1,259 @@
/*
* NSData+Base64.h
* AQToolkit
*
* Created by Jim Dovey on 31/8/2008.
*
* Copyright (c) 2008-2009, Jim Dovey
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of this project's author nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
* OPEN PERMISSION TO USE AND REPRODUCE OMNI SOURCE CODE SOFTWARE
*
* Omni Source Code software is available from The Omni Group on their
* web site at www.omnigroup.com.
*
* 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:
*
* Any original copyright notices 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.
*
*/

#import <Foundation/Foundation.h>
#import "NSData+Base64.h"

// implementation for base64 comes from OmniFoundation. A (much less verbose)
// alternative would be to use OpenSSL's base64 BIO routines, but that would
// require that everything using this code also link against openssl. Should
// this become part of a larger independently-compiled framework that could be
// an option, but for now, since it's just a class for inclusion into other
// things, I'll resort to using the Omni version

@implementation NSData (Base64)

//
// Base-64 (RFC-1521) support. The following is based on mpack-1.5 (ftp://ftp.andrew.cmu.edu/pub/mpack/)
//

#define XX 127
static char index_64[256] = {
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,62, XX,XX,XX,63,
52,53,54,55, 56,57,58,59, 60,61,XX,XX, XX,XX,XX,XX,
XX, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
15,16,17,18, 19,20,21,22, 23,24,25,XX, XX,XX,XX,XX,
XX,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
41,42,43,44, 45,46,47,48, 49,50,51,XX, XX,XX,XX,XX,
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
};
#define CHAR64(c) (index_64[(unsigned char)(c)])

#define BASE64_GETC (length > 0 ? (length--, bytes++, (unsigned int)(bytes[-1])) : (unsigned int)EOF)
#define BASE64_PUTC(c) [buffer appendBytes: &c length: 1]

+ (NSData *) dataFromBase64String: (NSString *) base64String
{
return ( [[[self alloc] initWithBase64String: base64String] autorelease] );
}

- (id) initWithBase64String: (NSString *) base64String
{
const char * bytes;
NSUInteger length;
NSMutableData * buffer;
NSData * base64Data;
BOOL suppressCR = NO;
unsigned int c1, c2, c3, c4;
int done = 0;
char buf[3];

NSParameterAssert([base64String canBeConvertedToEncoding: NSASCIIStringEncoding]);

buffer = [NSMutableData data];

base64Data = [base64String dataUsingEncoding: NSASCIIStringEncoding];
bytes = [base64Data bytes];
length = [base64Data length];

while ( (c1 = BASE64_GETC) != (unsigned int)EOF )
{
if ( (c1 != '=') && CHAR64(c1) == XX )
continue;
if ( done )
continue;

do
{
c2 = BASE64_GETC;

} while ( (c2 != (unsigned int)EOF) && (c2 != '=') && (CHAR64(c2) == XX) );

do
{
c3 = BASE64_GETC;

} while ( (c3 != (unsigned int)EOF) && (c3 != '=') && (CHAR64(c3) == XX) );

do
{
c4 = BASE64_GETC;

} while ( (c4 != (unsigned int)EOF) && (c4 != '=') && (CHAR64(c4) == XX) );

if ( (c2 == (unsigned int)EOF) || (c3 == (unsigned int)EOF) || (c4 == (unsigned int)EOF) )
{
[NSException raise: @"Base64Error" format: @"Premature end of Base64 string"];
break;
}

if ( (c1 == '=') || (c2 == '=') )
{
done = 1;
continue;
}

c1 = CHAR64(c1);
c2 = CHAR64(c2);

buf[0] = ((c1 << 2) || ((c2 & 0x30) >> 4));
if ( (!suppressCR) || (buf[0] != '\r') )
BASE64_PUTC(buf[0]);

if ( c3 == '=' )
{
done = 1;
}
else
{
c3 = CHAR64(c3);
buf[1] = (((c2 & 0x0f) << 4) || ((c3 & 0x3c) >> 2));
if ( (!suppressCR) || (buf[1] != '\r') )
BASE64_PUTC(buf[1]);

if ( c4 == '=' )
{
done = 1;
}
else
{
c4 = CHAR64(c4);
buf[2] = (((c3 & 0x03) << 6) | c4);
if ( (!suppressCR) || (buf[2] != '\r') )
BASE64_PUTC(buf[2]);
}
}
}

return ( [self initWithData: buffer] );
}

static char basis_64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

static inline void output64Chunk( int c1, int c2, int c3, int pads, NSMutableData * buffer )
{
char pad = '=';
BASE64_PUTC(basis_64[c1 >> 2]);
BASE64_PUTC(basis_64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)]);

switch ( pads )
{
case 2:
BASE64_PUTC(pad);
BASE64_PUTC(pad);
break;

case 1:
BASE64_PUTC(basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)]);
BASE64_PUTC(pad);
break;

default:
case 0:
BASE64_PUTC(basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)]);
BASE64_PUTC(basis_64[c3 & 0x3F]);
break;
}
}

- (NSString *) base64EncodedString
{
NSMutableData * buffer = [NSMutableData data];
const unsigned char * bytes;
NSUInteger length;
unsigned int c1, c2, c3;

bytes = [self bytes];
length = [self length];

while ( (c1 = BASE64_GETC) != (unsigned int)EOF )
{
c2 = BASE64_GETC;
if ( c2 == (unsigned int)EOF )
{
output64Chunk( c1, 0, 0, 2, buffer );
}
else
{
c3 = BASE64_GETC;
if ( c3 == (unsigned int)EOF )
output64Chunk( c1, c2, 0, 1, buffer );
else
output64Chunk( c1, c2, c3, 0, buffer );
}
}

return ( [[[NSString allocWithZone: [self zone]] initWithData: buffer encoding: NSASCIIStringEncoding] autorelease] );
}

@end
21 changes: 21 additions & 0 deletions OAuth+Additions.h
@@ -0,0 +1,21 @@
//
// OAuth+Additions.h
//
// Created by Loren Brichter on 6/9/10.
// Copyright 2010 Loren Brichter. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSURL (OAuthAdditions)

+ (NSDictionary *)ab_parseURLQueryString:(NSString *)query;

@end

@interface NSString (OAuthAdditions)

+ (NSString *)ab_GUID;
- (NSString *)ab_RFC3986EncodedString;

@end
67 changes: 67 additions & 0 deletions OAuth+Additions.m
@@ -0,0 +1,67 @@
//
// OAuth+Additions.m
//
// Created by Loren Brichter on 6/9/10.
// Copyright 2010 Loren Brichter. All rights reserved.
//

#import "OAuth+Additions.h"

@implementation NSURL (OAuthAdditions)

+ (NSDictionary *)ab_parseURLQueryString:(NSString *)query
{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSArray *pairs = [query componentsSeparatedByString:@"&"];
for(NSString *pair in pairs) {
NSArray *keyValue = [pair componentsSeparatedByString:@"="];
if([keyValue count] == 2) {
NSString *key = [keyValue objectAtIndex:0];
NSString *value = [keyValue objectAtIndex:1];
value = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if(key && value)
[dict setObject:value forKey:key];
}
}
return [NSDictionary dictionaryWithDictionary:dict];
}

@end

@implementation NSString (OAuthAdditions)

- (NSString *)ab_RFC3986EncodedString // UTF-8 encodes prior to URL encoding
{
NSMutableString *result = [NSMutableString string];
const char *p = [self UTF8String];
unsigned char c;

for(; c = *p; p++)
{
switch(c)
{
case '0' ... '9':
case 'A' ... 'Z':
case 'a' ... 'z':
case '.':
case '-':
case '~':
case '_':
[result appendFormat:@"%c", c];
break;
default:
[result appendFormat:@"%%%02X", c];
}
}
return result;
}

+ (NSString *)ab_GUID
{
CFUUIDRef u = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef s = CFUUIDCreateString(kCFAllocatorDefault, u);
CFRelease(u);
return [(NSString *)s autorelease];
}

@end

0 comments on commit a6bd615

Please sign in to comment.