/easytag-2.1.7/src/base64.c
C | 218 lines | 102 code | 16 blank | 100 comment | 34 complexity | 26388f2e254e46bf8bb0ec2a8b85033d MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
- /*
- * Copyright (c) 1995 - 1999 Kungliga Tekniska H??gskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
- /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
- The following encoding technique is taken from RFC 1521 by Borenstein
- and Freed. It is reproduced here in a slightly edited form for
- convenience.
- A 65-character subset of US-ASCII is used, enabling 6 bits to be
- represented per printable character. (The extra 65th character, "=",
- is used to signify a special processing function.)
- The encoding process represents 24-bit groups of input bits as output
- strings of 4 encoded characters. Proceeding from left to right, a
- 24-bit input group is formed by concatenating 3 8-bit input groups.
- These 24 bits are then treated as 4 concatenated 6-bit groups, each
- of which is translated into a single digit in the base64 alphabet.
- Each 6-bit group is used as an index into an array of 64 printable
- characters. The character referenced by the index is placed in the
- output string.
- Table 1: The Base64 Alphabet
- Value Encoding Value Encoding Value Encoding Value Encoding
- 0 A 17 R 34 i 51 z
- 1 B 18 S 35 j 52 0
- 2 C 19 T 36 k 53 1
- 3 D 20 U 37 l 54 2
- 4 E 21 V 38 m 55 3
- 5 F 22 W 39 n 56 4
- 6 G 23 X 40 o 57 5
- 7 H 24 Y 41 p 58 6
- 8 I 25 Z 42 q 59 7
- 9 J 26 a 43 r 60 8
- 10 K 27 b 44 s 61 9
- 11 L 28 c 45 t 62 +
- 12 M 29 d 46 u 63 /
- 13 N 30 e 47 v
- 14 O 31 f 48 w (pad) =
- 15 P 32 g 49 x
- 16 Q 33 h 50 y
- Special processing is performed if fewer than 24 bits are available
- at the end of the data being encoded. A full encoding quantum is
- always completed at the end of a quantity. When fewer than 24 input
- bits are available in an input group, zero bits are added (on the
- right) to form an integral number of 6-bit groups. Padding at the
- end of the data is performed using the '=' character.
- Since all base64 input is an integral number of octets, only the
- -------------------------------------------------
- following cases can arise:
- (1) the final quantum of encoding input is an integral
- multiple of 24 bits; here, the final unit of encoded
- output will be an integral multiple of 4 characters
- with no "=" padding,
- (2) the final quantum of encoding input is exactly 8 bits;
- here, the final unit of encoded output will be two
- characters followed by two "=" padding characters, or
- (3) the final quantum of encoding input is exactly 16 bits;
- here, the final unit of encoded output will be three
- characters followed by one "=" padding character.
- */
- /* $Id: base64.c,v 1.5 2001/05/28 17:33:41 joda Exp $ */
- /*
- * Code taken from Kerberos krb4-1.2.2
- */
- #include <stdlib.h>
- #include <string.h>
- #include "base64.h"
- /* Useful for encoding */
- static char base64_chars[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- /* For constant time lookups */
- static int
- is_base64_char(char c)
- {
- return (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') ||
- ('0' <= c && c <= '9') || (c == '+' || c == '/'));
- }
- static int
- pos(char c)
- {
- char *p;
- for (p = base64_chars; *p; p++)
- if (*p == c)
- return p - base64_chars;
- return -1;
- }
- int
- base64_encode(const void *data, int size, char **str)
- {
- char *s, *p;
- int i;
- int c;
- const unsigned char *q;
- p = s = (char *) malloc(size * 4 / 3 + 4);
- if (p == NULL)
- return -1;
- q = (const unsigned char *) data;
- i = 0;
- for (i = 0; i < size;)
- {
- c = q[i++];
- c *= 256;
- if (i < size)
- c += q[i];
- i++;
- c *= 256;
- if (i < size)
- c += q[i];
- i++;
- p[0] = base64_chars[(c & 0x00fc0000) >> 18];
- p[1] = base64_chars[(c & 0x0003f000) >> 12];
- p[2] = base64_chars[(c & 0x00000fc0) >> 6];
- p[3] = base64_chars[(c & 0x0000003f) >> 0];
- if (i > size)
- p[3] = '=';
- if (i > size + 1)
- p[2] = '=';
- p += 4;
- }
- *p = 0;
- *str = s;
- return strlen(s);
- }
- #define DECODE_ERROR ((unsigned) -1)
- static unsigned int
- token_decode(const char *token, const size_t size)
- {
- int i;
- unsigned int val = 0;
- int marker = 0;
-
- if (size < 4)
- return DECODE_ERROR;
- for (i = 0; i < 4; i++)
- {
- val *= 64;
- if (token[i] == '=')
- marker++;
- else if (marker > 0)
- return DECODE_ERROR;
- else
- val += pos(token[i]);
- }
- if (marker > 2)
- return DECODE_ERROR;
- return (marker << 24) | val;
- }
- int
- base64_decode(const char *str, void *data)
- {
- const char *p;
- unsigned char *q;
- unsigned int size;
- q = data;
- size = strlen(str);
- for (p = str; *p && (*p == '=' || is_base64_char(*p)); p += 4, size -= 4)
- {
- unsigned int val = token_decode(p, size);
- unsigned int marker = (val >> 24) & 0xff;
-
- if (val == DECODE_ERROR)
- return -1;
- *q++ = (val >> 16) & 0xff;
- if (marker < 2)
- *q++ = (val >> 8) & 0xff;
- if (marker < 1)
- *q++ = val & 0xff;
- }
- return q - (unsigned char *) data;
- }