projects/xwrited

changeset 20:683ebd334b21

Try to decode octal and "Meta-ASCII" escapes
author Guido Berhoerster <guido+xwrited@berhoerster.name>
date Sat Jun 30 22:07:46 2018 +0200 (23 months ago)
parents f0accfc74f7b
children 0897a8fe27af
files xwd-application.c
line diff
     1.1 --- a/xwd-application.c	Sat Jul 28 22:02:24 2018 +0200
     1.2 +++ b/xwd-application.c	Sat Jun 30 22:07:46 2018 +0200
     1.3 @@ -93,6 +93,68 @@
     1.4  }
     1.5  
     1.6  static void
     1.7 +string_decode_octal(GString *string)
     1.8 +{
     1.9 +	GString	*result;
    1.10 +	gsize	remaining = string->len;
    1.11 +	gchar	*p = string->str;
    1.12 +	gchar	oct[4] = { '\0' };
    1.13 +	guint64	num;
    1.14 +	char	*end;
    1.15 +
    1.16 +	result = g_string_sized_new(string->len);
    1.17 +
    1.18 +	while (remaining > 0) {
    1.19 +		if ((remaining >= 4) && (*p == '\\')) {
    1.20 +			/* put octal number in NUL-terminated buffer */
    1.21 +			memcpy(oct, p + 1, 3);
    1.22 +			/* convert valid octal number to byte */
    1.23 +			num = g_ascii_strtoull(oct, &end, 8);
    1.24 +			if ((*end == '\0') && (num <= 0xff)) {
    1.25 +				/* conversion succeeded */
    1.26 +				p += 4;
    1.27 +				remaining -= 4;
    1.28 +				g_string_append_c(result, num);
    1.29 +				continue;
    1.30 +			}
    1.31 +		}
    1.32 +
    1.33 +		g_string_append_c(result, *p++);
    1.34 +		remaining--;
    1.35 +	}
    1.36 +
    1.37 +	string_copy(string, result);
    1.38 +	g_string_free(result, TRUE);
    1.39 +}
    1.40 +
    1.41 +static void
    1.42 +string_decode_meta_ascii(GString *string)
    1.43 +{
    1.44 +	GString		*result;
    1.45 +	gchar		*p = string->str;
    1.46 +	gsize		remaining = string->len;
    1.47 +
    1.48 +	result = g_string_sized_new(string->len);
    1.49 +
    1.50 +	while (remaining > 0) {
    1.51 +		if ((remaining >= 3) && (*p == 'M') && (*(p + 1) == '-') &&
    1.52 +		    ((*(p + 2) & (1 << 7)) == 0)) {
    1.53 +			/* restore 8th bit */
    1.54 +			g_string_append_c(result, *(p + 2) | (1 << 7));
    1.55 +			remaining -= 3;
    1.56 +			p += 3;
    1.57 +			continue;
    1.58 +		}
    1.59 +
    1.60 +		g_string_append_c(result, *p++);
    1.61 +		remaining--;
    1.62 +	}
    1.63 +
    1.64 +	string_copy(string, result);
    1.65 +	g_string_free(result, TRUE);
    1.66 +}
    1.67 +
    1.68 +static void
    1.69  string_to_valid_utf8(GString *string)
    1.70  {
    1.71  	GString		*result;
    1.72 @@ -243,9 +305,18 @@
    1.73  	 * (U+FFFD) and non-printable characters are removed. Additionally,
    1.74  	 * padding typically added by wall(1) implementations is removed in
    1.75  	 * order to improve readability.
    1.76 +	 * Some write(1) and wall(1) implementations encode non-ASCII
    1.77 +	 * characters, in particular UTF-8 sequences, by prefixing them with
    1.78 +	 * "M-" and clearing the 8th bit while others (e.g. util-linux) use
    1.79 +	 * octal escape sequences. These encodings are reversed before messages
    1.80 +	 * are processed further. However some implementations such as NetBSD
    1.81 +	 * write(1) uncoditionally process each byte with toascii(3) which
    1.82 +	 * makes it impossible to restore the original value.
    1.83  	 */
    1.84  	message = g_string_new_len(self->message_buf->str,
    1.85  	    self->message_buf->len);
    1.86 +	string_decode_octal(message);
    1.87 +	string_decode_meta_ascii(message);
    1.88  	string_to_valid_utf8(message);
    1.89  	string_filter_nonprintable(message);
    1.90  	string_trim_lines(message);