On Mon, Jul 6, 2015 at 12:05 PM, Christian Hesse <list@xxxxxxxx> wrote: > From: Christian Hesse <mail@xxxxxxxx> > > Signed-off-by: Christian Hesse <mail@xxxxxxxx> > --- > 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@xxxxxxxxxxx \__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer /O /==\ O\ TEL +49 641 3992797 (;O/ \/ \O;) _______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev