2
0
MasterPassword/External/google-plus-ios-sdk/OpenSource/GTL/GTLBase64.m

140 lines
4.5 KiB
Mathematica
Raw Normal View History

/* Copyright (c) 2012 Google Inc.
*
* 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 "GTLBase64.h"
// Based on Cyrus Najmabadi's elegent little encoder and decoder from
// http://www.cocoadev.com/index.pl?BaseSixtyFour
static char gStandardEncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static char gWebSafeEncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
#pragma mark Encode
static NSString *EncodeBase64StringCommon(NSData *data, const char *table) {
if (data == nil) return nil;
const uint8_t* input = [data bytes];
NSUInteger length = [data length];
NSUInteger bufferSize = ((length + 2) / 3) * 4;
NSMutableData* buffer = [NSMutableData dataWithLength:bufferSize];
uint8_t *output = [buffer mutableBytes];
for (NSUInteger i = 0; i < length; i += 3) {
NSUInteger value = 0;
for (NSUInteger j = i; j < (i + 3); j++) {
value <<= 8;
if (j < length) {
value |= (0xFF & input[j]);
}
}
NSInteger idx = (i / 3) * 4;
output[idx + 0] = table[(value >> 18) & 0x3F];
output[idx + 1] = table[(value >> 12) & 0x3F];
output[idx + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '=';
output[idx + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '=';
}
NSString *result = [[[NSString alloc] initWithData:buffer
encoding:NSASCIIStringEncoding] autorelease];
return result;
}
NSString *GTLEncodeBase64(NSData *data) {
return EncodeBase64StringCommon(data, gStandardEncodingTable);
}
NSString *GTLEncodeWebSafeBase64(NSData *data) {
return EncodeBase64StringCommon(data, gWebSafeEncodingTable);
}
#pragma mark Decode
static void CreateDecodingTable(const char *encodingTable,
size_t encodingTableSize, char *decodingTable) {
memset(decodingTable, 0, 128);
for (unsigned int i = 0; i < encodingTableSize; i++) {
decodingTable[(unsigned int) encodingTable[i]] = i;
}
}
static NSData *DecodeBase64StringCommon(NSString *base64Str,
char *decodingTable) {
// The input string should be plain ASCII
const char *cString = [base64Str cStringUsingEncoding:NSASCIIStringEncoding];
if (cString == nil) return nil;
NSUInteger inputLength = strlen(cString);
if (inputLength % 4 != 0) return nil;
if (inputLength == 0) return [NSData data];
while (inputLength > 0 && cString[inputLength - 1] == '=') {
inputLength--;
}
NSInteger outputLength = inputLength * 3 / 4;
NSMutableData* data = [NSMutableData dataWithLength:outputLength];
uint8_t *output = [data mutableBytes];
NSInteger inputPoint = 0;
NSInteger outputPoint = 0;
char *table = decodingTable;
while (inputPoint < inputLength) {
int i0 = cString[inputPoint++];
int i1 = cString[inputPoint++];
int i2 = inputPoint < inputLength ? cString[inputPoint++] : 'A'; // 'A' will decode to \0
int i3 = inputPoint < inputLength ? cString[inputPoint++] : 'A';
output[outputPoint++] = (table[i0] << 2) | (table[i1] >> 4);
if (outputPoint < outputLength) {
output[outputPoint++] = ((table[i1] & 0xF) << 4) | (table[i2] >> 2);
}
if (outputPoint < outputLength) {
output[outputPoint++] = ((table[i2] & 0x3) << 6) | table[i3];
}
}
return data;
}
NSData *GTLDecodeBase64(NSString *base64Str) {
static char decodingTable[128];
static BOOL hasInited = NO;
if (!hasInited) {
CreateDecodingTable(gStandardEncodingTable, sizeof(gStandardEncodingTable),
decodingTable);
hasInited = YES;
}
return DecodeBase64StringCommon(base64Str, decodingTable);
}
NSData *GTLDecodeWebSafeBase64(NSString *base64Str) {
static char decodingTable[128];
static BOOL hasInited = NO;
if (!hasInited) {
CreateDecodingTable(gWebSafeEncodingTable, sizeof(gWebSafeEncodingTable),
decodingTable);
hasInited = YES;
}
return DecodeBase64StringCommon(base64Str, decodingTable);
}