Blame modules/base64.c

Packit Service a4b2a9
#include <base64.h>
Packit Service a4b2a9
Packit Service a4b2a9
/*
Packit Service a4b2a9
 * characters used for Base64 encoding
Packit Service a4b2a9
 */
Packit Service a4b2a9
static const char *BASE64_CHARS =
Packit Service a4b2a9
	 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
Packit Service a4b2a9
Packit Service a4b2a9
/*
Packit Service a4b2a9
 * encode three bytes using base64 (RFC 3548)
Packit Service a4b2a9
 *
Packit Service a4b2a9
 * @param triple three bytes that should be encoded
Packit Service a4b2a9
 * @param result buffer of four characters where the result is stored
Packit Service a4b2a9
 */
Packit Service a4b2a9
static void _base64_encode_triple(unsigned char triple[3], char result[4])
Packit Service a4b2a9
{
Packit Service a4b2a9
	int tripleValue, i;
Packit Service a4b2a9
Packit Service a4b2a9
	tripleValue = triple[0];
Packit Service a4b2a9
	tripleValue *= 256;
Packit Service a4b2a9
	tripleValue += triple[1];
Packit Service a4b2a9
	tripleValue *= 256;
Packit Service a4b2a9
	tripleValue += triple[2];
Packit Service a4b2a9
Packit Service a4b2a9
	for (i=0; i<4; i++) {
Packit Service a4b2a9
		result[3 - i] = BASE64_CHARS[tripleValue % 64];
Packit Service a4b2a9
		tripleValue /= 64;
Packit Service a4b2a9
	}
Packit Service a4b2a9
}
Packit Service a4b2a9
Packit Service a4b2a9
/*
Packit Service a4b2a9
 * encode an array of bytes using Base64 (RFC 3548)
Packit Service a4b2a9
 *
Packit Service a4b2a9
 * @param source the source buffer
Packit Service a4b2a9
 * @param sourcelen the length of the source buffer
Packit Service a4b2a9
 * @param target the target buffer
Packit Service a4b2a9
 * @param targetlen the length of the target buffer
Packit Service a4b2a9
 * @return 1 on success, 0 otherwise
Packit Service a4b2a9
 */
Packit Service a4b2a9
int base64_encode(char *source, size_t sourcelen, char *target, size_t targetlen)
Packit Service a4b2a9
{
Packit Service a4b2a9
	/* check if the result will fit in the target buffer */
Packit Service a4b2a9
	if ((sourcelen + 2)/ 3*4 > targetlen - 1)
Packit Service a4b2a9
		return 0;
Packit Service a4b2a9
Packit Service a4b2a9
	/* encode all full triples */
Packit Service a4b2a9
	while (sourcelen >= 3) {
Packit Service a4b2a9
		_base64_encode_triple(source, target);
Packit Service a4b2a9
		sourcelen -= 3;
Packit Service a4b2a9
		source += 3;
Packit Service a4b2a9
		target += 4;
Packit Service a4b2a9
	}
Packit Service a4b2a9
Packit Service a4b2a9
	/* encode the last one or two characters */
Packit Service a4b2a9
	if (sourcelen > 0) {
Packit Service a4b2a9
		unsigned char temp[3];
Packit Service a4b2a9
		memset(temp, 0, sizeof(temp));
Packit Service a4b2a9
		memcpy(temp, source, sourcelen);
Packit Service a4b2a9
		_base64_encode_triple(temp, target);
Packit Service a4b2a9
		target[3] = '=';
Packit Service a4b2a9
		if (sourcelen == 1)
Packit Service a4b2a9
			target[2] = '=';
Packit Service a4b2a9
		target += 4;
Packit Service a4b2a9
	}
Packit Service a4b2a9
Packit Service a4b2a9
	/* terminate the string */
Packit Service a4b2a9
	target[0] = 0;
Packit Service a4b2a9
Packit Service a4b2a9
	return 1;
Packit Service a4b2a9
}
Packit Service a4b2a9
Packit Service a4b2a9
/*
Packit Service a4b2a9
 * determine the value of a base64 encoding character
Packit Service a4b2a9
 *
Packit Service a4b2a9
 * @param base64char the character of which the value is searched
Packit Service a4b2a9
 * @return the value in case of success (0-63), -1 on failure
Packit Service a4b2a9
 */
Packit Service a4b2a9
static int _base64_char_value(char base64char)
Packit Service a4b2a9
{
Packit Service a4b2a9
	if (base64char >= 'A' && base64char <= 'Z')
Packit Service a4b2a9
		return base64char-'A';
Packit Service a4b2a9
	if (base64char >= 'a' && base64char <= 'z')
Packit Service a4b2a9
		return base64char-'a'+26;
Packit Service a4b2a9
	if (base64char >= '0' && base64char <= '9')
Packit Service a4b2a9
		return base64char-'0'+2*26;
Packit Service a4b2a9
	if (base64char == '+')
Packit Service a4b2a9
		return 2*26+10;
Packit Service a4b2a9
	if (base64char == '/')
Packit Service a4b2a9
		return 2*26+11;
Packit Service a4b2a9
	return -1;
Packit Service a4b2a9
}
Packit Service a4b2a9
Packit Service a4b2a9
/*
Packit Service a4b2a9
 * decode a 4 char base64 encoded byte triple
Packit Service a4b2a9
 *
Packit Service a4b2a9
 * @param quadruple the 4 characters that should be decoded
Packit Service a4b2a9
 * @param result the decoded data
Packit Service a4b2a9
 * @return lenth of the result (1, 2 or 3), 0 on failure
Packit Service a4b2a9
 */
Packit Service a4b2a9
static int _base64_decode_triple(char quadruple[4], char *result)
Packit Service a4b2a9
{
Packit Service a4b2a9
	int i, triple_value, bytes_to_decode = 3, only_equals_yet = 1;
Packit Service a4b2a9
	int char_value[4];
Packit Service a4b2a9
Packit Service a4b2a9
	for (i=0; i<4; i++)
Packit Service a4b2a9
		char_value[i] = _base64_char_value(quadruple[i]);
Packit Service a4b2a9
Packit Service a4b2a9
	/* check if the characters are valid */
Packit Service a4b2a9
	for (i=3; i>=0; i--) {
Packit Service a4b2a9
		if (char_value[i]<0) {
Packit Service a4b2a9
			if (only_equals_yet && quadruple[i]=='=') {
Packit Service a4b2a9
				/* we will ignore this character anyway, make it
Packit Service a4b2a9
				 * something that does not break our calculations */
Packit Service a4b2a9
				char_value[i]=0;
Packit Service a4b2a9
				bytes_to_decode--;
Packit Service a4b2a9
				continue;
Packit Service a4b2a9
			}
Packit Service a4b2a9
			return 0;
Packit Service a4b2a9
		}
Packit Service a4b2a9
		/* after we got a real character, no other '=' are allowed anymore */
Packit Service a4b2a9
		only_equals_yet = 0;
Packit Service a4b2a9
	}
Packit Service a4b2a9
Packit Service a4b2a9
	/* if we got "====" as input, bytes_to_decode is -1 */
Packit Service a4b2a9
	if (bytes_to_decode < 0)
Packit Service a4b2a9
		bytes_to_decode = 0;
Packit Service a4b2a9
Packit Service a4b2a9
	/* make one big value out of the partial values */
Packit Service a4b2a9
	triple_value = char_value[0];
Packit Service a4b2a9
	triple_value *= 64;
Packit Service a4b2a9
	triple_value += char_value[1];
Packit Service a4b2a9
	triple_value *= 64;
Packit Service a4b2a9
	triple_value += char_value[2];
Packit Service a4b2a9
	triple_value *= 64;
Packit Service a4b2a9
	triple_value += char_value[3];
Packit Service a4b2a9
Packit Service a4b2a9
	/* break the big value into bytes */
Packit Service a4b2a9
	for (i=bytes_to_decode; i<3; i++)
Packit Service a4b2a9
		triple_value /= 256;
Packit Service a4b2a9
	for (i=bytes_to_decode-1; i>=0; i--) {
Packit Service a4b2a9
		result[i] = triple_value%256;
Packit Service a4b2a9
		triple_value /= 256;
Packit Service a4b2a9
	}
Packit Service a4b2a9
Packit Service a4b2a9
	return bytes_to_decode;
Packit Service a4b2a9
}
Packit Service a4b2a9
Packit Service a4b2a9
/*
Packit Service a4b2a9
 * decode base64 encoded data
Packit Service a4b2a9
 *
Packit Service a4b2a9
 * @param source the encoded data (zero terminated)
Packit Service a4b2a9
 * @param target pointer to the target buffer
Packit Service a4b2a9
 * @param targetlen length of the target buffer
Packit Service a4b2a9
 * @return length of converted data on success, -1 otherwise
Packit Service a4b2a9
 */
Packit Service a4b2a9
size_t base64_decode(char *source, char *target, size_t targetlen)
Packit Service a4b2a9
{
Packit Service a4b2a9
	char *src, *tmpptr;
Packit Service a4b2a9
	char quadruple[4], tmpresult[3];
Packit Service a4b2a9
	int i, tmplen = 3;
Packit Service a4b2a9
	size_t converted = 0;
Packit Service a4b2a9
Packit Service a4b2a9
	/* concatinate '===' to the source to handle unpadded base64 data */
Packit Service a4b2a9
	src = malloc(strlen(source)+5);
Packit Service a4b2a9
	if (src == NULL)
Packit Service a4b2a9
		return -1;
Packit Service a4b2a9
	strcpy(src, source);
Packit Service a4b2a9
	strcat(src, "====");
Packit Service a4b2a9
	tmpptr = src;
Packit Service a4b2a9
Packit Service a4b2a9
	memset(target, 0, targetlen);
Packit Service a4b2a9
Packit Service a4b2a9
	/* convert as long as we get a full result */
Packit Service a4b2a9
	while (tmplen == 3) {
Packit Service a4b2a9
		/* get 4 characters to convert */
Packit Service a4b2a9
		for (i = 0; i < 4; i++) {
Packit Service a4b2a9
			/* skip invalid characters - we won't reach the end */
Packit Service a4b2a9
			while (*tmpptr != '=' && _base64_char_value(*tmpptr) < 0)
Packit Service a4b2a9
				tmpptr++;
Packit Service a4b2a9
			quadruple[i] = *(tmpptr++);
Packit Service a4b2a9
		}
Packit Service a4b2a9
Packit Service a4b2a9
		/* convert the characters */
Packit Service a4b2a9
		tmplen = _base64_decode_triple(quadruple, tmpresult);
Packit Service a4b2a9
Packit Service a4b2a9
		/* check if the fit in the result buffer */
Packit Service a4b2a9
		if (targetlen < tmplen) {
Packit Service a4b2a9
			free(src);
Packit Service a4b2a9
			return -1;
Packit Service a4b2a9
		}
Packit Service a4b2a9
Packit Service a4b2a9
		/* put the partial result in the result buffer */
Packit Service a4b2a9
		memcpy(target, tmpresult, tmplen);
Packit Service a4b2a9
		target += tmplen;
Packit Service a4b2a9
		targetlen -= tmplen;
Packit Service a4b2a9
		converted += tmplen;
Packit Service a4b2a9
	}
Packit Service a4b2a9
Packit Service a4b2a9
	free(src);
Packit Service a4b2a9
	return converted;
Packit Service a4b2a9
}
Packit Service a4b2a9
Packit Service a4b2a9
#if 0
Packit Service a4b2a9
#include <stdio.h>
Packit Service a4b2a9
Packit Service a4b2a9
int main(int argc, char **argv)
Packit Service a4b2a9
{
Packit Service a4b2a9
	char *source = "testt(estt#wot%est'ing";
Packit Service a4b2a9
	int source_len = strlen(source);
Packit Service a4b2a9
	char dest[80];
Packit Service a4b2a9
	int dest_len = 79;
Packit Service a4b2a9
	char decoded[80];
Packit Service a4b2a9
	int decode_len = 79;
Packit Service a4b2a9
	int len;
Packit Service a4b2a9
Packit Service a4b2a9
	printf("string %s\n", source);
Packit Service a4b2a9
Packit Service a4b2a9
	if (base64_encode(source, source_len, dest, dest_len))
Packit Service a4b2a9
		printf("encoded %s len %d\n", dest, strlen(dest));
Packit Service a4b2a9
Packit Service a4b2a9
	len = base64_decode(dest, decoded, decode_len);
Packit Service a4b2a9
	if (len != -1)
Packit Service a4b2a9
		printf("decoded %s len %d\n", decoded, len);
Packit Service a4b2a9
}
Packit Service a4b2a9
#endif