mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
gpg: Reflow long texts.
* common/stringhelp.c (format_text): New function. * common/t-stringhelp.c (stresc): New function. (test_format_text): New function. Test format_text. * g10/tofu.c (get_trust): Use format_text to reflow long texts. (show_statistics): Likewise. -- Signed-off-by: Neal H. Walfield <neal@g10code.com>
This commit is contained in:
parent
5b84b0d660
commit
19362a8dd7
@ -1327,3 +1327,132 @@ strtokenize (const char *string, const char *delim)
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
format_text (char *text, int in_place, int target_cols, int max_cols)
|
||||||
|
{
|
||||||
|
const int do_debug = 0;
|
||||||
|
|
||||||
|
/* The character under consideration. */
|
||||||
|
char *p;
|
||||||
|
/* The start of the current line. */
|
||||||
|
char *line;
|
||||||
|
/* The last space that we saw. */
|
||||||
|
char *last_space = NULL;
|
||||||
|
int last_space_cols = 0;
|
||||||
|
int copied_last_space = 0;
|
||||||
|
|
||||||
|
if (! in_place)
|
||||||
|
text = xstrdup (text);
|
||||||
|
|
||||||
|
p = line = text;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
/* The number of columns including any trailing space. */
|
||||||
|
int cols;
|
||||||
|
|
||||||
|
p = p + strcspn (p, "\n ");
|
||||||
|
if (! p)
|
||||||
|
/* P now points to the NUL character. */
|
||||||
|
p = &text[strlen (text)];
|
||||||
|
|
||||||
|
if (*p == '\n')
|
||||||
|
/* Pass through any newlines. */
|
||||||
|
{
|
||||||
|
p ++;
|
||||||
|
line = p;
|
||||||
|
last_space = NULL;
|
||||||
|
last_space_cols = 0;
|
||||||
|
copied_last_space = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Have a space or a NUL. Note: we don't count the trailing
|
||||||
|
space. */
|
||||||
|
cols = utf8_charcount (line, (uintptr_t) p - (uintptr_t) line);
|
||||||
|
if (cols < target_cols)
|
||||||
|
{
|
||||||
|
if (! *p)
|
||||||
|
/* Nothing left to break. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
last_space = p;
|
||||||
|
last_space_cols = cols;
|
||||||
|
p ++;
|
||||||
|
/* Skip any immediately following spaces. If we break:
|
||||||
|
"... foo bar ..." between "foo" and "bar" then we want:
|
||||||
|
"... foo\nbar ...", which means that the left space has
|
||||||
|
to be the first space after foo, not the last space
|
||||||
|
before bar. */
|
||||||
|
while (*p == ' ')
|
||||||
|
p ++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int cols_with_left_space;
|
||||||
|
int cols_with_right_space;
|
||||||
|
int left_penalty;
|
||||||
|
int right_penalty;
|
||||||
|
|
||||||
|
cols_with_left_space = last_space_cols;
|
||||||
|
cols_with_right_space = cols;
|
||||||
|
|
||||||
|
if (do_debug)
|
||||||
|
log_debug ("Breaking: '%.*s'\n",
|
||||||
|
(int) ((uintptr_t) p - (uintptr_t) line), line);
|
||||||
|
|
||||||
|
/* The number of columns away from TARGET_COLS. We prefer
|
||||||
|
to underflow than to overflow. */
|
||||||
|
left_penalty = target_cols - cols_with_left_space;
|
||||||
|
right_penalty = 2 * (cols_with_right_space - target_cols);
|
||||||
|
|
||||||
|
if (cols_with_right_space > max_cols)
|
||||||
|
/* Add a large penalty for each column that exceeds
|
||||||
|
max_cols. */
|
||||||
|
right_penalty += 4 * (cols_with_right_space - max_cols);
|
||||||
|
|
||||||
|
if (do_debug)
|
||||||
|
log_debug ("Left space => %d cols (penalty: %d); right space => %d cols (penalty: %d)\n",
|
||||||
|
cols_with_left_space, left_penalty,
|
||||||
|
cols_with_right_space, right_penalty);
|
||||||
|
if (last_space_cols && left_penalty <= right_penalty)
|
||||||
|
/* Prefer the left space. */
|
||||||
|
{
|
||||||
|
if (do_debug)
|
||||||
|
log_debug ("Breaking at left space.\n");
|
||||||
|
p = last_space;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (do_debug)
|
||||||
|
log_debug ("Breaking at right space.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! *p)
|
||||||
|
break;
|
||||||
|
|
||||||
|
*p = '\n';
|
||||||
|
p ++;
|
||||||
|
if (*p == ' ')
|
||||||
|
{
|
||||||
|
int spaces;
|
||||||
|
for (spaces = 1; p[spaces] == ' '; spaces ++)
|
||||||
|
;
|
||||||
|
memmove (p, &p[spaces], strlen (&p[spaces]) + 1);
|
||||||
|
}
|
||||||
|
line = p;
|
||||||
|
last_space = NULL;
|
||||||
|
last_space_cols = 0;
|
||||||
|
copied_last_space = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Chop off any trailing space. */
|
||||||
|
while (text[strlen (text) - 1] == ' ')
|
||||||
|
text[strlen (text) - 1] = '\0';
|
||||||
|
/* If we inserted the trailing newline, then remove it. */
|
||||||
|
if (! copied_last_space && text[strlen (text) - 1] == '\n')
|
||||||
|
text[strlen (text) - 1] = '\0';
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
@ -148,6 +148,11 @@ char **strsplit (char *string, char delim, char replacement, int *count);
|
|||||||
/* Tokenize STRING using the set of delimiters in DELIM. */
|
/* Tokenize STRING using the set of delimiters in DELIM. */
|
||||||
char **strtokenize (const char *string, const char *delim);
|
char **strtokenize (const char *string, const char *delim);
|
||||||
|
|
||||||
|
/* Format a string so that it fits within about TARGET_COLS columns.
|
||||||
|
If IN_PLACE is 0, then TEXT is copied to a new buffer, which is
|
||||||
|
returned. Otherwise, TEXT is modified in place and returned.
|
||||||
|
Normally, target_cols will be 72 and max_cols is 80. */
|
||||||
|
char *format_text (char *text, int in_place, int target_cols, int max_cols);
|
||||||
|
|
||||||
/*-- mapstrings.c --*/
|
/*-- mapstrings.c --*/
|
||||||
const char *map_static_macro_string (const char *string);
|
const char *map_static_macro_string (const char *string);
|
||||||
|
@ -677,6 +677,142 @@ test_strtokenize (void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
stresc (char *s)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
int l = strlen (s) + 1;
|
||||||
|
|
||||||
|
for (p = s; *p; p ++)
|
||||||
|
if (*p == '\n')
|
||||||
|
l ++;
|
||||||
|
|
||||||
|
p = xmalloc (l);
|
||||||
|
for (l = 0; *s; s ++, l ++)
|
||||||
|
{
|
||||||
|
if (*s == ' ')
|
||||||
|
p[l] = '_';
|
||||||
|
else if (*p == '\n')
|
||||||
|
{
|
||||||
|
p[l ++] = '\\';
|
||||||
|
p[l ++] = 'n';
|
||||||
|
p[l] = '\n';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p[l] = *s;
|
||||||
|
}
|
||||||
|
p[l] = *s;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_format_text (void)
|
||||||
|
{
|
||||||
|
struct test
|
||||||
|
{
|
||||||
|
int target_cols, max_cols;
|
||||||
|
char *input;
|
||||||
|
char *expected;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct test tests[] = {
|
||||||
|
{
|
||||||
|
10, 12,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
10, 12,
|
||||||
|
" ",
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
10, 12,
|
||||||
|
" ",
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
10, 12,
|
||||||
|
" \n ",
|
||||||
|
" \n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
10, 12,
|
||||||
|
" \n \n ",
|
||||||
|
" \n \n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
10, 12,
|
||||||
|
"0123456789 0123456789 0",
|
||||||
|
"0123456789\n0123456789\n0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
10, 12,
|
||||||
|
" 0123456789 0123456789 0 ",
|
||||||
|
" 0123456789\n0123456789\n0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
10, 12,
|
||||||
|
"01 34 67 90 23 56 89 12 45 67 89 1",
|
||||||
|
"01 34 67\n90 23 56\n89 12 45\n67 89 1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
10, 12,
|
||||||
|
"01 34 67 90 23 56 89 12 45 67 89 1",
|
||||||
|
"01 34 67\n90 23 56\n89 12 45\n67 89 1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
72, 80,
|
||||||
|
"Warning: if you think you've seen more than 10 messages "
|
||||||
|
"signed by this key, then this key might be a forgery! "
|
||||||
|
"Carefully examine the email address for small variations "
|
||||||
|
"(e.g., additional white space). If the key is suspect, "
|
||||||
|
"then use 'gpg --tofu-policy bad \"FINGERPRINT\"' to mark it as being bad.\n",
|
||||||
|
"Warning: if you think you've seen more than 10 messages signed by this\n"
|
||||||
|
"key, then this key might be a forgery! Carefully examine the email\n"
|
||||||
|
"address for small variations (e.g., additional white space). If the key\n"
|
||||||
|
"is suspect, then use 'gpg --tofu-policy bad \"FINGERPRINT\"' to mark it as\n"
|
||||||
|
"being bad.\n"
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
72, 80,
|
||||||
|
"Normally, there is only a single key associated with an email "
|
||||||
|
"address. However, people sometimes generate a new key if "
|
||||||
|
"their key is too old or they think it might be compromised. "
|
||||||
|
"Alternatively, a new key may indicate a man-in-the-middle "
|
||||||
|
"attack! Before accepting this key, you should talk to or "
|
||||||
|
"call the person to make sure this new key is legitimate.",
|
||||||
|
"Normally, there is only a single key associated with an email "
|
||||||
|
"address.\nHowever, people sometimes generate a new key if "
|
||||||
|
"their key is too old or\nthey think it might be compromised. "
|
||||||
|
"Alternatively, a new key may indicate\na man-in-the-middle "
|
||||||
|
"attack! Before accepting this key, you should talk\nto or "
|
||||||
|
"call the person to make sure this new key is legitimate.",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int failed = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof (tests) / sizeof (tests[0]); i ++)
|
||||||
|
{
|
||||||
|
struct test *test = &tests[i];
|
||||||
|
char *result =
|
||||||
|
format_text (test->input, 0, test->target_cols, test->max_cols);
|
||||||
|
if (strcmp (result, test->expected) != 0)
|
||||||
|
{
|
||||||
|
printf ("%s: Test #%d failed.\nExpected: '%s'\nResult: '%s'\n",
|
||||||
|
__func__, i + 1, stresc (test->expected), stresc (result));
|
||||||
|
failed ++;
|
||||||
|
}
|
||||||
|
xfree (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failed)
|
||||||
|
fail(0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
@ -692,6 +828,7 @@ main (int argc, char **argv)
|
|||||||
test_make_absfilename_try ();
|
test_make_absfilename_try ();
|
||||||
test_strsplit ();
|
test_strsplit ();
|
||||||
test_strtokenize ();
|
test_strtokenize ();
|
||||||
|
test_format_text ();
|
||||||
|
|
||||||
xfree (home_buffer);
|
xfree (home_buffer);
|
||||||
return 0;
|
return 0;
|
||||||
|
12
g10/tofu.c
12
g10/tofu.c
@ -2038,7 +2038,9 @@ get_trust (struct dbs *dbs, const char *fingerprint, const char *email,
|
|||||||
"Alternatively, a new key may indicate a man-in-the-middle "
|
"Alternatively, a new key may indicate a man-in-the-middle "
|
||||||
"attack! Before accepting this key, you should talk to or "
|
"attack! Before accepting this key, you should talk to or "
|
||||||
"call the person to make sure this new key is legitimate.";
|
"call the person to make sure this new key is legitimate.";
|
||||||
|
text = format_text (text, 0, 72, 80);
|
||||||
es_fprintf (fp, "\n%s\n", text);
|
es_fprintf (fp, "\n%s\n", text);
|
||||||
|
xfree (text);
|
||||||
}
|
}
|
||||||
|
|
||||||
es_fputc ('\n', fp);
|
es_fputc ('\n', fp);
|
||||||
@ -2440,7 +2442,8 @@ show_statistics (struct dbs *dbs, const char *fingerprint,
|
|||||||
if (policy == TOFU_POLICY_AUTO && messages < 10)
|
if (policy == TOFU_POLICY_AUTO && messages < 10)
|
||||||
{
|
{
|
||||||
char *set_policy_command;
|
char *set_policy_command;
|
||||||
const char *text;
|
char *text;
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
if (messages == 0)
|
if (messages == 0)
|
||||||
log_info (_("Warning: we've have yet to see"
|
log_info (_("Warning: we've have yet to see"
|
||||||
@ -2462,9 +2465,14 @@ show_statistics (struct dbs *dbs, const char *fingerprint,
|
|||||||
"Carefully examine the email address for small variations "
|
"Carefully examine the email address for small variations "
|
||||||
"(e.g., additional white space). If the key is suspect, "
|
"(e.g., additional white space). If the key is suspect, "
|
||||||
"then use '%s' to mark it as being bad.\n";
|
"then use '%s' to mark it as being bad.\n";
|
||||||
log_info (text,
|
tmp = xasprintf
|
||||||
|
(text,
|
||||||
messages, messages == 1 ? _("message") : _("message"),
|
messages, messages == 1 ? _("message") : _("message"),
|
||||||
set_policy_command);
|
set_policy_command);
|
||||||
|
text = format_text (tmp, 0, 72, 80);
|
||||||
|
xfree (tmp);
|
||||||
|
log_info ("%s", text);
|
||||||
|
xfree (text);
|
||||||
free (set_policy_command);
|
free (set_policy_command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user