Skip to content

Commit 9a0b418

Browse files
committed
Initial Commit
0 parents  commit 9a0b418

23 files changed

+7244
-0
lines changed

.gitignore

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
*.xcodeproj/*
2+
!*.xcodeproj/project.pbxproj
3+
!*.xcodeproj/project.xcworkspace
4+
/build
5+
*.pbxuser
6+
*.mode1v3
7+
*.mode2v3
8+
*.perspectivev3
9+
target/*
10+
.DS_Store
11+
profile
12+
*.svn
13+
/.svn/*
14+
xcuserdata
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// NSData+Base64.h
3+
// base64
4+
//
5+
// Created by Matt Gallagher on 2009/06/03.
6+
// Copyright 2009 Matt Gallagher. All rights reserved.
7+
//
8+
// This software is provided 'as-is', without any express or implied
9+
// warranty. In no event will the authors be held liable for any damages
10+
// arising from the use of this software. Permission is granted to anyone to
11+
// use this software for any purpose, including commercial applications, and to
12+
// alter it and redistribute it freely, subject to the following restrictions:
13+
//
14+
// 1. The origin of this software must not be misrepresented; you must not
15+
// claim that you wrote the original software. If you use this software
16+
// in a product, an acknowledgment in the product documentation would be
17+
// appreciated but is not required.
18+
// 2. Altered source versions must be plainly marked as such, and must not be
19+
// misrepresented as being the original software.
20+
// 3. This notice may not be removed or altered from any source
21+
// distribution.
22+
//
23+
24+
#import <Foundation/Foundation.h>
25+
26+
void *NewBase64Decode(
27+
const char *inputBuffer,
28+
size_t length,
29+
size_t *outputLength);
30+
31+
char *NewBase64Encode(
32+
const void *inputBuffer,
33+
size_t length,
34+
bool separateLines,
35+
size_t *outputLength);
36+
37+
@interface NSData (Base64)
38+
39+
+ (NSData *)dataFromBase64String:(NSString *)aString;
40+
- (NSString *)base64EncodedString;
41+
42+
@end
+308
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
//
2+
// NSData+Base64.m
3+
// base64
4+
//
5+
// Created by Matt Gallagher on 2009/06/03.
6+
// Copyright 2009 Matt Gallagher. All rights reserved.
7+
//
8+
// This software is provided 'as-is', without any express or implied
9+
// warranty. In no event will the authors be held liable for any damages
10+
// arising from the use of this software. Permission is granted to anyone to
11+
// use this software for any purpose, including commercial applications, and to
12+
// alter it and redistribute it freely, subject to the following restrictions:
13+
//
14+
// 1. The origin of this software must not be misrepresented; you must not
15+
// claim that you wrote the original software. If you use this software
16+
// in a product, an acknowledgment in the product documentation would be
17+
// appreciated but is not required.
18+
// 2. Altered source versions must be plainly marked as such, and must not be
19+
// misrepresented as being the original software.
20+
// 3. This notice may not be removed or altered from any source
21+
// distribution.
22+
//
23+
24+
#import "NSData+Base64.h"
25+
26+
//
27+
// Mapping from 6 bit pattern to ASCII character.
28+
//
29+
static unsigned char base64EncodeLookup[65] =
30+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
31+
32+
//
33+
// Definition for "masked-out" areas of the base64DecodeLookup mapping
34+
//
35+
#define xx 65
36+
37+
//
38+
// Mapping from ASCII character to 6 bit pattern.
39+
//
40+
static unsigned char base64DecodeLookup[256] =
41+
{
42+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
43+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
44+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, xx, 63,
45+
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx,
46+
xx, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
47+
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, xx,
48+
xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
49+
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx,
50+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
51+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
52+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
53+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
54+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
55+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
56+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
57+
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
58+
};
59+
60+
//
61+
// Fundamental sizes of the binary and base64 encode/decode units in bytes
62+
//
63+
#define BINARY_UNIT_SIZE 3
64+
#define BASE64_UNIT_SIZE 4
65+
66+
//
67+
// NewBase64Decode
68+
//
69+
// Decodes the base64 ASCII string in the inputBuffer to a newly malloced
70+
// output buffer.
71+
//
72+
// inputBuffer - the source ASCII string for the decode
73+
// length - the length of the string or -1 (to specify strlen should be used)
74+
// outputLength - if not-NULL, on output will contain the decoded length
75+
//
76+
// returns the decoded buffer. Must be free'd by caller. Length is given by
77+
// outputLength.
78+
//
79+
void *NewBase64Decode(
80+
const char *inputBuffer,
81+
size_t length,
82+
size_t *outputLength)
83+
{
84+
if (length == -1)
85+
{
86+
length = strlen(inputBuffer);
87+
}
88+
89+
size_t outputBufferSize =
90+
((length+BASE64_UNIT_SIZE-1) / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE;
91+
unsigned char *outputBuffer = (unsigned char *)malloc(outputBufferSize);
92+
93+
size_t i = 0;
94+
size_t j = 0;
95+
while (i < length)
96+
{
97+
//
98+
// Accumulate 4 valid characters (ignore everything else)
99+
//
100+
unsigned char accumulated[BASE64_UNIT_SIZE];
101+
size_t accumulateIndex = 0;
102+
while (i < length)
103+
{
104+
unsigned char decode = base64DecodeLookup[inputBuffer[i++]];
105+
if (decode != xx)
106+
{
107+
accumulated[accumulateIndex] = decode;
108+
accumulateIndex++;
109+
110+
if (accumulateIndex == BASE64_UNIT_SIZE)
111+
{
112+
break;
113+
}
114+
}
115+
}
116+
117+
//
118+
// Store the 6 bits from each of the 4 characters as 3 bytes
119+
//
120+
// (Uses improved bounds checking suggested by Alexandre Colucci)
121+
//
122+
if(accumulateIndex >= 2)
123+
outputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4);
124+
if(accumulateIndex >= 3)
125+
outputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2);
126+
if(accumulateIndex >= 4)
127+
outputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3];
128+
j += accumulateIndex - 1;
129+
}
130+
131+
if (outputLength)
132+
{
133+
*outputLength = j;
134+
}
135+
return outputBuffer;
136+
}
137+
138+
//
139+
// NewBase64Encode
140+
//
141+
// Encodes the arbitrary data in the inputBuffer as base64 into a newly malloced
142+
// output buffer.
143+
//
144+
// inputBuffer - the source data for the encode
145+
// length - the length of the input in bytes
146+
// separateLines - if zero, no CR/LF characters will be added. Otherwise
147+
// a CR/LF pair will be added every 64 encoded chars.
148+
// outputLength - if not-NULL, on output will contain the encoded length
149+
// (not including terminating 0 char)
150+
//
151+
// returns the encoded buffer. Must be free'd by caller. Length is given by
152+
// outputLength.
153+
//
154+
char *NewBase64Encode(
155+
const void *buffer,
156+
size_t length,
157+
bool separateLines,
158+
size_t *outputLength)
159+
{
160+
const unsigned char *inputBuffer = (const unsigned char *)buffer;
161+
162+
#define MAX_NUM_PADDING_CHARS 2
163+
#define OUTPUT_LINE_LENGTH 64
164+
#define INPUT_LINE_LENGTH ((OUTPUT_LINE_LENGTH / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE)
165+
#define CR_LF_SIZE 2
166+
167+
//
168+
// Byte accurate calculation of final buffer size
169+
//
170+
size_t outputBufferSize =
171+
((length / BINARY_UNIT_SIZE)
172+
+ ((length % BINARY_UNIT_SIZE) ? 1 : 0))
173+
* BASE64_UNIT_SIZE;
174+
if (separateLines)
175+
{
176+
outputBufferSize +=
177+
(outputBufferSize / OUTPUT_LINE_LENGTH) * CR_LF_SIZE;
178+
}
179+
180+
//
181+
// Include space for a terminating zero
182+
//
183+
outputBufferSize += 1;
184+
185+
//
186+
// Allocate the output buffer
187+
//
188+
char *outputBuffer = (char *)malloc(outputBufferSize);
189+
if (!outputBuffer)
190+
{
191+
return NULL;
192+
}
193+
194+
size_t i = 0;
195+
size_t j = 0;
196+
const size_t lineLength = separateLines ? INPUT_LINE_LENGTH : length;
197+
size_t lineEnd = lineLength;
198+
199+
while (true)
200+
{
201+
if (lineEnd > length)
202+
{
203+
lineEnd = length;
204+
}
205+
206+
for (; i + BINARY_UNIT_SIZE - 1 < lineEnd; i += BINARY_UNIT_SIZE)
207+
{
208+
//
209+
// Inner loop: turn 48 bytes into 64 base64 characters
210+
//
211+
outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
212+
outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
213+
| ((inputBuffer[i + 1] & 0xF0) >> 4)];
214+
outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2)
215+
| ((inputBuffer[i + 2] & 0xC0) >> 6)];
216+
outputBuffer[j++] = base64EncodeLookup[inputBuffer[i + 2] & 0x3F];
217+
}
218+
219+
if (lineEnd == length)
220+
{
221+
break;
222+
}
223+
224+
//
225+
// Add the newline
226+
//
227+
outputBuffer[j++] = '\r';
228+
outputBuffer[j++] = '\n';
229+
lineEnd += lineLength;
230+
}
231+
232+
if (i + 1 < length)
233+
{
234+
//
235+
// Handle the single '=' case
236+
//
237+
outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
238+
outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
239+
| ((inputBuffer[i + 1] & 0xF0) >> 4)];
240+
outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2];
241+
outputBuffer[j++] = '=';
242+
}
243+
else if (i < length)
244+
{
245+
//
246+
// Handle the double '=' case
247+
//
248+
outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
249+
outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0x03) << 4];
250+
outputBuffer[j++] = '=';
251+
outputBuffer[j++] = '=';
252+
}
253+
outputBuffer[j] = 0;
254+
255+
//
256+
// Set the output length and return the buffer
257+
//
258+
if (outputLength)
259+
{
260+
*outputLength = j;
261+
}
262+
return outputBuffer;
263+
}
264+
265+
@implementation NSData (Base64)
266+
267+
//
268+
// dataFromBase64String:
269+
//
270+
// Creates an NSData object containing the base64 decoded representation of
271+
// the base64 string 'aString'
272+
//
273+
// Parameters:
274+
// aString - the base64 string to decode
275+
//
276+
// returns the autoreleased NSData representation of the base64 string
277+
//
278+
+ (NSData *)dataFromBase64String:(NSString *)aString
279+
{
280+
NSData *data = [aString dataUsingEncoding:NSASCIIStringEncoding];
281+
size_t outputLength;
282+
void *outputBuffer = NewBase64Decode([data bytes], [data length], &outputLength);
283+
NSData *result = [NSData dataWithBytes:outputBuffer length:outputLength];
284+
free(outputBuffer);
285+
return result;
286+
}
287+
288+
//
289+
// base64EncodedString
290+
//
291+
// Creates an NSString object that contains the base 64 encoding of the
292+
// receiver's data. Lines are broken at 64 characters long.
293+
//
294+
// returns an autoreleased NSString being the base 64 representation of the
295+
// receiver.
296+
//
297+
- (NSString *)base64EncodedString
298+
{
299+
size_t outputLength;
300+
char *outputBuffer =
301+
NewBase64Encode([self bytes], [self length], true, &outputLength);
302+
303+
NSString *result = [[NSString alloc] initWithBytes:outputBuffer length:outputLength encoding:NSASCIIStringEncoding];
304+
free(outputBuffer);
305+
return result;
306+
}
307+
308+
@end

0 commit comments

Comments
 (0)