summaryrefslogtreecommitdiffstats
path: root/encode.c
blob: ee901bf10df65d51d1c13c927a6899660d2e2805 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/*	Copyright (C) 2021 Gentoo-libre Install

	This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

	You should have received a copy of the GNU General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <stdlib.h>

//base64Encode: Encodes binary input data into base64. Takes a pointer to a '\0' terminated input string and the size of the string, not including '\0' (e.g. strlen(string))
//Returns pointer to '\0' terminated string on success. Returns NULL if size of input string is zero, or if malloc fails
char *base64Encode(unsigned char *input, int size)
{
char index64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";//lookup table for base64 characters

if (!size){return NULL;}//Catches the case of feeding the function a negative or 0 length.
unsigned char *output = malloc( (((size + 2) / 3) << 2)+1 * sizeof(unsigned char) );//malloc output to the correct size. (length in input string +33%, rounded up to whole number) (+1 for added null char)
if (!output){fprintf(stderr,"Malloc Failed!\n"); return NULL;}

int base64Val;//base64Val is the base64 value resulted when all matching bits values are added together
int i = 0;//i is located at the position of the char currently being processed

int outputPos = 0;//i and the output string of base64 characters don't match up

while (size)//keep looping until all characters have been processed
{
	base64Val=0;
	if (input[i] & 4){++base64Val;}
	if (input[i] & 8){base64Val += 2;}
	if (input[i] & 16){base64Val += 4;}
	if (input[i] & 32){base64Val += 8;}
	if (input[i] & 64){base64Val += 16;}
	if (input[i] & 128){base64Val += 32;}
	output[outputPos++] = index64[base64Val];//the resulting base64 char is placed into output and then outputPos is incremented to the next position for the next char

	//this code may need to read into the NULL char, so it's imporant that the NULL char is there to prevent reading past the buffer
	++i;
	base64Val=0;
	if (input[i] & 16){++base64Val;}
	if (input[i] & 32){base64Val += 2;}
	if (input[i] & 64){base64Val += 4;}
	if (input[i] & 128){base64Val += 8;}
	if (input[i-1] & 1){base64Val += 16;}
	if (input[i-1] & 2){base64Val += 32;}
	output[outputPos++] = index64[base64Val];
	//even if there are no more characters to process at this stage; "===" is not permitted, "A==" should be printed instead
	if ((size == 1)){output[outputPos] = '='; output[outputPos+1] = '='; output[outputPos+2] = '\0'; return output;}

	//read the six bits from one before i and then read the two upper bits as 1 and 2
	++i;
	base64Val=0;
	if (input[i] & 64){++base64Val;}
	if (input[i] & 128){base64Val += 2;}
	if (input[i-1] & 1){base64Val += 4;}
	if (input[i-1] & 2){base64Val += 8;}
	if (input[i-1] & 4){base64Val += 16;}
	if (input[i-1] & 8){base64Val += 32;}
	output[outputPos++] = index64[base64Val];
	if (size == 2){output[outputPos] = '=';  output[outputPos+1] = '\0'; return output;}//if are two letters left at here; "=\0" should be printed

	base64Val=0;
	if (input[i] & 1){++base64Val;}
	if (input[i] & 2){base64Val += 2;}
	if (input[i] & 4){base64Val += 4;}
	if (input[i] & 8){base64Val += 8;}
	if (input[i] & 16){base64Val += 16;}
	if (input[i] & 32){base64Val += 32;}
	output[outputPos++] = index64[base64Val];

	++i;//process next i char
	size -= 3;//3 from length since 24 bits (3 chars) are processed at once
}

output[outputPos] = '\0';
return output;
}