GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/b64.c Lines: 48 83 57.8 %
Date: 2020-12-10 21:44:00 Branches: 30 58 51.7 %

Line Branch Exec Source
1
/**
2
 * `encode.c' - b64
3
 *
4
 * copyright (c) 2014 joseph werle
5
 */
6
7
#include <stdio.h>
8
#include <stdlib.h>
9
#include <ctype.h>
10
#include "b64.h"
11
12
char *
13
b64_encode (const unsigned char *src, size_t len) {
14
    int i = 0;
15
    int j = 0;
16
    char *enc = NULL;
17
    size_t size = 0;
18
    unsigned char buf[4];
19
    unsigned char tmp[3];
20
21
    // alloc
22
    enc = (char *) b64_malloc(1);
23
    if (NULL == enc) { return NULL; }
24
25
    // parse until end of source
26
    while (len--) {
27
        // read up to 3 bytes at a time into `tmp'
28
        tmp[i++] = *(src++);
29
30
        // if 3 bytes read then encode into `buf'
31
        if (3 == i) {
32
            buf[0] = (tmp[0] & 0xfc) >> 2;
33
            buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4);
34
            buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6);
35
            buf[3] = tmp[2] & 0x3f;
36
37
            // allocate 4 new byts for `enc` and
38
            // then translate each encoded buffer
39
            // part by index from the base 64 index table
40
            // into `enc' unsigned char array
41
            enc = (char *) b64_realloc(enc, size + 4);
42
            for (i = 0; i < 4; ++i) {
43
                enc[size++] = b64_table[buf[i]];
44
            }
45
46
            // reset index
47
            i = 0;
48
        }
49
    }
50
51
    // remainder
52
    if (i > 0) {
53
        // fill `tmp' with `\0' at most 3 times
54
        for (j = i; j < 3; ++j) {
55
            tmp[j] = '\0';
56
        }
57
58
        // perform same codec as above
59
        buf[0] = (tmp[0] & 0xfc) >> 2;
60
        buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4);
61
        buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6);
62
        buf[3] = tmp[2] & 0x3f;
63
64
        // perform same write to `enc` with new allocation
65
        for (j = 0; (j < i + 1); ++j) {
66
            enc = (char *) b64_realloc(enc, size + 1);
67
            enc[size++] = b64_table[buf[j]];
68
        }
69
70
        // while there is still a remainder
71
        // append `=' to `enc'
72
        while ((i++ < 3)) {
73
            enc = (char *) b64_realloc(enc, size + 1);
74
            enc[size++] = '=';
75
        }
76
    }
77
78
    // Make sure we have enough space to add '\0' character at end.
79
    enc = (char *) b64_realloc(enc, size + 1);
80
    enc[size] = '\0';
81
82
    return enc;
83
}
84
85
10
unsigned char *b64_decode_ex (const char *src, size_t len, size_t *decsize) {
86
10
    int i = 0;
87
10
    int j = 0;
88
10
    int l = 0;
89
10
    size_t size = 0;
90
10
    unsigned char *dec = NULL;
91
10
    unsigned char buf[3];
92
10
    unsigned char tmp[4];
93
94
    // alloc
95
10
    dec = (unsigned char *) b64_malloc(1);
96
10
    if (NULL == dec) { return NULL; }
97
98
    // parse until end of source
99
192
    while (len--) {
100
        // break if char is `=' or not base64 char
101
190
        if ('=' == src[j]) { break; }
102

182
        if (!(isalnum(src[j]) || '+' == src[j] || '/' == src[j])) { break; }
103
104
        // read up to 4 bytes at a time into `tmp'
105
182
        tmp[i++] = src[j++];
106
107
        // if 4 bytes read then decode into `buf'
108
182
        if (4 == i) {
109
            // translate values in `tmp' from table
110
200
            for (i = 0; i < 4; ++i) {
111
                // find translation char in `b64_table'
112
4352
                for (l = 0; l < 64; ++l) {
113
4352
                    if (tmp[i] == b64_table[l]) {
114
160
                        tmp[i] = l;
115
160
                        break;
116
                    }
117
                }
118
            }
119
120
            // decode
121
40
            buf[0] = (tmp[0] << 2) + ((tmp[1] & 0x30) >> 4);
122
40
            buf[1] = ((tmp[1] & 0xf) << 4) + ((tmp[2] & 0x3c) >> 2);
123
40
            buf[2] = ((tmp[2] & 0x3) << 6) + tmp[3];
124
125
            // write decoded buffer to `dec'
126
40
            dec = (unsigned char *) b64_realloc(dec, size + 3);
127
40
            if (dec != NULL){
128
160
                for (i = 0; i < 3; ++i) {
129
120
                    dec[size++] = buf[i];
130
                }
131
            } else {
132
                return NULL;
133
            }
134
135
            // reset
136
            i = 0;
137
        }
138
    }
139
140
    // remainder
141
10
    if (i > 0) {
142
        // fill `tmp' with `\0' at most 4 times
143
28
        for (j = i; j < 4; ++j) {
144
18
            tmp[j] = '\0';
145
        }
146
147
        // translate remainder
148
50
        for (j = 0; j < 4; ++j) {
149
            // find translation char in `b64_table'
150
1752
            for (l = 0; l < 64; ++l) {
151
1734
                if (tmp[j] == b64_table[l]) {
152
22
                    tmp[j] = l;
153
22
                    break;
154
                }
155
            }
156
        }
157
158
        // decode remainder
159
10
        buf[0] = (tmp[0] << 2) + ((tmp[1] & 0x30) >> 4);
160
10
        buf[1] = ((tmp[1] & 0xf) << 4) + ((tmp[2] & 0x3c) >> 2);
161
10
        buf[2] = ((tmp[2] & 0x3) << 6) + tmp[3];
162
163
        // write remainer decoded buffer to `dec'
164
10
        dec = (unsigned char *) b64_realloc(dec, size + (i - 1));
165
10
        if (dec != NULL){
166
22
            for (j = 0; (j < i - 1); ++j) {
167
12
                dec[size++] = buf[j];
168
            }
169
        } else {
170
            return NULL;
171
        }
172
    }
173
174
    // Make sure we have enough space to add '\0' character at end.
175
10
    dec = (unsigned char *) b64_realloc(dec, size + 1);
176
10
    if (dec != NULL){
177
10
        dec[size] = '\0';
178
    } else {
179
        return NULL;
180
    }
181
182
    // Return back the size of decoded string if demanded.
183
10
    if (decsize != NULL) {
184
10
        *decsize = size;
185
    }
186
187
10
    return dec;
188
}