Mercurial > projects > xwrited
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) { |