open62541 1.4.15
Open source implementation of OPC UA
Loading...
Searching...
No Matches
nodeset_base64.h
Go to the documentation of this file.
1/*
2 https://github.com/superwills/NibbleAndAHalf
3 nodeset_base64.h -- Fast base64 encoding and decoding.
4 version 1.0.0, April 17, 2013 143a
5 Copyright (C) 2013 William Sherif
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19 William Sherif
20 will.sherif@gmail.com
21 YWxsIHlvdXIgYmFzZSBhcmUgYmVsb25nIHRvIHVz
22*/
23#ifndef NODESET_BASE64_H
24#define NODESET_BASE64_H
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <ctype.h>
29
30static const char *b64 =
31 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
32
33// maps A=>0,B=>1..
34static const unsigned char unb64[] = {
35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10
36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 30
38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40
39 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, // 50
40 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, // 60
41 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, // 70
42 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 80
43 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 90
44 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, // 100
45 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // 110
46 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // 120
47 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, // 130
48 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 140
49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 150
50 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 170
52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 180
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 190
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 200
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 210
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 220
57 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 230
58 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240
59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 250
60 0, 0, 0, 0, 0, 0,
61}; // This array has 256 elements
62
63// Converts binary data of length=len to base64 characters.
64// Length of the resultant string is stored in flen
65// (you must pass pointer flen).
66char *base64(const void *binaryData, int len, int *flen);
67char *base64(const void *binaryData, int len, int *flen)
68{
69 const unsigned char *bin = (const unsigned char *)binaryData;
70 char *res;
71
72 int rc = 0; // result counter
73 int byteNo; // I need this after the loop
74
75 int modulusLen = len % 3;
76 int pad =
77 ((modulusLen & 1) << 1) +
78 ((modulusLen & 2) >> 1); // 2 gives 1 and 1 gives 2, but 0 gives 0.
79
80 *flen = 4 * (len + pad) / 3;
81 res = (char *)malloc((size_t)(*flen + 1)); // and one for the null
82 if (!res)
83 {
84 puts("ERROR: base64 could not allocate enough memory.");
85 puts("I must stop because I could not get enough");
86 return 0;
87 }
88
89 for (byteNo = 0; byteNo <= len - 3; byteNo += 3)
90 {
91 unsigned char BYTE0 = bin[byteNo];
92 unsigned char BYTE1 = bin[byteNo + 1];
93 unsigned char BYTE2 = bin[byteNo + 2];
94 res[rc++] = b64[BYTE0 >> 2];
95 res[rc++] = b64[((0x3 & BYTE0) << 4) + (BYTE1 >> 4)];
96 res[rc++] = b64[((0x0f & BYTE1) << 2) + (BYTE2 >> 6)];
97 res[rc++] = b64[0x3f & BYTE2];
98 }
99
100 if (pad == 2)
101 {
102 res[rc++] = b64[bin[byteNo] >> 2];
103 res[rc++] = b64[(0x3 & bin[byteNo]) << 4];
104 res[rc++] = '=';
105 res[rc++] = '=';
106 }
107 else if (pad == 1)
108 {
109 res[rc++] = b64[bin[byteNo] >> 2];
110 res[rc++] = b64[((0x3 & bin[byteNo]) << 4) + (bin[byteNo + 1] >> 4)];
111 res[rc++] = b64[(0x0f & bin[byteNo + 1]) << 2];
112 res[rc++] = '=';
113 }
114
115 res[rc] = 0; // NULL TERMINATOR! ;)
116 return res;
117}
118unsigned char *unbase64(const char *ascii, int len, int *flen);
119
120unsigned char *unbase64(const char *ascii, int len, int *flen)
121{
122 unsigned char *safeAsciiPtr;
123 unsigned char *bin;
124 int cb = 0;
125 int charNo = 0;
126 int pad = 0;
127
128 safeAsciiPtr = (unsigned char *)malloc((size_t)len);
129 if (!safeAsciiPtr)
130 {
131 puts("ERROR: unbase64 could not allocate enough memory.");
132 puts("I must stop because I could not get enough");
133 return 0;
134 }
135
136 for (charNo = 0; charNo < len; charNo++)
137 {
138 // remove all space characters e.g. LF, CR, space and tab
139 if (!isspace(ascii[charNo]))
140 {
141 if (((ascii[charNo] >= '0') &&
142 (ascii[charNo] <= '9')) ||
143 ((ascii[charNo] >= 'A') &&
144 (ascii[charNo] <= 'Z')) ||
145 ((ascii[charNo] >= 'a') &&
146 (ascii[charNo] <= 'z')) ||
147 (ascii[charNo] == '+') ||
148 (ascii[charNo] == '/') ||
149 (ascii[charNo] == '='))
150 {
151 safeAsciiPtr[cb++] = (unsigned char)ascii[charNo];
152 }
153 else
154 {
155 puts("ERROR: You passed an invalid base64 string (illegal character). "
156 "You get NULL back.");
157 free(safeAsciiPtr);
158 *flen = 0;
159 return 0;
160 }
161 }
162 }
163
164 len = cb;
165 if (len < 2)
166 { // 2 accesses below would be OOB.
167 // catch empty string, return NULL as result.
168 puts("ERROR: You passed an invalid base64 string (too short). You get "
169 "NULL back.");
170 *flen = 0;
171 free(safeAsciiPtr);
172 return 0;
173 }
174 if (safeAsciiPtr[len - 1] == '=')
175 ++pad;
176 if (safeAsciiPtr[len - 2] == '=')
177 ++pad;
178
179 *flen = 3 * len / 4 - pad;
180 bin = (unsigned char *)malloc((size_t)*flen);
181 if (!bin)
182 {
183 puts("ERROR: unbase64 could not allocate enough memory.");
184 puts("I must stop because I could not get enough");
185 free(safeAsciiPtr);
186 return 0;
187 }
188
189 cb = 0;
190 for (charNo = 0; charNo <= len - 4 - pad; charNo += 4)
191 {
192 unsigned char A = unb64[safeAsciiPtr[charNo]];
193 unsigned char B = unb64[safeAsciiPtr[charNo + 1]];
194 unsigned char C = unb64[safeAsciiPtr[charNo + 2]];
195 unsigned char D = unb64[safeAsciiPtr[charNo + 3]];
196
197 bin[cb++] = (unsigned char)(A << 2) | (B >> 4);
198 bin[cb++] = (unsigned char)(B << 4) | (C >> 2);
199 bin[cb++] = (unsigned char)(C << 6) | (D);
200 }
201
202 if (pad == 1 && (charNo + 2) < len)
203 {
204 unsigned char A = unb64[safeAsciiPtr[charNo]];
205 unsigned char B = unb64[safeAsciiPtr[charNo + 1]];
206 unsigned char C = unb64[safeAsciiPtr[charNo + 2]];
207
208 bin[cb++] = (unsigned char)(A << 2) | (B >> 4);
209 bin[cb++] = (unsigned char)(B << 4) | (C >> 2);
210 }
211 else if (pad == 2 && (charNo + 1) < len)
212 {
213 unsigned char A = (unsigned char)unb64[safeAsciiPtr[charNo]];
214 unsigned char B = (unsigned char)unb64[safeAsciiPtr[charNo + 1]];
215
216 bin[cb++] = (unsigned char)(A << 2) | (B >> 4);
217 }
218
219 free(safeAsciiPtr);
220
221 return bin;
222}
223
224#endif /* NODESET_BASE64_H */
unsigned char * unbase64(const char *ascii, int len, int *flen)
char * base64(const void *binaryData, int len, int *flen)