comparison xwd-application.c @ 20:683ebd334b21

Try to decode octal and "Meta-ASCII" escapes
author Guido Berhoerster <guido+xwrited@berhoerster.name>
date Sat, 30 Jun 2018 22:07:46 +0200
parents f0accfc74f7b
children
comparison
equal deleted inserted replaced
19:f0accfc74f7b 20:683ebd334b21
91 91
92 return (dest); 92 return (dest);
93 } 93 }
94 94
95 static void 95 static void
96 string_decode_octal(GString *string)
97 {
98 GString *result;
99 gsize remaining = string->len;
100 gchar *p = string->str;
101 gchar oct[4] = { '\0' };
102 guint64 num;
103 char *end;
104
105 result = g_string_sized_new(string->len);
106
107 while (remaining > 0) {
108 if ((remaining >= 4) && (*p == '\\')) {
109 /* put octal number in NUL-terminated buffer */
110 memcpy(oct, p + 1, 3);
111 /* convert valid octal number to byte */
112 num = g_ascii_strtoull(oct, &end, 8);
113 if ((*end == '\0') && (num <= 0xff)) {
114 /* conversion succeeded */
115 p += 4;
116 remaining -= 4;
117 g_string_append_c(result, num);
118 continue;
119 }
120 }
121
122 g_string_append_c(result, *p++);
123 remaining--;
124 }
125
126 string_copy(string, result);
127 g_string_free(result, TRUE);
128 }
129
130 static void
131 string_decode_meta_ascii(GString *string)
132 {
133 GString *result;
134 gchar *p = string->str;
135 gsize remaining = string->len;
136
137 result = g_string_sized_new(string->len);
138
139 while (remaining > 0) {
140 if ((remaining >= 3) && (*p == 'M') && (*(p + 1) == '-') &&
141 ((*(p + 2) & (1 << 7)) == 0)) {
142 /* restore 8th bit */
143 g_string_append_c(result, *(p + 2) | (1 << 7));
144 remaining -= 3;
145 p += 3;
146 continue;
147 }
148
149 g_string_append_c(result, *p++);
150 remaining--;
151 }
152
153 string_copy(string, result);
154 g_string_free(result, TRUE);
155 }
156
157 static void
96 string_to_valid_utf8(GString *string) 158 string_to_valid_utf8(GString *string)
97 { 159 {
98 GString *result; 160 GString *result;
99 gchar *start = string->str; 161 gchar *start = string->str;
100 gchar *end; 162 gchar *end;
241 * should be the most common case on modern systems. Any invalid 303 * should be the most common case on modern systems. Any invalid
242 * sequences are replaced with the Unicode "REPLACEMENT CHARACTER" 304 * sequences are replaced with the Unicode "REPLACEMENT CHARACTER"
243 * (U+FFFD) and non-printable characters are removed. Additionally, 305 * (U+FFFD) and non-printable characters are removed. Additionally,
244 * padding typically added by wall(1) implementations is removed in 306 * padding typically added by wall(1) implementations is removed in
245 * order to improve readability. 307 * order to improve readability.
308 * Some write(1) and wall(1) implementations encode non-ASCII
309 * characters, in particular UTF-8 sequences, by prefixing them with
310 * "M-" and clearing the 8th bit while others (e.g. util-linux) use
311 * octal escape sequences. These encodings are reversed before messages
312 * are processed further. However some implementations such as NetBSD
313 * write(1) uncoditionally process each byte with toascii(3) which
314 * makes it impossible to restore the original value.
246 */ 315 */
247 message = g_string_new_len(self->message_buf->str, 316 message = g_string_new_len(self->message_buf->str,
248 self->message_buf->len); 317 self->message_buf->len);
318 string_decode_octal(message);
319 string_decode_meta_ascii(message);
249 string_to_valid_utf8(message); 320 string_to_valid_utf8(message);
250 string_filter_nonprintable(message); 321 string_filter_nonprintable(message);
251 string_trim_lines(message); 322 string_trim_lines(message);
252 323
253 if (enable_debug_logging) { 324 if (enable_debug_logging) {