gwenhywfar  4.8.0beta
base64.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Thu May 06 2004
3  copyright : (C) 2004 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 #define DISABLE_DEBUGLOG
31 
32 
33 #include "base64.h"
34 #include <gwenhywfar/misc.h>
35 #include <gwenhywfar/debug.h>
36 #include <gwenhywfar/text.h>
37 #include <string.h>
38 
39 
40 static const char GWEN_Base64_Alphabet[]=
41  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
42 
43 
44 int GWEN_Base64_Encode(const unsigned char *src, unsigned int size,
45  GWEN_BUFFER *dst,
46  unsigned int maxLineLength) {
47  unsigned int by3;
48  unsigned int i;
49  unsigned int l;
50  uint32_t triplet;
51  unsigned char c1, c2, c3, c4;
52 
53  if (maxLineLength) {
54  if (maxLineLength<4) {
55  DBG_ERROR(GWEN_LOGDOMAIN, "I need at least 4 bytes per line");
56  return -1;
57  }
58  }
59 
60  by3=size/3;
61  /* first encode full triplets */
62  l=0;
63  for (i=0; i<by3; i++) {
64  triplet=(src[0]<<16)+(src[1]<<8)+src[2];
65  src+=3;
66  c4=triplet & 0x3f;
67  triplet>>=6;
68  c3=triplet & 0x3f;
69  triplet>>=6;
70  c2=triplet & 0x3f;
71  triplet>>=6;
72  c1=triplet & 0x3f;
73  if (maxLineLength) {
74  if (l+4>maxLineLength) {
75  GWEN_Buffer_AppendByte(dst, '\n');
76  l=0;
77  }
78  l+=4;
79  }
84  }
85  if (maxLineLength) {
86  if (l+4>=maxLineLength) {
87  GWEN_Buffer_AppendByte(dst, '\n');
88  l=0;
89  }
90  }
91 
92  /* then encode remainder */
93  switch(size % 3) {
94  case 0:
95  /* no remainder */
96  break;
97 
98  case 1:
99  /* 1 remainder, leads to two trailing "=" */
100  triplet=(src[0]<<4);
101  c2=triplet & 0x3f;
102  triplet>>=6;
103  c1=triplet & 0x3f;
106  GWEN_Buffer_AppendString(dst, "==");
107  break;
108 
109  case 2:
110  /* 2 remainders, leads to one trailing "=" */
111  triplet=(src[0]<<10)+(src[1]<<2);
112  c3=triplet & 0x3f;
113  triplet>>=6;
114  c2=triplet & 0x3f;
115  triplet>>=6;
116  c1=triplet & 0x3f;
120  GWEN_Buffer_AppendByte(dst, '=');
121  break;
122 
123  default:
124  break;
125  }
126 
127  return 0;
128 }
129 
130 
131 
132 int GWEN_Base64_Decode(const unsigned char *src, unsigned int size,
133  GWEN_BUFFER *dst) {
134  unsigned int i;
135  const char *p = "0";
136  uint32_t v;
137  int lastWasEq;
138  int sizeGiven;
139 
140  /* first decode full triplets */
141  sizeGiven=(size!=0);
142  lastWasEq=0;
143  for (;;) {
144  if ((sizeGiven && size==0) || lastWasEq || !*src)
145  break;
146  v=0;
147 
148  while (*src && ((p=strchr(GWEN_Base64_Alphabet, *src))==0))
149  src++;
150  if (!*src)
151  break;
152  for (i=0; i<4; i++) {
153  /* get next valid character */
154  if (lastWasEq) {
155  while (*src && *src!='=')
156  src++;
157  }
158  else {
159  while (*src && ((p=strchr(GWEN_Base64_Alphabet, *src))==0))
160  src++;
161  }
162  if (!*src) {
163  if (i==0 && !sizeGiven) {
164  return 0;
165  }
166  else {
167  DBG_ERROR(GWEN_LOGDOMAIN, "Premature end reached (%d)", i);
168  return -1;
169  }
170  }
171  if (*src=='=')
172  lastWasEq++;
173  v<<=6;
174  v+=(p-GWEN_Base64_Alphabet) & 0x3f;
175  src++;
176  } /* for */
177 
178  /* now we have a triplet */
179  if (sizeGiven) {
180  switch(size) {
181  case 1:
182  GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
183  size--;
184  break;
185  case 2:
186  GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
187  GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff);
188  size-=2;
189  break;
190  default:
191  GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
192  GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff);
193  GWEN_Buffer_AppendByte(dst, v & 0xff);
194  size-=3;
195  break;
196  } /* switch */
197  }
198  else {
199  int bytes;
200 
201  bytes=(24-(lastWasEq*6))/8;
202  if (bytes) {
203  GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
204  if (bytes>1) {
205  GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff);
206  if (bytes>2)
207  GWEN_Buffer_AppendByte(dst, v & 0xff);
208  }
209  }
210  }
211  } /* for full quadruplets */
212 
213  return 0;
214 }
215 
216 
217 
218 
219