mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-22 04:41:43 +03:00
252 lines
11 KiB
Objective-C
Executable File
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 |