gwenhywfar  5.10.1
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 {
48  unsigned int by3;
49  unsigned int i;
50  unsigned int l;
51  uint32_t triplet;
52  unsigned char c1, c2, c3, c4;
53 
54  if (maxLineLength) {
55  if (maxLineLength<4) {
56  DBG_ERROR(GWEN_LOGDOMAIN, "I need at least 4 bytes per line");
57  return -1;
58  }
59  }
60 
61  by3=size/3;
62  /* first encode full triplets */
63  l=0;
64  for (i=0; i<by3; i++) {
65  triplet=(src[0]<<16)+(src[1]<<8)+src[2];
66  src+=3;
67  c4=triplet & 0x3f;
68  triplet>>=6;
69  c3=triplet & 0x3f;
70  triplet>>=6;
71  c2=triplet & 0x3f;
72  triplet>>=6;
73  c1=triplet & 0x3f;
74  if (maxLineLength) {
75  if (l+4>maxLineLength) {
76  GWEN_Buffer_AppendByte(dst, '\n');
77  l=0;
78  }
79  l+=4;
80  }
85  }
86  if (maxLineLength) {
87  if (l+4>=maxLineLength) {
88  GWEN_Buffer_AppendByte(dst, '\n');
89  l=0;
90  }
91  }
92 
93  /* then encode remainder */
94  switch (size % 3) {
95  case 0:
96  /* no remainder */
97  break;
98 
99  case 1:
100  /* 1 remainder, leads to two trailing "=" */
101  triplet=(src[0]<<4);
102  c2=triplet & 0x3f;
103  triplet>>=6;
104  c1=triplet & 0x3f;
107  GWEN_Buffer_AppendString(dst, "==");
108  break;
109 
110  case 2:
111  /* 2 remainders, leads to one trailing "=" */
112  triplet=(src[0]<<10)+(src[1]<<2);
113  c3=triplet & 0x3f;
114  triplet>>=6;
115  c2=triplet & 0x3f;
116  triplet>>=6;
117  c1=triplet & 0x3f;
121  GWEN_Buffer_AppendByte(dst, '=');
122  break;
123 
124  default:
125  break;
126  }
127 
128  return 0;
129 }
130 
131 
132 
133 int GWEN_Base64_Decode(const unsigned char *src, unsigned int size,
134  GWEN_BUFFER *dst)
135 {
136  unsigned int i;
137  const char *p = "0";
138  uint32_t v;
139  int lastWasEq;
140  int sizeGiven;
141 
142  /* first decode full triplets */
143  sizeGiven=(size!=0);
144  lastWasEq=0;
145  for (;;) {
146  if ((sizeGiven && size==0) || lastWasEq || !*src)
147  break;
148  v=0;
149 
150  while (*src && ((p=strchr(GWEN_Base64_Alphabet, *src))==0))
151  src++;
152  if (!*src)
153  break;
154  for (i=0; i<4; i++) {
155  /* get next valid character */
156  if (lastWasEq) {
157  while (*src && *src!='=')
158  src++;
159  }
160  else {
161  while (*src && ((p=strchr(GWEN_Base64_Alphabet, *src))==0))
162  src++;
163  }
164  if (!*src) {
165  if (i==0 && !sizeGiven) {
166  return 0;
167  }
168  else {
169  DBG_ERROR(GWEN_LOGDOMAIN, "Premature end reached (%d)", i);
170  return -1;
171  }
172  }
173  if (*src=='=')
174  lastWasEq++;
175  v<<=6;
176  v+=(p-GWEN_Base64_Alphabet) & 0x3f;
177  src++;
178  } /* for */
179 
180  /* now we have a triplet */
181  if (sizeGiven) {
182  switch (size) {
183  case 1:
184  GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
185  size--;
186  break;
187  case 2:
188  GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
189  GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff);
190  size-=2;
191  break;
192  default:
193  GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
194  GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff);
195  GWEN_Buffer_AppendByte(dst, v & 0xff);
196  size-=3;
197  break;
198  } /* switch */
199  }
200  else {
201  int bytes;
202 
203  bytes=(24-(lastWasEq*6))/8;
204  if (bytes) {
205  GWEN_Buffer_AppendByte(dst, (v>>16) & 0xff);
206  if (bytes>1) {
207  GWEN_Buffer_AppendByte(dst, (v>>8) & 0xff);
208  if (bytes>2)
209  GWEN_Buffer_AppendByte(dst, v & 0xff);
210  }
211  }
212  }
213  } /* for full quadruplets */
214 
215  return 0;
216 }
217 
218 
219 
220 
221 
int GWEN_Base64_Decode(const unsigned char *src, unsigned int size, GWEN_BUFFER *dst)
Definition: base64.c:133
#define GWEN_LOGDOMAIN
Definition: logger.h:35
int GWEN_Base64_Encode(const unsigned char *src, unsigned int size, GWEN_BUFFER *dst, unsigned int maxLineLength)
Definition: base64.c:44
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:394
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
static const char GWEN_Base64_Alphabet[]
Definition: base64.c:40
int GWEN_Buffer_AppendString(GWEN_BUFFER *bf, const char *buffer)
Definition: buffer.c:989