Skip to content

Commit

Permalink
set line length for armored output #1099
Browse files Browse the repository at this point in the history
  • Loading branch information
rrrooommmaaa committed Jun 25, 2020
1 parent 9fcf17a commit a93481f
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 1 deletion.
8 changes: 8 additions & 0 deletions include/rnp/rnp.h
Original file line number Diff line number Diff line change
Expand Up @@ -2277,6 +2277,14 @@ rnp_result_t rnp_identifier_iterator_destroy(rnp_identifier_iterator_t it);
*/
rnp_result_t rnp_output_pipe(rnp_input_t input, rnp_output_t output);

/** Set line length for armored output
*
* @param output stream to configure
* @param llen line length in characters
* @return RNP_SUCCESS on success, or any other value on error
*/
rnp_result_t rnp_output_armor_set_line_length(rnp_output_t output, size_t llen);

#if defined(__cplusplus)
}

Expand Down
9 changes: 9 additions & 0 deletions src/lib/rnp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7173,3 +7173,12 @@ rnp_output_pipe(rnp_input_t input, rnp_output_t output)
output->keep = !ret;
return ret;
}

rnp_result_t
rnp_output_armor_set_line_length(rnp_output_t output, size_t llen)
{
if (!output || llen <= 0) {
return RNP_ERROR_BAD_PARAMETERS;
}
return armored_dst_set_line_length(&output->dst, llen);
}
17 changes: 17 additions & 0 deletions src/librepgp/stream-armor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,23 @@ init_armored_dst(pgp_dest_t *dst, pgp_dest_t *writedst, pgp_armored_msg_t msgtyp
return ret;
}

static bool
is_armored_dest(pgp_dest_t *dst)
{
return dst->type == PGP_STREAM_ARMORED;
}

rnp_result_t
armored_dst_set_line_length(pgp_dest_t *dst, size_t llen)
{
if (!dst || !dst->param || !is_armored_dest(dst)) {
return RNP_ERROR_BAD_PARAMETERS;
}
auto param = (pgp_dest_armored_param_t *) dst->param;
param->llen = llen;
return RNP_SUCCESS;
}

bool
is_armored_source(pgp_source_t *src)
{
Expand Down
10 changes: 9 additions & 1 deletion src/librepgp/stream-armor.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, [Ribose Inc](https://www.ribose.com).
* Copyright (c) 2017-2020, [Ribose Inc](https://www.ribose.com).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
Expand Down Expand Up @@ -94,4 +94,12 @@ bool is_armored_source(pgp_source_t *src);
**/
bool is_cleartext_source(pgp_source_t *src);

/** Set line length for armoring
*
* @param dst initialized dest to write armored data to
* @param llen line length in characters
* @return RNP_SUCCESS on success, or any other value on error
*/
rnp_result_t armored_dst_set_line_length(pgp_dest_t *dst, size_t llen);

#endif
131 changes: 131 additions & 0 deletions src/tests/ffi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,31 @@ check_key_properties(rnp_key_handle_t key,
assert_true(have_secret == have_secret_expected);
}

static size_t
get_longest_line_length(const std::string &str)
{
const char begin_tag[] = "-----BEGIN PGP MESSAGE-----\r\n";
// const char end_tag[] = "-----END PGP MESSAGE-----\r\n";
// eol could be \n or \r\n
size_t index = strlen(begin_tag);
size_t max_len = 0;
for (;;) {
auto new_index = str.find('\n', index);
if (new_index == std::string::npos) {
break;
}
size_t line_length = new_index - index;
if (str[new_index - 1] == '\r') {
line_length--;
}
if (line_length > max_len) {
max_len = line_length;
}
index = new_index + 1;
}
return max_len;
}

TEST_F(rnp_tests, test_ffi_keygen_json_pair)
{
rnp_ffi_t ffi = NULL;
Expand Down Expand Up @@ -4500,6 +4525,112 @@ TEST_F(rnp_tests, test_ffi_enarmor_dearmor)
}
}

TEST_F(rnp_tests, test_ffi_customized_enarmor)
{
// enarmor message
const std::string msg("this is a test long enough to have more than 76 characters in "
"enarmored representation");
std::string data;

// enarmor with line_length = 64
data.clear();
{
uint8_t * buf = NULL;
size_t buf_size = 0;
rnp_input_t input = NULL;
rnp_output_t output = NULL;
rnp_output_t armor_layer = NULL;

assert_rnp_success(
rnp_input_from_memory(&input, (const uint8_t *) msg.data(), msg.size(), true));
assert_rnp_success(rnp_output_to_memory(&output, 0));
assert_rnp_success(rnp_output_to_armor(output, &armor_layer, "message"));
// should fail when trying to set line length on non-armor output
assert_rnp_failure(rnp_output_armor_set_line_length(output, 64));
// should fail when trying to set zero line length
assert_rnp_failure(rnp_output_armor_set_line_length(armor_layer, 0));
assert_rnp_success(rnp_output_armor_set_line_length(armor_layer, 64));

assert_rnp_success(rnp_output_pipe(input, armor_layer));
assert_rnp_success(rnp_output_finish(armor_layer));

assert_rnp_success(rnp_output_memory_get_buf(output, &buf, &buf_size, false));
data = std::string(buf, buf + buf_size);

assert_int_equal(get_longest_line_length(data), 64);
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_output_destroy(armor_layer));
assert_rnp_success(rnp_output_destroy(output));
}
// test that the dearmored message is correct
{
uint8_t * buf = NULL;
size_t buf_size = 0;
rnp_input_t input = NULL;
rnp_output_t output = NULL;

assert_rnp_success(
rnp_input_from_memory(&input, (const uint8_t *) data.data(), data.size(), true));
assert_rnp_success(rnp_output_to_memory(&output, 0));

assert_rnp_success(rnp_dearmor(input, output));

assert_rnp_success(rnp_output_memory_get_buf(output, &buf, &buf_size, false));
std::string dearmored(buf, buf + buf_size);
assert_true(msg == dearmored);

assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_output_destroy(output));
}

// enarmor with line_length = 72
data.clear();
{
uint8_t * buf = NULL;
size_t buf_size = 0;
rnp_input_t input = NULL;
rnp_output_t output = NULL;
rnp_output_t armor_layer = NULL;

assert_rnp_success(
rnp_input_from_memory(&input, (const uint8_t *) msg.data(), msg.size(), true));
assert_rnp_success(rnp_output_to_memory(&output, 0));
assert_rnp_success(rnp_output_to_armor(output, &armor_layer, "message"));
assert_rnp_success(rnp_output_armor_set_line_length(armor_layer, 72));

assert_rnp_success(rnp_output_pipe(input, armor_layer));
assert_rnp_success(rnp_output_finish(armor_layer));

assert_rnp_success(rnp_output_memory_get_buf(output, &buf, &buf_size, false));
data = std::string(buf, buf + buf_size);

assert_int_equal(get_longest_line_length(data), 72);
assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_output_destroy(armor_layer));
assert_rnp_success(rnp_output_destroy(output));
}
// test that the dearmored message is correct
{
uint8_t * buf = NULL;
size_t buf_size = 0;
rnp_input_t input = NULL;
rnp_output_t output = NULL;

assert_rnp_success(
rnp_input_from_memory(&input, (const uint8_t *) data.data(), data.size(), true));
assert_rnp_success(rnp_output_to_memory(&output, 0));

assert_rnp_success(rnp_dearmor(input, output));

assert_rnp_success(rnp_output_memory_get_buf(output, &buf, &buf_size, false));
std::string dearmored(buf, buf + buf_size);
assert_true(msg == dearmored);

assert_rnp_success(rnp_input_destroy(input));
assert_rnp_success(rnp_output_destroy(output));
}
}

TEST_F(rnp_tests, test_ffi_version)
{
const uint32_t version = rnp_version();
Expand Down
2 changes: 2 additions & 0 deletions src/tests/rnp_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,8 @@ void test_ffi_signatures_detached_memory_g10(void **state);

void test_ffi_enarmor_dearmor(void **state);

void test_ffi_customized_enarmor(void **state);

void test_ffi_version(void **state);

void test_ffi_key_export(void **state);
Expand Down

0 comments on commit a93481f

Please sign in to comment.