Imported Upstream version 2.5.1
[ossec-hids.git] / src / addagent / b64.c
1 /* @(#) $Id$ */
2 /*
3  * Copyright (C), 2000-2004 by the monit project group.
4  * All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #define TRUE    1
26 #define FALSE   0
27
28 char *decode_base64(const char *src);
29 char *encode_base64(int size, char *src);
30
31 /* Private prototypes */
32 static int is_base64(char c);
33 static char encode(unsigned char u);
34 static unsigned char decode(char c);
35
36
37 /**
38  *  Implementation of base64 encoding/decoding. 
39  *
40  *  @author Jan-Henrik Haukeland, <hauk@tildeslash.com>
41  *
42  *  @version \$Id$
43  *
44  *  @file
45  */
46
47
48
49 /**
50  * Base64 encode and return size data in 'src'. The caller must free the
51  * returned string.
52  * @param size The size of the data in src
53  * @param src The data to be base64 encode
54  * @return encoded string otherwise NULL
55  */
56 char *encode_base64(int size, char *src) {
57
58     int i;
59     char *out, *p;
60
61     if(!src)
62         return NULL;
63
64     if(!size)
65         size= strlen((char *)src);
66
67     out = (char *)calloc(sizeof(char), size*4/3+4);
68     if(!out)
69         return NULL;
70     
71     p = out;
72
73     for(i = 0; i < size; i+=3) {
74
75         unsigned char b1=0, b2=0, b3=0, b4=0, b5=0, b6=0, b7=0;
76
77         b1 = src[i];
78
79         if(i+1<size)
80             b2 = src[i+1];
81
82         if(i+2<size)
83             b3 = src[i+2];
84
85         b4= b1>>2;
86         b5= ((b1&0x3)<<4)|(b2>>4);
87         b6= ((b2&0xf)<<2)|(b3>>6);
88         b7= b3&0x3f;
89
90         *p++= encode(b4);
91         *p++= encode(b5);
92
93         if(i+1<size) {
94             *p++= encode(b6);
95         } else {
96             *p++= '=';
97         }
98
99         if(i+2<size) {
100             *p++= encode(b7);
101         } else {
102             *p++= '=';
103         }
104
105     }
106
107     return out;
108
109 }
110
111 /**
112  * Decode the base64 encoded string 'src' into the memory pointed to by
113  * 'dest'. The dest buffer is NUL terminated.
114  * Return NULL in case of error
115  */
116 char *decode_base64(const char *src) 
117 {
118     if(src && *src) 
119     {
120         char *dest;
121         unsigned char *p;
122         int k, l = strlen(src)+1;
123         unsigned char *buf;
124         
125         /* The size of the dest will always be less than
126          * the source
127          */
128         dest = (char *)calloc(sizeof(char), l + 13);
129         if(!dest)
130             return(NULL);
131         
132         p = (unsigned char *)dest;
133          
134         buf = malloc(l);
135         if(!buf)
136             return(NULL);
137
138         /* Ignore non base64 chars as per the POSIX standard */
139         for(k=0, l=0; src[k]; k++) 
140         {
141             if(is_base64(src[k])) 
142             {
143                 buf[l++]= src[k];
144             }
145         } 
146
147         for(k=0; k<l; k+=4) 
148         {
149             char c1='A', c2='A', c3='A', c4='A';
150             unsigned char b1=0, b2=0, b3=0, b4=0;
151
152             c1= buf[k];
153
154             if(k+1<l) 
155             {
156                 c2= buf[k+1];
157             }
158
159             if(k+2<l) {
160                 c3= buf[k+2];
161             }
162
163             if(k+3<l) {
164                 c4= buf[k+3];
165             }
166
167             b1= decode(c1);
168             b2= decode(c2);
169             b3= decode(c3);
170             b4= decode(c4);
171
172             *p++=((b1<<2)|(b2>>4) );
173
174             if(c3 != '=') {
175                 *p++=(((b2&0xf)<<4)|(b3>>2) );
176             }
177
178             if(c4 != '=') {
179                 *p++=(((b3&0x3)<<6)|b4 );
180             }
181
182         }
183
184         free(buf);
185
186         /*return(p-dest); */
187         return(dest);
188
189     }
190
191     return(NULL);
192
193 }
194
195
196  /* ----------------------------------------------------------------- Private */
197
198 static char encode(unsigned char u) {
199
200     if(u < 26)  return 'A'+u;
201     if(u < 52)  return 'a'+(u-26);
202     if(u < 62)  return '0'+(u-52);
203     if(u == 62) return '+';
204
205     return '/';
206
207 }
208
209
210 /**
211  * Decode a base64 character
212  */
213 static unsigned char decode(char c) {
214
215     if(c >= 'A' && c <= 'Z') return(c - 'A');
216     if(c >= 'a' && c <= 'z') return(c - 'a' + 26);
217     if(c >= '0' && c <= '9') return(c - '0' + 52);
218     if(c == '+')             return 62;
219
220     return 63;
221
222 }
223
224
225 /**
226  * Return TRUE if 'c' is a valid base64 character, otherwise FALSE
227  */
228 static int is_base64(char c) {
229
230     if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
231             (c >= '0' && c <= '9') || (c == '+')             ||
232             (c == '/')             || (c == '=')) {
233
234         return TRUE;
235
236     }
237
238     return FALSE;
239
240 }
241
242
243 /*
244 int main(int argc, char **argv)
245 {
246     char *s;
247     char *d;
248     
249     if(argc < 2)
250     {
251         printf("%s string\n",argv[0]);
252         exit(1);
253     }
254     s = encode_base64(strlen(argv[1]), argv[1]);
255
256     printf("b64:\n%s\n",s);
257
258
259     d = decode_base64(s);
260     printf("decode:%s\n",d);
261     
262     exit(0);
263 }
264
265 */
266
267
268 /* EOF */