ecency-mobile/ios/Pods/Base64/Base64/MF_Base64Additions.m
2019-01-22 23:02:15 +02:00

252 lines
11 KiB
Objective-C
Executable File

//
// MF_Base64Additions.m
// Base64 -- RFC 4648 compatible implementation
// see http://www.ietf.org/rfc/rfc4648.txt for more details
//
// Designed to be compiled with Automatic Reference Counting
//
// Created by Dave Poirier on 2012-06-14.
// Public Domain
// Hosted at https://github.com/ekscrypto/Base64
//
#import "MF_Base64Additions.h"
@implementation MF_Base64Codec
+(NSString *)base64StringFromBase64UrlEncodedString:(NSString *)base64UrlEncodedString
{
NSString *s = base64UrlEncodedString;
s = [s stringByReplacingOccurrencesOfString:@"-" withString:@"+"];
s = [s stringByReplacingOccurrencesOfString:@"_" withString:@"/"];
switch (s.length % 4) {
case 2:
s = [s stringByAppendingString:@"=="];
break;
case 3:
s = [s stringByAppendingString:@"="];
break;
default:
break;
}
return s;
}
+(NSString *)base64UrlEncodedStringFromBase64String:(NSString *)base64String
{
NSString *s = base64String;
s = [s stringByReplacingOccurrencesOfString:@"=" withString:@""];
s = [s stringByReplacingOccurrencesOfString:@"+" withString:@"-"];
s = [s stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
return s;
}
+(NSData *)dataFromBase64String:(NSString *)encoding
{
NSData *data = nil;
unsigned char *decodedBytes = NULL;
@try {
#define __ 255
static char decodingTable[256] = {
__,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0x00 - 0x0F
__,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0x10 - 0x1F
__,__,__,__, __,__,__,__, __,__,__,62, __,__,__,63, // 0x20 - 0x2F
52,53,54,55, 56,57,58,59, 60,61,__,__, __, 0,__,__, // 0x30 - 0x3F
__, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, // 0x40 - 0x4F
15,16,17,18, 19,20,21,22, 23,24,25,__, __,__,__,__, // 0x50 - 0x5F
__,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, // 0x60 - 0x6F
41,42,43,44, 45,46,47,48, 49,50,51,__, __,__,__,__, // 0x70 - 0x7F
__,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0x80 - 0x8F
__,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0x90 - 0x9F
__,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0xA0 - 0xAF
__,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0xB0 - 0xBF
__,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0xC0 - 0xCF
__,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0xD0 - 0xDF
__,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0xE0 - 0xEF
__,__,__,__, __,__,__,__, __,__,__,__, __,__,__,__, // 0xF0 - 0xFF
};
encoding = [encoding stringByReplacingOccurrencesOfString:@"=" withString:@""];
NSData *encodedData = [encoding dataUsingEncoding:NSASCIIStringEncoding];
unsigned char *encodedBytes = (unsigned char *)[encodedData bytes];
NSUInteger encodedLength = [encodedData length];
if( encodedLength >= (NSUIntegerMax - 3) ) return nil; // NSUInteger overflow check
NSUInteger encodedBlocks = (encodedLength+3) >> 2;
NSUInteger expectedDataLength = encodedBlocks * 3;
unsigned char decodingBlock[4];
decodedBytes = malloc(expectedDataLength);
if( decodedBytes != NULL ) {
NSUInteger i = 0;
NSUInteger j = 0;
NSUInteger k = 0;
unsigned char c;
while( i < encodedLength ) {
c = decodingTable[encodedBytes[i]];
i++;
if( c != __ ) {
decodingBlock[j] = c;
j++;
if( j == 4 ) {
decodedBytes[k] = (decodingBlock[0] << 2) | (decodingBlock[1] >> 4);
decodedBytes[k+1] = (decodingBlock[1] << 4) | (decodingBlock[2] >> 2);
decodedBytes[k+2] = (decodingBlock[2] << 6) | (decodingBlock[3]);
j = 0;
k += 3;
}
}
}
// Process left over bytes, if any
if( j == 3 ) {
decodedBytes[k] = (decodingBlock[0] << 2) | (decodingBlock[1] >> 4);
decodedBytes[k+1] = (decodingBlock[1] << 4) | (decodingBlock[2] >> 2);
k += 2;
} else if( j == 2 ) {
decodedBytes[k] = (decodingBlock[0] << 2) | (decodingBlock[1] >> 4);
k += 1;
}
data = [[NSData alloc] initWithBytes:decodedBytes length:k];
}
}
@catch (NSException *exception) {
data = nil;
NSLog(@"WARNING: error occured while decoding base 32 string: %@", exception);
}
@finally {
if( decodedBytes != NULL ) {
free( decodedBytes );
}
}
return data;
}
+(NSString *)base64StringFromData:(NSData *)data
{
NSString *encoding = nil;
unsigned char *encodingBytes = NULL;
@try {
static char encodingTable[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static NSUInteger paddingTable[] = {0,2,1};
// Table 1: The Base 64 Alphabet
//
// Value Encoding Value Encoding Value Encoding Value Encoding
// 0 A 17 R 34 i 51 z
// 1 B 18 S 35 j 52 0
// 2 C 19 T 36 k 53 1
// 3 D 20 U 37 l 54 2
// 4 E 21 V 38 m 55 3
// 5 F 22 W 39 n 56 4
// 6 G 23 X 40 o 57 5
// 7 H 24 Y 41 p 58 6
// 8 I 25 Z 42 q 59 7
// 9 J 26 a 43 r 60 8
// 10 K 27 b 44 s 61 9
// 11 L 28 c 45 t 62 +
// 12 M 29 d 46 u 63 /
// 13 N 30 e 47 v
// 14 O 31 f 48 w (pad) =
// 15 P 32 g 49 x
// 16 Q 33 h 50 y
NSUInteger dataLength = [data length];
NSUInteger encodedBlocks = dataLength / 3;
if( (encodedBlocks + 1) >= (NSUIntegerMax / 4) ) return nil; // NSUInteger overflow check
NSUInteger padding = paddingTable[dataLength % 3];
if( padding > 0 ) encodedBlocks++;
NSUInteger encodedLength = encodedBlocks * 4;
encodingBytes = malloc(encodedLength);
if( encodingBytes != NULL ) {
NSUInteger rawBytesToProcess = dataLength;
NSUInteger rawBaseIndex = 0;
NSUInteger encodingBaseIndex = 0;
unsigned char *rawBytes = (unsigned char *)[data bytes];
unsigned char rawByte1, rawByte2, rawByte3;
while( rawBytesToProcess >= 3 ) {
rawByte1 = rawBytes[rawBaseIndex];
rawByte2 = rawBytes[rawBaseIndex+1];
rawByte3 = rawBytes[rawBaseIndex+2];
encodingBytes[encodingBaseIndex] = encodingTable[((rawByte1 >> 2) & 0x3F)];
encodingBytes[encodingBaseIndex+1] = encodingTable[((rawByte1 << 4) & 0x30) | ((rawByte2 >> 4) & 0x0F) ];
encodingBytes[encodingBaseIndex+2] = encodingTable[((rawByte2 << 2) & 0x3C) | ((rawByte3 >> 6) & 0x03) ];
encodingBytes[encodingBaseIndex+3] = encodingTable[(rawByte3 & 0x3F)];
rawBaseIndex += 3;
encodingBaseIndex += 4;
rawBytesToProcess -= 3;
}
rawByte2 = 0;
switch (dataLength-rawBaseIndex) {
case 2:
rawByte2 = rawBytes[rawBaseIndex+1];
case 1:
rawByte1 = rawBytes[rawBaseIndex];
encodingBytes[encodingBaseIndex] = encodingTable[((rawByte1 >> 2) & 0x3F)];
encodingBytes[encodingBaseIndex+1] = encodingTable[((rawByte1 << 4) & 0x30) | ((rawByte2 >> 4) & 0x0F) ];
encodingBytes[encodingBaseIndex+2] = encodingTable[((rawByte2 << 2) & 0x3C) ];
// we can skip rawByte3 since we have a partial block it would always be 0
break;
}
// compute location from where to begin inserting padding, it may overwrite some bytes from the partial block encoding
// if their value was 0 (cases 1-2).
encodingBaseIndex = encodedLength - padding;
while( padding-- > 0 ) {
encodingBytes[encodingBaseIndex++] = '=';
}
encoding = [[NSString alloc] initWithBytes:encodingBytes length:encodedLength encoding:NSASCIIStringEncoding];
}
}
@catch (NSException *exception) {
encoding = nil;
NSLog(@"WARNING: error occured while tring to encode base 32 data: %@", exception);
}
@finally {
if( encodingBytes != NULL ) {
free( encodingBytes );
}
}
return encoding;
}
@end
@implementation NSString (Base64Addition)
-(NSString *)base64String
{
NSData *utf8encoding = [self dataUsingEncoding:NSUTF8StringEncoding];
return [MF_Base64Codec base64StringFromData:utf8encoding];
}
-(NSString *)base64UrlEncodedString
{
return [MF_Base64Codec base64UrlEncodedStringFromBase64String:[self base64String]];
}
+(NSString *)stringFromBase64String:(NSString *)base64String
{
NSData *utf8encoding = [MF_Base64Codec dataFromBase64String:base64String];
return [[NSString alloc] initWithData:utf8encoding encoding:NSUTF8StringEncoding];
}
+(NSString *)stringFromBase64UrlEncodedString:(NSString *)base64UrlEncodedString
{
return [self stringFromBase64String:[MF_Base64Codec base64StringFromBase64UrlEncodedString:base64UrlEncodedString]];
}
@end
@implementation NSData (Base64Addition)
+(NSData *)dataWithBase64String:(NSString *)base64String
{
return [MF_Base64Codec dataFromBase64String:base64String];
}
+(NSData *)dataWithBase64UrlEncodedString:(NSString *)base64UrlEncodedString
{
return [self dataWithBase64String:[MF_Base64Codec base64StringFromBase64UrlEncodedString:base64UrlEncodedString]];
}
-(NSString *)base64String
{
return [MF_Base64Codec base64StringFromData:self];
}
-(NSString *)base64UrlEncodedString
{
return [MF_Base64Codec base64UrlEncodedStringFromBase64String:[self base64String]];
}
@end