Files: e1e1c56a064cee691025d3117030ea74cc5e8354 / base64.c
2365 bytesRaw
1 | /* |
2 | |
3 | This code is public domain software. |
4 | |
5 | */ |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | // single base64 character conversion |
15 | // |
16 | static int POS(char c) |
17 | { |
18 | if (c>='A' && c<='Z') return c - 'A'; |
19 | if (c>='a' && c<='z') return c - 'a' + 26; |
20 | if (c>='0' && c<='9') return c - '0' + 52; |
21 | if (c == '+') return 62; |
22 | if (c == '/') return 63; |
23 | if (c == '=') return -1; |
24 | return -2; |
25 | } |
26 | |
27 | // base64 decoding |
28 | // |
29 | // s: base64 string |
30 | // str_len size of the base64 string |
31 | // data: output buffer for decoded data |
32 | // data_len expected size of decoded data |
33 | // return: 0 on success, -1 on failure |
34 | // |
35 | int base64_decode(const char* s, size_t str_len, void *data, size_t data_len) |
36 | { |
37 | const char *p, *str_end; |
38 | unsigned char *q, *end; |
39 | int n[4] = { 0, 0, 0, 0 }; |
40 | |
41 | if (str_len % 4) { errno = EBADMSG; return -1; } |
42 | q = (unsigned char*) data; |
43 | end = q + data_len; |
44 | str_end = s + str_len; |
45 | |
46 | for (p = s; p < str_end; ) { |
47 | n[0] = POS(*p++); |
48 | n[1] = POS(*p++); |
49 | n[2] = POS(*p++); |
50 | n[3] = POS(*p++); |
51 | |
52 | if (n[0] == -2 || n[1] == -2 || n[2] == -2 || n[3] == -2) |
53 | { errno = EBADMSG; return -1; } |
54 | |
55 | if (n[0] == -1 || n[1] == -1) |
56 | { errno = EBADMSG; return -1; } |
57 | |
58 | if (n[2] == -1 && n[3] != -1) |
59 | { errno = EBADMSG; return -1; } |
60 | |
61 | if (q >= end) { errno = EMSGSIZE; return -1; } |
62 | q[0] = (n[0] << 2) + (n[1] >> 4); |
63 | if (n[2] != -1) { |
64 | if (q+1 >= end) { errno = EMSGSIZE; return -1; } |
65 | q[1] = ((n[1] & 15) << 4) + (n[2] >> 2); |
66 | } |
67 | if (n[3] != -1) { |
68 | if (q+2 >= end) { errno = EMSGSIZE; return -1; } |
69 | q[2] = ((n[2] & 3) << 6) + n[3]; |
70 | } |
71 | q += 3; |
72 | } |
73 | |
74 | return 0; |
75 | } |
76 | |
77 | int base64_encode(const void* buf, size_t size, char *str, size_t out_size) { |
78 | static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
79 | |
80 | char* p = str; |
81 | const unsigned char* q = (const unsigned char*) buf; |
82 | size_t i = 0; |
83 | |
84 | if ((size+3)*4/3 + 1 > out_size) { |
85 | errno = EMSGSIZE; |
86 | return -1; |
87 | } |
88 | |
89 | while (i < size) { |
90 | int c = q[i++]; |
91 | c *= 256; |
92 | if (i < size) |
93 | c += q[i]; |
94 | i++; |
95 | |
96 | c *= 256; |
97 | if (i < size) |
98 | c += q[i]; |
99 | i++; |
100 | |
101 | *p++ = base64[(c & 0x00fc0000) >> 18]; |
102 | *p++ = base64[(c & 0x0003f000) >> 12]; |
103 | |
104 | if (i > size + 1) |
105 | *p++ = '='; |
106 | else |
107 | *p++ = base64[(c & 0x00000fc0) >> 6]; |
108 | |
109 | if (i > size) |
110 | *p++ = '='; |
111 | else |
112 | *p++ = base64[c & 0x0000003f]; |
113 | } |
114 | |
115 | *p = 0; |
116 | |
117 | return 0; |
118 | } |
119 |
Built with git-ssb-web