]> git.ipfire.org Git - thirdparty/squid.git/blob - lib/base64.c
Import of fix-ranges branch
[thirdparty/squid.git] / lib / base64.c
1 /*
2 * $Id: base64.c,v 1.21 2003/01/23 00:37:01 robertc Exp $
3 */
4
5 #include "config.h"
6 #include "util.h"
7
8 #if HAVE_STDIO_H
9 #include <stdio.h>
10 #endif
11 #if HAVE_STDLIB_H
12 #include <stdlib.h>
13 #endif
14
15
16 static void base64_init(void);
17
18 static int base64_initialized = 0;
19 #define BASE64_VALUE_SZ 256
20 #define BASE64_RESULT_SZ 8192
21 int base64_value[BASE64_VALUE_SZ];
22 const char base64_code[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
23
24
25 static void
26 base64_init(void)
27 {
28 int i;
29
30 for (i = 0; i < BASE64_VALUE_SZ; i++)
31 base64_value[i] = -1;
32
33 for (i = 0; i < 64; i++)
34 base64_value[(int) base64_code[i]] = i;
35 base64_value['='] = 0;
36
37 base64_initialized = 1;
38 }
39
40 char *
41 base64_decode(const char *p)
42 {
43 static char result[BASE64_RESULT_SZ];
44 int j;
45 int c;
46 long val;
47 if (!p)
48 return NULL;
49 if (!base64_initialized)
50 base64_init();
51 val = c = 0;
52 for (j = 0; *p && j + 4 < BASE64_RESULT_SZ; p++) {
53 unsigned int k = ((unsigned char) *p) % BASE64_VALUE_SZ;
54 if (base64_value[k] < 0)
55 continue;
56 val <<= 6;
57 val += base64_value[k];
58 if (++c < 4)
59 continue;
60 /* One quantum of four encoding characters/24 bit */
61 result[j++] = (val >> 16) & 0xff; /* High 8 bits */
62 result[j++] = (val >> 8) & 0xff; /* Mid 8 bits */
63 result[j++] = val & 0xff; /* Low 8 bits */
64 val = c = 0;
65 }
66 result[j] = 0;
67 return result;
68 }
69
70 /* adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments */
71 const char *
72 base64_encode(const char *decoded_str)
73 {
74 static char result[BASE64_RESULT_SZ];
75 int bits = 0;
76 int char_count = 0;
77 int out_cnt = 0;
78 int c;
79
80 if (!decoded_str)
81 return decoded_str;
82
83 if (!base64_initialized)
84 base64_init();
85
86 while ((c = (unsigned char) *decoded_str++) && out_cnt < sizeof(result) - 5) {
87 bits += c;
88 char_count++;
89 if (char_count == 3) {
90 result[out_cnt++] = base64_code[bits >> 18];
91 result[out_cnt++] = base64_code[(bits >> 12) & 0x3f];
92 result[out_cnt++] = base64_code[(bits >> 6) & 0x3f];
93 result[out_cnt++] = base64_code[bits & 0x3f];
94 bits = 0;
95 char_count = 0;
96 } else {
97 bits <<= 8;
98 }
99 }
100 if (char_count != 0) {
101 bits <<= 16 - (8 * char_count);
102 result[out_cnt++] = base64_code[bits >> 18];
103 result[out_cnt++] = base64_code[(bits >> 12) & 0x3f];
104 if (char_count == 1) {
105 result[out_cnt++] = '=';
106 result[out_cnt++] = '=';
107 } else {
108 result[out_cnt++] = base64_code[(bits >> 6) & 0x3f];
109 result[out_cnt++] = '=';
110 }
111 }
112 result[out_cnt] = '\0'; /* terminate */
113 return result;
114 }
115
116 /* adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments */
117 const char *
118 base64_encode_bin(const char *data, int len)
119 {
120 static char result[BASE64_RESULT_SZ];
121 int bits = 0;
122 int char_count = 0;
123 int out_cnt = 0;
124
125 if (!data)
126 return data;
127
128 if (!base64_initialized)
129 base64_init();
130
131 while (len-- && out_cnt < sizeof(result) - 5) {
132 int c = (unsigned char) *data++;
133 bits += c;
134 char_count++;
135 if (char_count == 3) {
136 result[out_cnt++] = base64_code[bits >> 18];
137 result[out_cnt++] = base64_code[(bits >> 12) & 0x3f];
138 result[out_cnt++] = base64_code[(bits >> 6) & 0x3f];
139 result[out_cnt++] = base64_code[bits & 0x3f];
140 bits = 0;
141 char_count = 0;
142 } else {
143 bits <<= 8;
144 }
145 }
146 if (char_count != 0) {
147 bits <<= 16 - (8 * char_count);
148 result[out_cnt++] = base64_code[bits >> 18];
149 result[out_cnt++] = base64_code[(bits >> 12) & 0x3f];
150 if (char_count == 1) {
151 result[out_cnt++] = '=';
152 result[out_cnt++] = '=';
153 } else {
154 result[out_cnt++] = base64_code[(bits >> 6) & 0x3f];
155 result[out_cnt++] = '=';
156 }
157 }
158 result[out_cnt] = '\0'; /* terminate */
159 return result;
160 }