~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/base64.c

  • Committer: Monty Taylor
  • Date: 2010-10-15 17:18:02 UTC
  • mto: (1859.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1860.
  • Revision ID: mordred@inaugust.com-20101015171802-qhk6zyfhrkvprr1n
Added support for registering regular sys_var instances via module::Context.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2003 MySQL AB
2
 
 
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 of the License.
6
 
 
7
 
   This program is distributed in the hope that it will be useful,
8
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
   GNU General Public License for more details.
11
 
 
12
 
   You should have received a copy of the GNU General Public License
13
 
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
 
 
16
 
#include <mystrings/m_string.h>  /* strchr() */
17
 
#include <mystrings/m_ctype.h>  /* my_isspace() */
18
 
#include <mysys/base64.h>
19
 
 
20
 
#ifndef MAIN
21
 
 
22
 
static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
23
 
                             "abcdefghijklmnopqrstuvwxyz"
24
 
                             "0123456789+/";
25
 
 
26
 
 
27
 
int
28
 
base64_needed_encoded_length(int length_of_data)
29
 
{
30
 
  int nb_base64_chars;
31
 
  nb_base64_chars= (length_of_data + 2) / 3 * 4;
32
 
 
33
 
  return
34
 
    nb_base64_chars +            /* base64 char incl padding */
35
 
    (nb_base64_chars - 1)/ 76 +  /* newlines */
36
 
    1;                           /* NUL termination of string */
37
 
}
38
 
 
39
 
 
40
 
int
41
 
base64_needed_decoded_length(int length_of_encoded_data)
42
 
{
43
 
  return (int) ceil(length_of_encoded_data * 3 / 4);
44
 
}
45
 
 
46
 
 
47
 
/*
48
 
  Encode a data as base64.
49
 
 
50
 
  Note: We require that dst is pre-allocated to correct size.
51
 
        See base64_needed_encoded_length().
52
 
*/
53
 
 
54
 
int
55
 
base64_encode(const void *src, size_t src_len, char *dst)
56
 
{
57
 
  const unsigned char *s= (const unsigned char*)src;
58
 
  size_t i= 0;
59
 
  size_t len= 0;
60
 
 
61
 
  for (; i < src_len; len += 4)
62
 
  {
63
 
    unsigned c;
64
 
 
65
 
    if (len == 76)
66
 
    {
67
 
      len= 0;
68
 
      *dst++= '\n';
69
 
    }
70
 
 
71
 
    c= s[i++];
72
 
    c <<= 8;
73
 
 
74
 
    if (i < src_len)
75
 
      c += s[i];
76
 
    c <<= 8;
77
 
    i++;
78
 
 
79
 
    if (i < src_len)
80
 
      c += s[i];
81
 
    i++;
82
 
 
83
 
    *dst++= base64_table[(c >> 18) & 0x3f];
84
 
    *dst++= base64_table[(c >> 12) & 0x3f];
85
 
 
86
 
    if (i > (src_len + 1))
87
 
      *dst++= '=';
88
 
    else
89
 
      *dst++= base64_table[(c >> 6) & 0x3f];
90
 
 
91
 
    if (i > src_len)
92
 
      *dst++= '=';
93
 
    else
94
 
      *dst++= base64_table[(c >> 0) & 0x3f];
95
 
  }
96
 
  *dst= '\0';
97
 
 
98
 
  return 0;
99
 
}
100
 
 
101
 
 
102
 
static inline uint
103
 
pos(unsigned char c)
104
 
{
105
 
  return (uint) (strchr(base64_table, c) - base64_table);
106
 
}
107
 
 
108
 
 
109
 
#define SKIP_SPACE(src, i, size)                                \
110
 
{                                                               \
111
 
  while (i < size && my_isspace(&my_charset_latin1, * src))     \
112
 
  {                                                             \
113
 
    i++;                                                        \
114
 
    src++;                                                      \
115
 
  }                                                             \
116
 
  if (i == size)                                                \
117
 
  {                                                             \
118
 
    break;                                                      \
119
 
  }                                                             \
120
 
}
121
 
 
122
 
 
123
 
/*
124
 
  Decode a base64 string
125
 
 
126
 
  SYNOPSIS
127
 
    base64_decode()
128
 
    src      Pointer to base64-encoded string
129
 
    len      Length of string at 'src'
130
 
    dst      Pointer to location where decoded data will be stored
131
 
    end_ptr  Pointer to variable that will refer to the character
132
 
             after the end of the encoded data that were decoded. Can
133
 
             be NULL.
134
 
 
135
 
  DESCRIPTION
136
 
 
137
 
    The base64-encoded data in the range ['src','*end_ptr') will be
138
 
    decoded and stored starting at 'dst'.  The decoding will stop
139
 
    after 'len' characters have been read from 'src', or when padding
140
 
    occurs in the base64-encoded data. In either case: if 'end_ptr' is
141
 
    non-null, '*end_ptr' will be set to point to the character after
142
 
    the last read character, even in the presence of error.
143
 
 
144
 
  NOTE
145
 
    We require that 'dst' is pre-allocated to correct size.
146
 
 
147
 
  SEE ALSO
148
 
    base64_needed_decoded_length().
149
 
 
150
 
  RETURN VALUE
151
 
    Number of bytes written at 'dst' or -1 in case of failure
152
 
*/
153
 
int
154
 
base64_decode(const char *src_base, size_t len,
155
 
              void *dst, const char **end_ptr)
156
 
{
157
 
  char b[3];
158
 
  size_t i= 0;
159
 
  char *dst_base= (char *)dst;
160
 
  char const *src= src_base;
161
 
  char *d= dst_base;
162
 
  size_t j;
163
 
 
164
 
  while (i < len)
165
 
  {
166
 
    unsigned c= 0;
167
 
    size_t mark= 0;
168
 
 
169
 
    SKIP_SPACE(src, i, len);
170
 
 
171
 
    c += pos(*src++);
172
 
    c <<= 6;
173
 
    i++;
174
 
 
175
 
    SKIP_SPACE(src, i, len);
176
 
 
177
 
    c += pos(*src++);
178
 
    c <<= 6;
179
 
    i++;
180
 
 
181
 
    SKIP_SPACE(src, i, len);
182
 
 
183
 
    if (*src != '=')
184
 
      c += pos(*src++);
185
 
    else
186
 
    {
187
 
      src += 2;                /* There should be two bytes padding */
188
 
      i= len;
189
 
      mark= 2;
190
 
      c <<= 6;
191
 
      goto end;
192
 
    }
193
 
    c <<= 6;
194
 
    i++;
195
 
 
196
 
    SKIP_SPACE(src, i, len);
197
 
 
198
 
    if (*src != '=')
199
 
      c += pos(*src++);
200
 
    else
201
 
    {
202
 
      src += 1;                 /* There should be one byte padding */
203
 
      i= len;
204
 
      mark= 1;
205
 
      goto end;
206
 
    }
207
 
    i++;
208
 
 
209
 
  end:
210
 
    b[0]= (c >> 16) & 0xff;
211
 
    b[1]= (c >>  8) & 0xff;
212
 
    b[2]= (c >>  0) & 0xff;
213
 
 
214
 
    for (j=0; j<3-mark; j++)
215
 
      *d++= b[j];
216
 
  }
217
 
 
218
 
  if (end_ptr != NULL)
219
 
    *end_ptr= src;
220
 
 
221
 
  /*
222
 
    The variable 'i' is set to 'len' when padding has been read, so it
223
 
    does not actually reflect the number of bytes read from 'src'.
224
 
   */
225
 
  return i != len ? -1 : d - dst_base;
226
 
}
227
 
 
228
 
 
229
 
#else /* MAIN */
230
 
 
231
 
#define require(b) { \
232
 
  if (!(b)) { \
233
 
    printf("Require failed at %s:%d\n", __FILE__, __LINE__); \
234
 
    abort(); \
235
 
  } \
236
 
}
237
 
 
238
 
 
239
 
int
240
 
main(void)
241
 
{
242
 
  int i;
243
 
  size_t j;
244
 
  size_t k, l;
245
 
  size_t dst_len;
246
 
  size_t needed_length;
247
 
 
248
 
  for (i= 0; i < 500; i++)
249
 
  {
250
 
    /* Create source data */
251
 
    const size_t src_len= rand() % 1000 + 1;
252
 
 
253
 
    char * src= (char *) malloc(src_len);
254
 
    char * s= src;
255
 
    char * str;
256
 
    char * dst;
257
 
 
258
 
    require(src);
259
 
    for (j= 0; j<src_len; j++)
260
 
    {
261
 
      char c= rand();
262
 
      *s++= c;
263
 
    }
264
 
 
265
 
    /* Encode */
266
 
    needed_length= base64_needed_encoded_length(src_len);
267
 
    str= (char *) malloc(needed_length);
268
 
    require(str);
269
 
    for (k= 0; k < needed_length; k++)
270
 
      str[k]= 0xff; /* Fill memory to check correct NUL termination */
271
 
    require(base64_encode(src, src_len, str) == 0);
272
 
    require(needed_length == strlen(str) + 1);
273
 
 
274
 
    /* Decode */
275
 
    dst= (char *) malloc(base64_needed_decoded_length(strlen(str)));
276
 
    require(dst);
277
 
    dst_len= base64_decode(str, strlen(str), dst, NULL);
278
 
    require(dst_len == src_len);
279
 
 
280
 
    if (memcmp(src, dst, src_len) != 0)
281
 
    {
282
 
      printf("       --------- src ---------   --------- dst ---------\n");
283
 
      for (k= 0; k<src_len; k+=8)
284
 
      {
285
 
        printf("%.4x   ", (uint) k);
286
 
        for (l=0; l<8 && k+l<src_len; l++)
287
 
        {
288
 
          unsigned char c= src[k+l];
289
 
          printf("%.2x ", (unsigned)c);
290
 
        }
291
 
 
292
 
        printf("  ");
293
 
 
294
 
        for (l=0; l<8 && k+l<dst_len; l++)
295
 
        {
296
 
          unsigned char c= dst[k+l];
297
 
          printf("%.2x ", (unsigned)c);
298
 
        }
299
 
        printf("\n");
300
 
      }
301
 
      printf("src length: %.8x, dst length: %.8x\n",
302
 
             (uint) src_len, (uint) dst_len);
303
 
      require(0);
304
 
    }
305
 
  }
306
 
  printf("Test succeeded.\n");
307
 
  return 0;
308
 
}
309
 
 
310
 
#endif