[PATCH 1/1] paint visual host key with unicode box-drawing characters
Roland Mainz
roland.mainz at nrubsig.org
Wed Jul 8 00:25:25 AEST 2015
On Mon, Jul 6, 2015 at 12:05 PM, Christian Hesse <list at eworm.de> wrote:
> From: Christian Hesse <mail at eworm.de>
>
> Signed-off-by: Christian Hesse <mail at eworm.de>
> ---
> sshkey.c | 47 ++++++++++++++++++++++++++++++++++++-----------
> 1 file changed, 36 insertions(+), 11 deletions(-)
>
> diff --git a/sshkey.c b/sshkey.c
> index cfe5980..47511c2 100644
> --- a/sshkey.c
> +++ b/sshkey.c
> @@ -44,6 +44,9 @@
> #include <stdio.h>
> #include <string.h>
> #include <resolv.h>
> +#ifdef HAVE_LOCALE_H
> +#include <locale.h>
> +#endif /* HAVE_LOCALE_H */
> #ifdef HAVE_UTIL_H
> #include <util.h>
> #endif /* HAVE_UTIL_H */
> @@ -1088,6 +1091,12 @@ fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
> * Chars to be used after each other every time the worm
> * intersects with itself. Matter of taste.
> */
> +#ifdef HAVE_LOCALE_H
> + char *locale;
> + char *border_utf8[] = { "┏", "━", "┓", "┃", "┗", "┛" };
> +#endif
> + char *border_ascii[] = { "+", "-", "+", "|", "+", "+" };
> + char **border;
> char *augmentation_string = " .o+=*BOX@%&#/^SE";
> char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X];
> u_char field[FLDSIZE_X][FLDSIZE_Y];
> @@ -1096,9 +1105,25 @@ fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
> int x, y, r;
> size_t len = strlen(augmentation_string) - 1;
>
> - if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL)
> + if ((retval = malloc((FLDSIZE_X + 7) * FLDSIZE_Y + FLDSIZE_X * 3 * 2)) == NULL)
> return NULL;
>
> +#ifdef HAVE_LOCALE_H
> + /* initialize locale */
> + setlocale(LC_ALL, "");
> +
> + /* get locale for LC_CTYPE and decide about characters to use */
> + locale = setlocale(LC_CTYPE, NULL);
> + if (locale != NULL && *locale != 0 &&
> + (strstr(locale, "UTF-8") ||
> + strstr(locale, "utf-8") ||
> + strstr(locale, "UTF8") ||
> + strstr(locale, "utf8")))
> + border = border_utf8;
> + else
> +#endif
> + border = border_ascii;
> +
> /* initialize field */
> memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
> x = FLDSIZE_X / 2;
> @@ -1145,34 +1170,34 @@ fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len,
>
> /* output upper border */
> p = retval;
> - *p++ = '+';
> + p += sprintf(p, "%s", border[0]);
> for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++)
> - *p++ = '-';
> + p += sprintf(p, "%s", border[1]);
> memcpy(p, title, tlen);
> p += tlen;
> for (i += tlen; i < FLDSIZE_X; i++)
> - *p++ = '-';
> - *p++ = '+';
> + p += sprintf(p, "%s", border[1]);
> + p += sprintf(p, "%s", border[2]);
> *p++ = '\n';
>
> /* output content */
> for (y = 0; y < FLDSIZE_Y; y++) {
> - *p++ = '|';
> + p += sprintf(p, "%s", border[3]);
> for (x = 0; x < FLDSIZE_X; x++)
> *p++ = augmentation_string[MIN(field[x][y], len)];
> - *p++ = '|';
> + p += sprintf(p, "%s", border[3]);
> *p++ = '\n';
> }
>
> /* output lower border */
> - *p++ = '+';
> + p += sprintf(p, "%s", border[4]);
> for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++)
> - *p++ = '-';
> + p += sprintf(p, "%s", border[1]);
> memcpy(p, hash, hlen);
> p += hlen;
> for (i += hlen; i < FLDSIZE_X; i++)
> - *p++ = '-';
> - *p++ = '+';
> + p += sprintf(p, "%s", border[1]);
> + p += sprintf(p, "%s", border[5]);
>
> return retval;
> }
General comments:
1. Not all locales use UTF-8 as encoding but can still use the Unicode
characters you use (e.g. GB18030 is a modern example and it's use is
mandated by all software vendors in PRC China). A quick solution is to
use |iconv()| to convert the UTF-8 byte sequences to the local
encoding (see http://svn.nrubsig.org/svn/people/gisburn/code/ucs4towchar_t/ucs4towchar_t.c
- that could should be easy to modify). Note that if |iconf()|
produces an empty string in a character-by-character conversion it
means that the destination locale cannot represent that character in
the local encoding (you have to fall-back to the ASCII representation
then (this will also eliminate the need for the |setlocale()|&&co.
testing)).
2. UTF-8 sequences in ISO C code are not portable and a lot of
compilers will choke on that (e.g. if they are in a non-UTF-8 locale
like "C", "POSIX" or any non-UTF-8 multibyte locale). Correct fix
would be to provide the UTF-8 byte sequences for the characters as
plain C strings escaped in octal or hexadecimal notation (and then
squish them through |iconf()|)
3. Not all UTF-8 locales (or locale aliases) have "UTF-8" in their
name (for example the name "en_US" is allowed to be an alias for
"en_US.UTF-8" (this quickly becomes messy in the Chinese/Japanese
environments, e.g. where "ja_JP" can be anything from ja_JP.PCK to
ja_JP.UTF-8))
----
Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
More information about the openssh-unix-dev
mailing list