You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
643 lines
21 KiB
643 lines
21 KiB
1 year ago
|
//
|
||
|
// NSData+YYAdd.m
|
||
|
// YYKit <https://github.com/ibireme/YYKit>
|
||
|
//
|
||
|
// Created by ibireme on 13/4/4.
|
||
|
// Copyright (c) 2015 ibireme.
|
||
|
//
|
||
|
// This source code is licensed under the MIT-style license found in the
|
||
|
// LICENSE file in the root directory of this source tree.
|
||
|
//
|
||
|
|
||
|
#import "NSData+YYAdd.h"
|
||
|
#import "YYKitMacro.h"
|
||
|
#include <CommonCrypto/CommonCrypto.h>
|
||
|
#include <zlib.h>
|
||
|
|
||
|
YYSYNTH_DUMMY_CLASS(NSData_YYAdd)
|
||
|
|
||
|
|
||
|
@implementation NSData (YYAdd)
|
||
|
|
||
|
- (NSString *)md2String {
|
||
|
unsigned char result[CC_MD2_DIGEST_LENGTH];
|
||
|
CC_MD2(self.bytes, (CC_LONG)self.length, result);
|
||
|
return [NSString stringWithFormat:
|
||
|
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||
|
result[0], result[1], result[2], result[3],
|
||
|
result[4], result[5], result[6], result[7],
|
||
|
result[8], result[9], result[10], result[11],
|
||
|
result[12], result[13], result[14], result[15]
|
||
|
];
|
||
|
}
|
||
|
|
||
|
- (NSData *)md2Data {
|
||
|
unsigned char result[CC_MD2_DIGEST_LENGTH];
|
||
|
CC_MD2(self.bytes, (CC_LONG)self.length, result);
|
||
|
return [NSData dataWithBytes:result length:CC_MD2_DIGEST_LENGTH];
|
||
|
}
|
||
|
|
||
|
- (NSString *)md4String {
|
||
|
unsigned char result[CC_MD4_DIGEST_LENGTH];
|
||
|
CC_MD4(self.bytes, (CC_LONG)self.length, result);
|
||
|
return [NSString stringWithFormat:
|
||
|
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||
|
result[0], result[1], result[2], result[3],
|
||
|
result[4], result[5], result[6], result[7],
|
||
|
result[8], result[9], result[10], result[11],
|
||
|
result[12], result[13], result[14], result[15]
|
||
|
];
|
||
|
}
|
||
|
|
||
|
- (NSData *)md4Data {
|
||
|
unsigned char result[CC_MD4_DIGEST_LENGTH];
|
||
|
CC_MD4(self.bytes, (CC_LONG)self.length, result);
|
||
|
return [NSData dataWithBytes:result length:CC_MD4_DIGEST_LENGTH];
|
||
|
}
|
||
|
|
||
|
- (NSString *)md5String {
|
||
|
unsigned char result[CC_MD5_DIGEST_LENGTH];
|
||
|
CC_MD5(self.bytes, (CC_LONG)self.length, result);
|
||
|
return [NSString stringWithFormat:
|
||
|
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||
|
result[0], result[1], result[2], result[3],
|
||
|
result[4], result[5], result[6], result[7],
|
||
|
result[8], result[9], result[10], result[11],
|
||
|
result[12], result[13], result[14], result[15]
|
||
|
];
|
||
|
}
|
||
|
|
||
|
- (NSData *)md5Data {
|
||
|
unsigned char result[CC_MD5_DIGEST_LENGTH];
|
||
|
CC_MD5(self.bytes, (CC_LONG)self.length, result);
|
||
|
return [NSData dataWithBytes:result length:CC_MD5_DIGEST_LENGTH];
|
||
|
}
|
||
|
|
||
|
- (NSString *)sha1String {
|
||
|
unsigned char result[CC_SHA1_DIGEST_LENGTH];
|
||
|
CC_SHA1(self.bytes, (CC_LONG)self.length, result);
|
||
|
NSMutableString *hash = [NSMutableString
|
||
|
stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
|
||
|
for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
|
||
|
[hash appendFormat:@"%02x", result[i]];
|
||
|
}
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
- (NSData *)sha1Data {
|
||
|
unsigned char result[CC_SHA1_DIGEST_LENGTH];
|
||
|
CC_SHA1(self.bytes, (CC_LONG)self.length, result);
|
||
|
return [NSData dataWithBytes:result length:CC_SHA1_DIGEST_LENGTH];
|
||
|
}
|
||
|
|
||
|
- (NSString *)sha224String {
|
||
|
unsigned char result[CC_SHA224_DIGEST_LENGTH];
|
||
|
CC_SHA224(self.bytes, (CC_LONG)self.length, result);
|
||
|
NSMutableString *hash = [NSMutableString
|
||
|
stringWithCapacity:CC_SHA224_DIGEST_LENGTH * 2];
|
||
|
for (int i = 0; i < CC_SHA224_DIGEST_LENGTH; i++) {
|
||
|
[hash appendFormat:@"%02x", result[i]];
|
||
|
}
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
- (NSData *)sha224Data {
|
||
|
unsigned char result[CC_SHA224_DIGEST_LENGTH];
|
||
|
CC_SHA224(self.bytes, (CC_LONG)self.length, result);
|
||
|
return [NSData dataWithBytes:result length:CC_SHA224_DIGEST_LENGTH];
|
||
|
}
|
||
|
|
||
|
- (NSString *)sha256String {
|
||
|
unsigned char result[CC_SHA256_DIGEST_LENGTH];
|
||
|
CC_SHA256(self.bytes, (CC_LONG)self.length, result);
|
||
|
NSMutableString *hash = [NSMutableString
|
||
|
stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
|
||
|
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
|
||
|
[hash appendFormat:@"%02x", result[i]];
|
||
|
}
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
- (NSData *)sha256Data {
|
||
|
unsigned char result[CC_SHA256_DIGEST_LENGTH];
|
||
|
CC_SHA256(self.bytes, (CC_LONG)self.length, result);
|
||
|
return [NSData dataWithBytes:result length:CC_SHA256_DIGEST_LENGTH];
|
||
|
}
|
||
|
|
||
|
- (NSString *)sha384String {
|
||
|
unsigned char result[CC_SHA384_DIGEST_LENGTH];
|
||
|
CC_SHA384(self.bytes, (CC_LONG)self.length, result);
|
||
|
NSMutableString *hash = [NSMutableString
|
||
|
stringWithCapacity:CC_SHA384_DIGEST_LENGTH * 2];
|
||
|
for (int i = 0; i < CC_SHA384_DIGEST_LENGTH; i++) {
|
||
|
[hash appendFormat:@"%02x", result[i]];
|
||
|
}
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
- (NSData *)sha384Data {
|
||
|
unsigned char result[CC_SHA384_DIGEST_LENGTH];
|
||
|
CC_SHA384(self.bytes, (CC_LONG)self.length, result);
|
||
|
return [NSData dataWithBytes:result length:CC_SHA384_DIGEST_LENGTH];
|
||
|
}
|
||
|
|
||
|
- (NSString *)sha512String {
|
||
|
unsigned char result[CC_SHA512_DIGEST_LENGTH];
|
||
|
CC_SHA512(self.bytes, (CC_LONG)self.length, result);
|
||
|
NSMutableString *hash = [NSMutableString
|
||
|
stringWithCapacity:CC_SHA512_DIGEST_LENGTH * 2];
|
||
|
for (int i = 0; i < CC_SHA512_DIGEST_LENGTH; i++) {
|
||
|
[hash appendFormat:@"%02x", result[i]];
|
||
|
}
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
- (NSData *)sha512Data {
|
||
|
unsigned char result[CC_SHA512_DIGEST_LENGTH];
|
||
|
CC_SHA512(self.bytes, (CC_LONG)self.length, result);
|
||
|
return [NSData dataWithBytes:result length:CC_SHA512_DIGEST_LENGTH];
|
||
|
}
|
||
|
|
||
|
- (NSString *)hmacStringUsingAlg:(CCHmacAlgorithm)alg withKey:(NSString *)key {
|
||
|
size_t size;
|
||
|
switch (alg) {
|
||
|
case kCCHmacAlgMD5: size = CC_MD5_DIGEST_LENGTH; break;
|
||
|
case kCCHmacAlgSHA1: size = CC_SHA1_DIGEST_LENGTH; break;
|
||
|
case kCCHmacAlgSHA224: size = CC_SHA224_DIGEST_LENGTH; break;
|
||
|
case kCCHmacAlgSHA256: size = CC_SHA256_DIGEST_LENGTH; break;
|
||
|
case kCCHmacAlgSHA384: size = CC_SHA384_DIGEST_LENGTH; break;
|
||
|
case kCCHmacAlgSHA512: size = CC_SHA512_DIGEST_LENGTH; break;
|
||
|
default: return nil;
|
||
|
}
|
||
|
unsigned char result[size];
|
||
|
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
|
||
|
CCHmac(alg, cKey, strlen(cKey), self.bytes, self.length, result);
|
||
|
NSMutableString *hash = [NSMutableString stringWithCapacity:size * 2];
|
||
|
for (int i = 0; i < size; i++) {
|
||
|
[hash appendFormat:@"%02x", result[i]];
|
||
|
}
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
- (NSData *)hmacDataUsingAlg:(CCHmacAlgorithm)alg withKey:(NSData *)key {
|
||
|
size_t size;
|
||
|
switch (alg) {
|
||
|
case kCCHmacAlgMD5: size = CC_MD5_DIGEST_LENGTH; break;
|
||
|
case kCCHmacAlgSHA1: size = CC_SHA1_DIGEST_LENGTH; break;
|
||
|
case kCCHmacAlgSHA224: size = CC_SHA224_DIGEST_LENGTH; break;
|
||
|
case kCCHmacAlgSHA256: size = CC_SHA256_DIGEST_LENGTH; break;
|
||
|
case kCCHmacAlgSHA384: size = CC_SHA384_DIGEST_LENGTH; break;
|
||
|
case kCCHmacAlgSHA512: size = CC_SHA512_DIGEST_LENGTH; break;
|
||
|
default: return nil;
|
||
|
}
|
||
|
unsigned char result[size];
|
||
|
CCHmac(alg, [key bytes], key.length, self.bytes, self.length, result);
|
||
|
return [NSData dataWithBytes:result length:size];
|
||
|
}
|
||
|
|
||
|
- (NSString *)hmacMD5StringWithKey:(NSString *)key {
|
||
|
return [self hmacStringUsingAlg:kCCHmacAlgMD5 withKey:key];
|
||
|
}
|
||
|
|
||
|
- (NSData *)hmacMD5DataWithKey:(NSData *)key {
|
||
|
return [self hmacDataUsingAlg:kCCHmacAlgMD5 withKey:key];
|
||
|
}
|
||
|
|
||
|
- (NSString *)hmacSHA1StringWithKey:(NSString *)key {
|
||
|
return [self hmacStringUsingAlg:kCCHmacAlgSHA1 withKey:key];
|
||
|
}
|
||
|
|
||
|
- (NSData *)hmacSHA1DataWithKey:(NSData *)key {
|
||
|
return [self hmacDataUsingAlg:kCCHmacAlgSHA1 withKey:key];
|
||
|
}
|
||
|
|
||
|
- (NSString *)hmacSHA224StringWithKey:(NSString *)key {
|
||
|
return [self hmacStringUsingAlg:kCCHmacAlgSHA224 withKey:key];
|
||
|
}
|
||
|
|
||
|
- (NSData *)hmacSHA224DataWithKey:(NSData *)key {
|
||
|
return [self hmacDataUsingAlg:kCCHmacAlgSHA224 withKey:key];
|
||
|
}
|
||
|
|
||
|
- (NSString *)hmacSHA256StringWithKey:(NSString *)key {
|
||
|
return [self hmacStringUsingAlg:kCCHmacAlgSHA256 withKey:key];
|
||
|
}
|
||
|
|
||
|
- (NSData *)hmacSHA256DataWithKey:(NSData *)key {
|
||
|
return [self hmacDataUsingAlg:kCCHmacAlgSHA256 withKey:key];
|
||
|
}
|
||
|
|
||
|
- (NSString *)hmacSHA384StringWithKey:(NSString *)key {
|
||
|
return [self hmacStringUsingAlg:kCCHmacAlgSHA384 withKey:key];
|
||
|
}
|
||
|
|
||
|
- (NSData *)hmacSHA384DataWithKey:(NSData *)key {
|
||
|
return [self hmacDataUsingAlg:kCCHmacAlgSHA384 withKey:key];
|
||
|
}
|
||
|
|
||
|
- (NSString *)hmacSHA512StringWithKey:(NSString *)key {
|
||
|
return [self hmacStringUsingAlg:kCCHmacAlgSHA512 withKey:key];
|
||
|
}
|
||
|
|
||
|
- (NSData *)hmacSHA512DataWithKey:(NSData *)key {
|
||
|
return [self hmacDataUsingAlg:kCCHmacAlgSHA512 withKey:key];
|
||
|
}
|
||
|
|
||
|
- (NSString *)crc32String {
|
||
|
uLong result = crc32(0, self.bytes, (uInt)self.length);
|
||
|
return [NSString stringWithFormat:@"%08x", (uint32_t)result];
|
||
|
}
|
||
|
|
||
|
- (uint32_t)crc32 {
|
||
|
uLong result = crc32(0, self.bytes, (uInt)self.length);
|
||
|
return (uint32_t)result;
|
||
|
}
|
||
|
|
||
|
- (NSData *)aes256EncryptWithKey:(NSData *)key iv:(NSData *)iv {
|
||
|
if (key.length != 16 && key.length != 24 && key.length != 32) {
|
||
|
return nil;
|
||
|
}
|
||
|
if (iv.length != 16 && iv.length != 0) {
|
||
|
return nil;
|
||
|
}
|
||
|
|
||
|
NSData *result = nil;
|
||
|
size_t bufferSize = self.length + kCCBlockSizeAES128;
|
||
|
void *buffer = malloc(bufferSize);
|
||
|
if (!buffer) return nil;
|
||
|
size_t encryptedSize = 0;
|
||
|
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
|
||
|
kCCAlgorithmAES128,
|
||
|
kCCOptionPKCS7Padding,
|
||
|
key.bytes,
|
||
|
key.length,
|
||
|
iv.bytes,
|
||
|
self.bytes,
|
||
|
self.length,
|
||
|
buffer,
|
||
|
bufferSize,
|
||
|
&encryptedSize);
|
||
|
if (cryptStatus == kCCSuccess) {
|
||
|
result = [[NSData alloc]initWithBytes:buffer length:encryptedSize];
|
||
|
free(buffer);
|
||
|
return result;
|
||
|
} else {
|
||
|
free(buffer);
|
||
|
return nil;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (NSData *)aes256DecryptWithkey:(NSData *)key iv:(NSData *)iv {
|
||
|
if (key.length != 16 && key.length != 24 && key.length != 32) {
|
||
|
return nil;
|
||
|
}
|
||
|
if (iv.length != 16 && iv.length != 0) {
|
||
|
return nil;
|
||
|
}
|
||
|
|
||
|
NSData *result = nil;
|
||
|
size_t bufferSize = self.length + kCCBlockSizeAES128;
|
||
|
void *buffer = malloc(bufferSize);
|
||
|
if (!buffer) return nil;
|
||
|
size_t encryptedSize = 0;
|
||
|
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
|
||
|
kCCAlgorithmAES128,
|
||
|
kCCOptionPKCS7Padding,
|
||
|
key.bytes,
|
||
|
key.length,
|
||
|
iv.bytes,
|
||
|
self.bytes,
|
||
|
self.length,
|
||
|
buffer,
|
||
|
bufferSize,
|
||
|
&encryptedSize);
|
||
|
if (cryptStatus == kCCSuccess) {
|
||
|
result = [[NSData alloc]initWithBytes:buffer length:encryptedSize];
|
||
|
free(buffer);
|
||
|
return result;
|
||
|
} else {
|
||
|
free(buffer);
|
||
|
return nil;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- (NSString *)utf8String {
|
||
|
if (self.length > 0) {
|
||
|
return [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding];
|
||
|
}
|
||
|
return @"";
|
||
|
}
|
||
|
|
||
|
- (NSString *)hexString {
|
||
|
NSUInteger length = self.length;
|
||
|
NSMutableString *result = [NSMutableString stringWithCapacity:length * 2];
|
||
|
const unsigned char *byte = self.bytes;
|
||
|
for (int i = 0; i < length; i++, byte++) {
|
||
|
[result appendFormat:@"%02X", *byte];
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
+ (NSData *)dataWithHexString:(NSString *)hexStr {
|
||
|
hexStr = [hexStr stringByReplacingOccurrencesOfString:@" " withString:@""];
|
||
|
hexStr = [hexStr lowercaseString];
|
||
|
NSUInteger len = hexStr.length;
|
||
|
if (!len) return nil;
|
||
|
unichar *buf = malloc(sizeof(unichar) * len);
|
||
|
if (!buf) return nil;
|
||
|
[hexStr getCharacters:buf range:NSMakeRange(0, len)];
|
||
|
|
||
|
NSMutableData *result = [NSMutableData data];
|
||
|
unsigned char bytes;
|
||
|
char str[3] = { '\0', '\0', '\0' };
|
||
|
int i;
|
||
|
for (i = 0; i < len / 2; i++) {
|
||
|
str[0] = buf[i * 2];
|
||
|
str[1] = buf[i * 2 + 1];
|
||
|
bytes = strtol(str, NULL, 16);
|
||
|
[result appendBytes:&bytes length:1];
|
||
|
}
|
||
|
free(buf);
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static const char base64EncodingTable[64]
|
||
|
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||
|
static const short base64DecodingTable[256] = {
|
||
|
-2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -1, -1, -2, -2,
|
||
|
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||
|
-1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63,
|
||
|
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2,
|
||
|
-2, 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, -2, -2, -2, -2, -2,
|
||
|
-2, 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, -2, -2, -2, -2, -2,
|
||
|
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||
|
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||
|
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||
|
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||
|
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||
|
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||
|
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
|
||
|
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2
|
||
|
};
|
||
|
|
||
|
- (NSString *)base64EncodedString {
|
||
|
NSUInteger length = self.length;
|
||
|
if (length == 0)
|
||
|
return @"";
|
||
|
|
||
|
NSUInteger out_length = ((length + 2) / 3) * 4;
|
||
|
uint8_t *output = malloc(((out_length + 2) / 3) * 4);
|
||
|
if (output == NULL)
|
||
|
return nil;
|
||
|
|
||
|
const char *input = self.bytes;
|
||
|
NSInteger i, value;
|
||
|
for (i = 0; i < length; i += 3) {
|
||
|
value = 0;
|
||
|
for (NSInteger j = i; j < i + 3; j++) {
|
||
|
value <<= 8;
|
||
|
if (j < length) {
|
||
|
value |= (0xFF & input[j]);
|
||
|
}
|
||
|
}
|
||
|
NSInteger index = (i / 3) * 4;
|
||
|
output[index + 0] = base64EncodingTable[(value >> 18) & 0x3F];
|
||
|
output[index + 1] = base64EncodingTable[(value >> 12) & 0x3F];
|
||
|
output[index + 2] = ((i + 1) < length)
|
||
|
? base64EncodingTable[(value >> 6) & 0x3F]
|
||
|
: '=';
|
||
|
output[index + 3] = ((i + 2) < length)
|
||
|
? base64EncodingTable[(value >> 0) & 0x3F]
|
||
|
: '=';
|
||
|
}
|
||
|
|
||
|
NSString *base64 = [[NSString alloc] initWithBytes:output
|
||
|
length:out_length
|
||
|
encoding:NSASCIIStringEncoding];
|
||
|
free(output);
|
||
|
return base64;
|
||
|
}
|
||
|
|
||
|
+ (NSData *)dataWithBase64EncodedString:(NSString *)base64EncodedString {
|
||
|
NSInteger length = base64EncodedString.length;
|
||
|
const char *string = [base64EncodedString cStringUsingEncoding:NSASCIIStringEncoding];
|
||
|
if (string == NULL)
|
||
|
return nil;
|
||
|
|
||
|
while (length > 0 && string[length - 1] == '=')
|
||
|
length--;
|
||
|
|
||
|
NSInteger outputLength = length * 3 / 4;
|
||
|
NSMutableData *data = [NSMutableData dataWithLength:outputLength];
|
||
|
if (data == nil)
|
||
|
return nil;
|
||
|
if (length == 0)
|
||
|
return data;
|
||
|
|
||
|
uint8_t *output = data.mutableBytes;
|
||
|
NSInteger inputPoint = 0;
|
||
|
NSInteger outputPoint = 0;
|
||
|
while (inputPoint < length) {
|
||
|
char i0 = string[inputPoint++];
|
||
|
char i1 = string[inputPoint++];
|
||
|
char i2 = inputPoint < length ? string[inputPoint++] : 'A';
|
||
|
char i3 = inputPoint < length ? string[inputPoint++] : 'A';
|
||
|
|
||
|
output[outputPoint++] = (base64DecodingTable[i0] << 2)
|
||
|
| (base64DecodingTable[i1] >> 4);
|
||
|
if (outputPoint < outputLength) {
|
||
|
output[outputPoint++] = ((base64DecodingTable[i1] & 0xf) << 4)
|
||
|
| (base64DecodingTable[i2] >> 2);
|
||
|
}
|
||
|
if (outputPoint < outputLength) {
|
||
|
output[outputPoint++] = ((base64DecodingTable[i2] & 0x3) << 6)
|
||
|
| base64DecodingTable[i3];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
- (id)jsonValueDecoded {
|
||
|
NSError *error = nil;
|
||
|
id value = [NSJSONSerialization JSONObjectWithData:self options:kNilOptions error:&error];
|
||
|
if (error) {
|
||
|
NSLog(@"jsonValueDecoded error:%@", error);
|
||
|
}
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
- (NSData *)gzipInflate {
|
||
|
if ([self length] == 0) return self;
|
||
|
|
||
|
unsigned full_length = (unsigned)[self length];
|
||
|
unsigned half_length = (unsigned)[self length] / 2;
|
||
|
|
||
|
NSMutableData *decompressed = [NSMutableData
|
||
|
dataWithLength:full_length + half_length];
|
||
|
BOOL done = NO;
|
||
|
int status;
|
||
|
|
||
|
z_stream strm;
|
||
|
strm.next_in = (Bytef *)[self bytes];
|
||
|
strm.avail_in = (unsigned)[self length];
|
||
|
strm.total_out = 0;
|
||
|
strm.zalloc = Z_NULL;
|
||
|
strm.zfree = Z_NULL;
|
||
|
|
||
|
if (inflateInit2(&strm, (15 + 32)) != Z_OK) return nil;
|
||
|
while (!done) {
|
||
|
// Make sure we have enough room and reset the lengths.
|
||
|
if (strm.total_out >= [decompressed length])
|
||
|
[decompressed increaseLengthBy:half_length];
|
||
|
strm.next_out = [decompressed mutableBytes] + strm.total_out;
|
||
|
strm.avail_out = (uInt)([decompressed length] - strm.total_out);
|
||
|
|
||
|
// Inflate another chunk.
|
||
|
status = inflate(&strm, Z_SYNC_FLUSH);
|
||
|
if (status == Z_STREAM_END) done = YES;
|
||
|
else if (status != Z_OK) break;
|
||
|
}
|
||
|
if (inflateEnd(&strm) != Z_OK) return nil;
|
||
|
|
||
|
// Set real length.
|
||
|
if (done) {
|
||
|
[decompressed setLength:strm.total_out];
|
||
|
return [NSData dataWithData:decompressed];
|
||
|
} else return nil;
|
||
|
}
|
||
|
|
||
|
- (NSData *)gzipDeflate {
|
||
|
if ([self length] == 0) return self;
|
||
|
|
||
|
z_stream strm;
|
||
|
|
||
|
strm.zalloc = Z_NULL;
|
||
|
strm.zfree = Z_NULL;
|
||
|
strm.opaque = Z_NULL;
|
||
|
strm.total_out = 0;
|
||
|
strm.next_in = (Bytef *)[self bytes];
|
||
|
strm.avail_in = (uInt)[self length];
|
||
|
|
||
|
// Compresssion Levels:
|
||
|
// Z_NO_COMPRESSION
|
||
|
// Z_BEST_SPEED
|
||
|
// Z_BEST_COMPRESSION
|
||
|
// Z_DEFAULT_COMPRESSION
|
||
|
|
||
|
if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15 + 16),
|
||
|
8, Z_DEFAULT_STRATEGY) != Z_OK)
|
||
|
return nil;
|
||
|
|
||
|
// 16K chunks for expansion
|
||
|
NSMutableData *compressed = [NSMutableData dataWithLength:16384];
|
||
|
|
||
|
do {
|
||
|
if (strm.total_out >= [compressed length])
|
||
|
[compressed increaseLengthBy:16384];
|
||
|
|
||
|
strm.next_out = [compressed mutableBytes] + strm.total_out;
|
||
|
strm.avail_out = (uInt)([compressed length] - strm.total_out);
|
||
|
|
||
|
deflate(&strm, Z_FINISH);
|
||
|
}
|
||
|
while (strm.avail_out == 0);
|
||
|
|
||
|
deflateEnd(&strm);
|
||
|
|
||
|
[compressed setLength:strm.total_out];
|
||
|
return [NSData dataWithData:compressed];
|
||
|
}
|
||
|
|
||
|
- (NSData *)zlibInflate {
|
||
|
if ([self length] == 0) return self;
|
||
|
|
||
|
NSUInteger full_length = [self length];
|
||
|
NSUInteger half_length = [self length] / 2;
|
||
|
|
||
|
NSMutableData *decompressed = [NSMutableData
|
||
|
dataWithLength:full_length + half_length];
|
||
|
BOOL done = NO;
|
||
|
int status;
|
||
|
|
||
|
z_stream strm;
|
||
|
strm.next_in = (Bytef *)[self bytes];
|
||
|
strm.avail_in = (uInt)full_length;
|
||
|
strm.total_out = 0;
|
||
|
strm.zalloc = Z_NULL;
|
||
|
strm.zfree = Z_NULL;
|
||
|
|
||
|
if (inflateInit(&strm) != Z_OK) return nil;
|
||
|
|
||
|
while (!done) {
|
||
|
// Make sure we have enough room and reset the lengths.
|
||
|
if (strm.total_out >= [decompressed length])
|
||
|
[decompressed increaseLengthBy:half_length];
|
||
|
strm.next_out = [decompressed mutableBytes] + strm.total_out;
|
||
|
strm.avail_out = (uInt)([decompressed length] - strm.total_out);
|
||
|
|
||
|
// Inflate another chunk.
|
||
|
status = inflate(&strm, Z_SYNC_FLUSH);
|
||
|
if (status == Z_STREAM_END) done = YES;
|
||
|
else if (status != Z_OK) break;
|
||
|
}
|
||
|
if (inflateEnd(&strm) != Z_OK) return nil;
|
||
|
|
||
|
// Set real length.
|
||
|
if (done) {
|
||
|
[decompressed setLength:strm.total_out];
|
||
|
return [NSData dataWithData:decompressed];
|
||
|
} else return nil;
|
||
|
}
|
||
|
|
||
|
- (NSData *)zlibDeflate {
|
||
|
if ([self length] == 0) return self;
|
||
|
|
||
|
z_stream strm;
|
||
|
|
||
|
strm.zalloc = Z_NULL;
|
||
|
strm.zfree = Z_NULL;
|
||
|
strm.opaque = Z_NULL;
|
||
|
strm.total_out = 0;
|
||
|
strm.next_in = (Bytef *)[self bytes];
|
||
|
strm.avail_in = (uInt)[self length];
|
||
|
|
||
|
// Compresssion Levels:
|
||
|
// Z_NO_COMPRESSION
|
||
|
// Z_BEST_SPEED
|
||
|
// Z_BEST_COMPRESSION
|
||
|
// Z_DEFAULT_COMPRESSION
|
||
|
|
||
|
if (deflateInit(&strm, Z_DEFAULT_COMPRESSION) != Z_OK) return nil;
|
||
|
|
||
|
// 16K chuncks for expansion
|
||
|
NSMutableData *compressed = [NSMutableData dataWithLength:16384];
|
||
|
|
||
|
do {
|
||
|
if (strm.total_out >= [compressed length])
|
||
|
[compressed increaseLengthBy:16384];
|
||
|
|
||
|
strm.next_out = [compressed mutableBytes] + strm.total_out;
|
||
|
strm.avail_out = (uInt)([compressed length] - strm.total_out);
|
||
|
|
||
|
deflate(&strm, Z_FINISH);
|
||
|
}
|
||
|
while (strm.avail_out == 0);
|
||
|
|
||
|
deflateEnd(&strm);
|
||
|
|
||
|
[compressed setLength:strm.total_out];
|
||
|
return [NSData dataWithData:compressed];
|
||
|
}
|
||
|
|
||
|
+ (NSData *)dataNamed:(NSString *)name {
|
||
|
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@""];
|
||
|
if (!path) return nil;
|
||
|
NSData *data = [NSData dataWithContentsOfFile:path];
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
@end
|