buffer_t *buf;
uint8_t *guid_p;
const unsigned char *data;
- size_t pos;
unsigned int i, count;
buf = t_buffer_create(strlen(input));
- if (base64_decode(input, strlen(input), &pos, buf) < 0) {
+ if (base64_decode(input, strlen(input), NULL, buf) < 0) {
*error_r = "Invalid base64 data";
return -1;
}
buffer_t **extra_buf_r)
{
struct attachment_istream_part *part = &astream->part;
+ struct base64_decoder b64dec;
struct istream *input, *base64_input;
struct ostream *output;
const unsigned char *data;
output = o_stream_create_fd_file(outfd, 0, FALSE);
o_stream_cork(output);
+ base64_decode_init(&b64dec, &base64_scheme, 0);
hash_format_reset(astream->set.hash_format);
size_t bytes_needed = 1;
while ((ret = i_stream_read_bytes(base64_input, &data, &size,
bytes_needed)) > 0) {
buffer_set_used_size(buf, 0);
- if (base64_decode(data, size, &size, buf) < 0) {
+ if (base64_decode_more(&b64dec, data, size, &size, buf) < 0) {
i_error("istream-attachment: BUG: "
"Attachment base64 data unexpectedly broke");
failed = TRUE;
i_stream_get_error(base64_input));
failed = TRUE;
}
+ if (base64_decode_finish(&b64dec) < 0) {
+ i_error("istream-attachment: BUG: "
+ "Attachment base64 data unexpectedly broke");
+ failed = TRUE;
+ }
if (o_stream_finish(output) < 0) {
i_error("istream-attachment: write(%s) failed: %s",
o_stream_get_name(output), o_stream_get_error(output));
struct message_block *input,
struct message_block *output)
{
+ struct base64_decoder b64dec;
const unsigned char *data = NULL;
size_t pos = 0, size = 0;
const char *error;
}
case MESSAGE_CTE_BASE64:
buffer_set_used_size(ctx->buf, 0);
+ base64_decode_init(&b64dec, &base64_scheme, 0);
if (ctx->encoding_buf->used != 0) {
- ret = base64_decode(ctx->encoding_buf->data,
- ctx->encoding_buf->used,
- &pos, ctx->buf);
+ ret = base64_decode_more(&b64dec,
+ ctx->encoding_buf->data,
+ ctx->encoding_buf->used,
+ &pos, ctx->buf);
} else {
- ret = base64_decode(input->data, input->size,
- &pos, ctx->buf);
+ ret = base64_decode_more(&b64dec,
+ input->data, input->size,
+ &pos, ctx->buf);
}
- if (ret < 0) {
+ if (ret < 0 || base64_decode_finish(&b64dec) < 0) {
/* corrupted base64 data, don't bother with
the rest of it */
return FALSE;
*/
int base64_scheme_decode(const struct base64_scheme *b64,
- const void *src, size_t src_size, size_t *src_pos_r,
- buffer_t *dest)
+ const void *src, size_t src_size, buffer_t *dest)
{
- const unsigned char *b64dec = b64->decmap;
- const unsigned char *src_c = src;
- size_t src_pos;
- unsigned char input[4], output[3];
- int ret = 1;
-
- for (src_pos = 0; src_pos+3 < src_size; ) {
- input[0] = b64dec[src_c[src_pos]];
- if (input[0] == 0xff) {
- if (unlikely(!IS_EMPTY(src_c[src_pos]))) {
- ret = -1;
- break;
- }
- src_pos++;
- continue;
- }
-
- input[1] = b64dec[src_c[src_pos+1]];
- if (unlikely(input[1] == 0xff)) {
- ret = -1;
- break;
- }
- output[0] = (input[0] << 2) | (input[1] >> 4);
+ struct base64_decoder dec;
+ int ret;
- input[2] = b64dec[src_c[src_pos+2]];
- if (input[2] == 0xff) {
- if (unlikely(src_c[src_pos+2] != '=' ||
- src_c[src_pos+3] != '=')) {
- ret = -1;
- break;
- }
- buffer_append(dest, output, 1);
- ret = 0;
- src_pos += 4;
- break;
- }
-
- output[1] = (input[1] << 4) | (input[2] >> 2);
- input[3] = b64dec[src_c[src_pos+3]];
- if (input[3] == 0xff) {
- if (unlikely(src_c[src_pos+3] != '=')) {
- ret = -1;
- break;
- }
- buffer_append(dest, output, 2);
- ret = 0;
- src_pos += 4;
- break;
- }
-
- output[2] = ((input[2] << 6) & 0xc0) | input[3];
- buffer_append(dest, output, 3);
- src_pos += 4;
- }
-
- for (; src_pos < src_size; src_pos++) {
- if (!IS_EMPTY(src_c[src_pos]))
- break;
- }
-
- if (src_pos_r != NULL)
- *src_pos_r = src_pos;
+ base64_decode_init(&dec, b64, 0);
+ ret = base64_decode_more(&dec, src, src_size, NULL, dest);
+ if (ret >= 0)
+ ret = base64_decode_finish(&dec);
return ret;
}
size_t len = strlen(str);
buf = t_buffer_create(MAX_BASE64_DECODED_SIZE(len));
- (void)base64_scheme_decode(b64, str, len, NULL, buf);
+ (void)base64_scheme_decode(b64, str, len, buf);
return buf;
}
Any CR, LF characters are ignored, as well as whitespace at beginning or
end of line.
-
- This function may be called multiple times for parsing the same stream.
- If src_pos is non-NULL, it's updated to first non-translated character in
- src. */
+ */
int base64_scheme_decode(const struct base64_scheme *b64,
- const void *src, size_t src_size, size_t *src_pos_r,
- buffer_t *dest) ATTR_NULL(4);
+ const void *src, size_t src_size, buffer_t *dest);
/* Decode given string to a buffer allocated from data stack.
}
/* Translates base64 data into binary and appends it to dest buffer. See
- base64_scheme_decode(). */
+ base64_scheme_decode().
+
+ The src_pos_r parameter is deprecated and MUST be NULL.
+ */
static inline int
-base64_decode(const void *src, size_t src_size, size_t *src_pos_r,
+base64_decode(const void *src, size_t src_size, size_t *src_pos_r ATTR_UNUSED,
buffer_t *dest) ATTR_NULL(3)
{
- return base64_scheme_decode(&base64_scheme, src, src_size,
- src_pos_r, dest);
+ // NOTE: src_pos_r is deprecated here; to be removed in v2.4 */
+ i_assert(src_pos_r == NULL);
+
+ return base64_scheme_decode(&base64_scheme, src, src_size, dest);
}
/* Decode given string to a buffer allocated from data stack. */
/* Translates base64url data into binary and appends it to dest buffer. See
base64_scheme_decode(). */
static inline int
-base64url_decode(const void *src, size_t src_size, size_t *src_pos_r,
- buffer_t *dest) ATTR_NULL(3)
+base64url_decode(const void *src, size_t src_size, buffer_t *dest)
{
- return base64_scheme_decode(&base64url_scheme, src, src_size,
- src_pos_r, dest);
+ return base64_scheme_decode(&base64url_scheme, src, src_size, dest);
}
/* Decode given string to a buffer allocated from data stack. */
const char *input;
const char *output;
int ret;
- unsigned int src_pos;
};
static void test_base64_decode(void)
{
static const struct test_base64_decode tests[] = {
{ "\taGVsbG8gd29ybGQ=",
- "hello world", 0, UINT_MAX },
+ "hello world", 0 },
{ "\nZm9v\n \tIGJh \t\ncml0cw==",
- "foo barits", 0, UINT_MAX },
+ "foo barits", 0 },
{ " anVzdCBuaWlu \n",
- "just niin", 1, UINT_MAX },
+ "just niin", 0 },
{ "aGVsb",
- "hel", 1, 4 },
+ "hel", -1 },
{ "aGVsb!!!!!",
- "hel", -1, 4 },
+ "hel", -1 },
{ "aGVs!!!!!",
- "hel", -1, 4 },
+ "hel", -1 },
{ "0JPQvtCy0L7RgNGPzIHRgiwg0YfRgt"
"C+INC60YPRgCDQtNC+0Y/MgdGCLg==",
"\xd0\x93\xd0\xbe\xd0\xb2\xd0\xbe\xd1\x80\xd1\x8f\xcc"
"\x81\xd1\x82\x2c\x20\xd1\x87\xd1\x82\xd0\xbe\x20\xd0"
"\xba\xd1\x83\xd1\x80\x20\xd0\xb4\xd0\xbe\xd1\x8f\xcc"
- "\x81\xd1\x82\x2e", 0, UINT_MAX },
+ "\x81\xd1\x82\x2e", 0 },
};
string_t *str;
buffer_t buf;
unsigned int i;
- size_t src_pos;
int ret;
test_begin("base64_decode()");
buffer_create_from_data(&buf, t_malloc0(max_decoded_size),
max_decoded_size);
str = &buf;
- src_pos = 0;
ret = base64_decode(tests[i].input, strlen(tests[i].input),
- &src_pos, str);
+ NULL, str);
test_assert_idx(tests[i].ret == ret, i);
test_assert_idx(strlen(tests[i].output) == str_len(str) &&
memcmp(tests[i].output, str_data(str),
str_len(str)) == 0, i);
- test_assert_idx(src_pos == tests[i].src_pos ||
- (tests[i].src_pos == UINT_MAX &&
- src_pos == strlen(tests[i].input)), i);
if (ret >= 0) {
test_assert_idx(
str_len(str) <= MAX_BASE64_DECODED_SIZE(
const char *input;
const char *output;
int ret;
- unsigned int src_pos;
};
static void test_base64url_decode(void)
{
static const struct test_base64url_decode tests[] = {
{ "\taGVsbG8gd29ybGQ=",
- "hello world", 0, UINT_MAX },
+ "hello world", 0 },
{ "\nZm9v\n \tIGJh \t\ncml0cw==",
- "foo barits", 0, UINT_MAX },
+ "foo barits", 0 },
{ " anVzdCBuaWlu \n",
- "just niin", 1, UINT_MAX },
+ "just niin", 0 },
{ "aGVsb",
- "hel", 1, 4 },
+ "hel", -1 },
{ "aGVsb!!!!!",
- "hel", -1, 4 },
+ "hel", -1 },
{ "aGVs!!!!!",
- "hel", -1, 4 },
+ "hel", -1 },
{ "0JPQvtCy0L7RgNGPzIHRgiwg0YfRgt"
"C-INC60YPRgCDQtNC-0Y_MgdGCLg==",
"\xd0\x93\xd0\xbe\xd0\xb2\xd0\xbe\xd1\x80\xd1\x8f\xcc"
"\x81\xd1\x82\x2c\x20\xd1\x87\xd1\x82\xd0\xbe\x20\xd0"
"\xba\xd1\x83\xd1\x80\x20\xd0\xb4\xd0\xbe\xd1\x8f\xcc"
- "\x81\xd1\x82\x2e", 0, UINT_MAX },
+ "\x81\xd1\x82\x2e", 0 },
};
string_t *str;
buffer_t buf;
unsigned int i;
- size_t src_pos;
int ret;
test_begin("base64url_decode()");
buffer_create_from_data(&buf, t_malloc0(max_decoded_size),
max_decoded_size);
str = &buf;
- src_pos = 0;
ret = base64url_decode(tests[i].input, strlen(tests[i].input),
- &src_pos, str);
+ str);
test_assert_idx(tests[i].ret == ret, i);
test_assert_idx(strlen(tests[i].output) == str_len(str) &&
memcmp(tests[i].output, str_data(str),
str_len(str)) == 0, i);
- test_assert_idx(src_pos == tests[i].src_pos ||
- (tests[i].src_pos == UINT_MAX &&
- src_pos == strlen(tests[i].input)), i);
if (ret >= 0) {
test_assert_idx(
str_len(str) <= MAX_BASE64_DECODED_SIZE(
str_truncate(dest, 0);
base64url_encode(buf, max, str);
test_assert_idx(base64url_decode(str_data(str), str_len(str),
- NULL, dest) >= 0, i);
+ dest) >= 0, i);
test_assert_idx(str_len(dest) == max &&
memcmp(buf, str_data(dest), max) == 0, i);
}