changed git call from https to git readonly
[atutor.git] / mods / atsocial_iphone_app / OAuth / Crypto / Base64Transcoder.c
1 /*
2  *  Base64Transcoder.c
3  *  Base64Test
4  *
5  *  Created by Jonathan Wight on Tue Mar 18 2003.
6  *  Copyright (c) 2003 Toxic Software. All rights reserved.
7  *
8  *  Permission is hereby granted, free of charge, to any person obtaining a copy
9  *  of this software and associated documentation files (the "Software"), to deal
10  *  in the Software without restriction, including without limitation the rights
11  *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  *  copies of the Software, and to permit persons to whom the Software is
13  *  furnished to do so, subject to the following conditions:
14  *
15  *  The above copyright notice and this permission notice shall be included in
16  *  all copies or substantial portions of the Software.
17  *
18  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  *  THE SOFTWARE.
25  *
26  */
27
28 #include "Base64Transcoder.h"
29
30 #include <math.h>
31 #include <string.h>
32
33 const u_int8_t kBase64EncodeTable[64] = {
34         /*  0 */ 'A',   /*  1 */ 'B',   /*  2 */ 'C',   /*  3 */ 'D', 
35         /*  4 */ 'E',   /*  5 */ 'F',   /*  6 */ 'G',   /*  7 */ 'H', 
36         /*  8 */ 'I',   /*  9 */ 'J',   /* 10 */ 'K',   /* 11 */ 'L', 
37         /* 12 */ 'M',   /* 13 */ 'N',   /* 14 */ 'O',   /* 15 */ 'P', 
38         /* 16 */ 'Q',   /* 17 */ 'R',   /* 18 */ 'S',   /* 19 */ 'T', 
39         /* 20 */ 'U',   /* 21 */ 'V',   /* 22 */ 'W',   /* 23 */ 'X', 
40         /* 24 */ 'Y',   /* 25 */ 'Z',   /* 26 */ 'a',   /* 27 */ 'b', 
41         /* 28 */ 'c',   /* 29 */ 'd',   /* 30 */ 'e',   /* 31 */ 'f', 
42         /* 32 */ 'g',   /* 33 */ 'h',   /* 34 */ 'i',   /* 35 */ 'j', 
43         /* 36 */ 'k',   /* 37 */ 'l',   /* 38 */ 'm',   /* 39 */ 'n', 
44         /* 40 */ 'o',   /* 41 */ 'p',   /* 42 */ 'q',   /* 43 */ 'r', 
45         /* 44 */ 's',   /* 45 */ 't',   /* 46 */ 'u',   /* 47 */ 'v', 
46         /* 48 */ 'w',   /* 49 */ 'x',   /* 50 */ 'y',   /* 51 */ 'z', 
47         /* 52 */ '0',   /* 53 */ '1',   /* 54 */ '2',   /* 55 */ '3', 
48         /* 56 */ '4',   /* 57 */ '5',   /* 58 */ '6',   /* 59 */ '7', 
49         /* 60 */ '8',   /* 61 */ '9',   /* 62 */ '+',   /* 63 */ '/'
50 };
51
52 /*
53 -1 = Base64 end of data marker.
54 -2 = White space (tabs, cr, lf, space)
55 -3 = Noise (all non whitespace, non-base64 characters) 
56 -4 = Dangerous noise
57 -5 = Illegal noise (null byte)
58 */
59
60 const int8_t kBase64DecodeTable[128] = {
61         /* 0x00 */ -5,  /* 0x01 */ -3,  /* 0x02 */ -3,  /* 0x03 */ -3,
62         /* 0x04 */ -3,  /* 0x05 */ -3,  /* 0x06 */ -3,  /* 0x07 */ -3,
63         /* 0x08 */ -3,  /* 0x09 */ -2,  /* 0x0a */ -2,  /* 0x0b */ -2,
64         /* 0x0c */ -2,  /* 0x0d */ -2,  /* 0x0e */ -3,  /* 0x0f */ -3,
65         /* 0x10 */ -3,  /* 0x11 */ -3,  /* 0x12 */ -3,  /* 0x13 */ -3,
66         /* 0x14 */ -3,  /* 0x15 */ -3,  /* 0x16 */ -3,  /* 0x17 */ -3,
67         /* 0x18 */ -3,  /* 0x19 */ -3,  /* 0x1a */ -3,  /* 0x1b */ -3,
68         /* 0x1c */ -3,  /* 0x1d */ -3,  /* 0x1e */ -3,  /* 0x1f */ -3,
69         /* ' ' */ -2,   /* '!' */ -3,   /* '"' */ -3,   /* '#' */ -3,
70         /* '$' */ -3,   /* '%' */ -3,   /* '&' */ -3,   /* ''' */ -3,
71         /* '(' */ -3,   /* ')' */ -3,   /* '*' */ -3,   /* '+' */ 62,
72         /* ',' */ -3,   /* '-' */ -3,   /* '.' */ -3,   /* '/' */ 63,
73         /* '0' */ 52,   /* '1' */ 53,   /* '2' */ 54,   /* '3' */ 55,
74         /* '4' */ 56,   /* '5' */ 57,   /* '6' */ 58,   /* '7' */ 59,
75         /* '8' */ 60,   /* '9' */ 61,   /* ':' */ -3,   /* ';' */ -3,
76         /* '<' */ -3,   /* '=' */ -1,   /* '>' */ -3,   /* '?' */ -3,
77         /* '@' */ -3,   /* 'A' */ 0,    /* 'B' */  1,   /* 'C' */  2,
78         /* 'D' */  3,   /* 'E' */  4,   /* 'F' */  5,   /* 'G' */  6,
79         /* 'H' */  7,   /* 'I' */  8,   /* 'J' */  9,   /* 'K' */ 10,
80         /* 'L' */ 11,   /* 'M' */ 12,   /* 'N' */ 13,   /* 'O' */ 14,
81         /* 'P' */ 15,   /* 'Q' */ 16,   /* 'R' */ 17,   /* 'S' */ 18,
82         /* 'T' */ 19,   /* 'U' */ 20,   /* 'V' */ 21,   /* 'W' */ 22,
83         /* 'X' */ 23,   /* 'Y' */ 24,   /* 'Z' */ 25,   /* '[' */ -3,
84         /* '\' */ -3,   /* ']' */ -3,   /* '^' */ -3,   /* '_' */ -3,
85         /* '`' */ -3,   /* 'a' */ 26,   /* 'b' */ 27,   /* 'c' */ 28,
86         /* 'd' */ 29,   /* 'e' */ 30,   /* 'f' */ 31,   /* 'g' */ 32,
87         /* 'h' */ 33,   /* 'i' */ 34,   /* 'j' */ 35,   /* 'k' */ 36,
88         /* 'l' */ 37,   /* 'm' */ 38,   /* 'n' */ 39,   /* 'o' */ 40,
89         /* 'p' */ 41,   /* 'q' */ 42,   /* 'r' */ 43,   /* 's' */ 44,
90         /* 't' */ 45,   /* 'u' */ 46,   /* 'v' */ 47,   /* 'w' */ 48,
91         /* 'x' */ 49,   /* 'y' */ 50,   /* 'z' */ 51,   /* '{' */ -3,
92         /* '|' */ -3,   /* '}' */ -3,   /* '~' */ -3,   /* 0x7f */ -3
93 };
94
95 const u_int8_t kBits_00000011 = 0x03;
96 const u_int8_t kBits_00001111 = 0x0F;
97 const u_int8_t kBits_00110000 = 0x30;
98 const u_int8_t kBits_00111100 = 0x3C;
99 const u_int8_t kBits_00111111 = 0x3F;
100 const u_int8_t kBits_11000000 = 0xC0;
101 const u_int8_t kBits_11110000 = 0xF0;
102 const u_int8_t kBits_11111100 = 0xFC;
103
104 size_t EstimateBas64EncodedDataSize(size_t inDataSize)
105 {
106 size_t theEncodedDataSize = (int)ceil(inDataSize / 3.0) * 4;
107 theEncodedDataSize = theEncodedDataSize / 72 * 74 + theEncodedDataSize % 72;
108 return(theEncodedDataSize);
109 }
110
111 size_t EstimateBas64DecodedDataSize(size_t inDataSize)
112 {
113 size_t theDecodedDataSize = (int)ceil(inDataSize / 4.0) * 3;
114 //theDecodedDataSize = theDecodedDataSize / 72 * 74 + theDecodedDataSize % 72;
115 return(theDecodedDataSize);
116 }
117
118 bool Base64EncodeData(const void *inInputData, size_t inInputDataSize, char *outOutputData, size_t *ioOutputDataSize)
119 {
120 size_t theEncodedDataSize = EstimateBas64EncodedDataSize(inInputDataSize);
121 if (*ioOutputDataSize < theEncodedDataSize)
122         return(false);
123 *ioOutputDataSize = theEncodedDataSize;
124 const u_int8_t *theInPtr = (const u_int8_t *)inInputData;
125 u_int32_t theInIndex = 0, theOutIndex = 0;
126 for (; theInIndex < (inInputDataSize / 3) * 3; theInIndex += 3)
127         {
128         outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
129         outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4];
130         outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (theInPtr[theInIndex + 2] & kBits_11000000) >> 6];
131         outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 2] & kBits_00111111) >> 0];
132         if (theOutIndex % 74 == 72)
133                 {
134                 outOutputData[theOutIndex++] = '\r';
135                 outOutputData[theOutIndex++] = '\n';
136                 }
137         }
138 const size_t theRemainingBytes = inInputDataSize - theInIndex;
139 if (theRemainingBytes == 1)
140         {
141         outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
142         outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (0 & kBits_11110000) >> 4];
143         outOutputData[theOutIndex++] = '=';
144         outOutputData[theOutIndex++] = '=';
145         if (theOutIndex % 74 == 72)
146                 {
147                 outOutputData[theOutIndex++] = '\r';
148                 outOutputData[theOutIndex++] = '\n';
149                 }
150         }
151 else if (theRemainingBytes == 2)
152         {
153         outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
154         outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4];
155         outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (0 & kBits_11000000) >> 6];
156         outOutputData[theOutIndex++] = '=';
157         if (theOutIndex % 74 == 72)
158                 {
159                 outOutputData[theOutIndex++] = '\r';
160                 outOutputData[theOutIndex++] = '\n';
161                 }
162         }
163 return(true);
164 }
165
166 bool Base64DecodeData(const void *inInputData, size_t inInputDataSize, void *ioOutputData, size_t *ioOutputDataSize)
167 {
168 memset(ioOutputData, '.', *ioOutputDataSize);
169
170 size_t theDecodedDataSize = EstimateBas64DecodedDataSize(inInputDataSize);
171 if (*ioOutputDataSize < theDecodedDataSize)
172         return(false);
173 *ioOutputDataSize = 0;
174 const u_int8_t *theInPtr = (const u_int8_t *)inInputData;
175 u_int8_t *theOutPtr = (u_int8_t *)ioOutputData;
176 size_t theInIndex = 0, theOutIndex = 0;
177 u_int8_t theOutputOctet;
178 size_t theSequence = 0;
179 for (; theInIndex < inInputDataSize; )
180         {
181         int8_t theSextet = 0;
182         
183         int8_t theCurrentInputOctet = theInPtr[theInIndex];
184         theSextet = kBase64DecodeTable[theCurrentInputOctet];
185         if (theSextet == -1)
186                 break;
187         while (theSextet == -2)
188                 {
189                 theCurrentInputOctet = theInPtr[++theInIndex];
190                 theSextet = kBase64DecodeTable[theCurrentInputOctet];
191                 }
192         while (theSextet == -3)
193                 {
194                 theCurrentInputOctet = theInPtr[++theInIndex];
195                 theSextet = kBase64DecodeTable[theCurrentInputOctet];
196                 }
197         if (theSequence == 0)
198                 {
199                 theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 2 & kBits_11111100;
200                 }
201         else if (theSequence == 1)
202                 {
203                 theOutputOctet |= (theSextet >- 0 ? theSextet : 0) >> 4 & kBits_00000011;
204                 theOutPtr[theOutIndex++] = theOutputOctet;
205                 }
206         else if (theSequence == 2)
207                 {
208                 theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 4 & kBits_11110000;
209                 }
210         else if (theSequence == 3)
211                 {
212                 theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 2 & kBits_00001111;
213                 theOutPtr[theOutIndex++] = theOutputOctet;
214                 }
215         else if (theSequence == 4)
216                 {
217                 theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 6 & kBits_11000000;
218                 }
219         else if (theSequence == 5)
220                 {
221                 theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 0 & kBits_00111111;
222                 theOutPtr[theOutIndex++] = theOutputOctet;
223                 }
224         theSequence = (theSequence + 1) % 6;
225         if (theSequence != 2 && theSequence != 4)
226                 theInIndex++;
227         }
228 *ioOutputDataSize = theOutIndex;
229 return(true);
230 }