@@ -272,16 +272,65 @@ static void add_rfc822_quoted(struct strbuf *out, const char *s, int len)
272
272
strbuf_addch (out , '"' );
273
273
}
274
274
275
- static int is_rfc2047_special (char ch )
275
+ enum rfc2047_type {
276
+ RFC2047_SUBJECT ,
277
+ RFC2047_ADDRESS ,
278
+ };
279
+
280
+ static int is_rfc2047_special (char ch , enum rfc2047_type type )
276
281
{
277
- if (ch == ' ' || ch == '\n' )
282
+ /*
283
+ * rfc2047, section 4.2:
284
+ *
285
+ * 8-bit values which correspond to printable ASCII characters other
286
+ * than "=", "?", and "_" (underscore), MAY be represented as those
287
+ * characters. (But see section 5 for restrictions.) In
288
+ * particular, SPACE and TAB MUST NOT be represented as themselves
289
+ * within encoded words.
290
+ */
291
+
292
+ /*
293
+ * rule out non-ASCII characters and non-printable characters (the
294
+ * non-ASCII check should be redundant as isprint() is not localized
295
+ * and only knows about ASCII, but be defensive about that)
296
+ */
297
+ if (non_ascii (ch ) || !isprint (ch ))
298
+ return 1 ;
299
+
300
+ /*
301
+ * rule out special printable characters (' ' should be the only
302
+ * whitespace character considered printable, but be defensive and use
303
+ * isspace())
304
+ */
305
+ if (isspace (ch ) || ch == '=' || ch == '?' || ch == '_' )
278
306
return 1 ;
279
307
280
- return (non_ascii (ch ) || (ch == '=' ) || (ch == '?' ) || (ch == '_' ));
308
+ /*
309
+ * rfc2047, section 5.3:
310
+ *
311
+ * As a replacement for a 'word' entity within a 'phrase', for example,
312
+ * one that precedes an address in a From, To, or Cc header. The ABNF
313
+ * definition for 'phrase' from RFC 822 thus becomes:
314
+ *
315
+ * phrase = 1*( encoded-word / word )
316
+ *
317
+ * In this case the set of characters that may be used in a "Q"-encoded
318
+ * 'encoded-word' is restricted to: <upper and lower case ASCII
319
+ * letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
320
+ * (underscore, ASCII 95.)>. An 'encoded-word' that appears within a
321
+ * 'phrase' MUST be separated from any adjacent 'word', 'text' or
322
+ * 'special' by 'linear-white-space'.
323
+ */
324
+
325
+ if (type != RFC2047_ADDRESS )
326
+ return 0 ;
327
+
328
+ /* '=' and '_' are special cases and have been checked above */
329
+ return !(isalnum (ch ) || ch == '!' || ch == '*' || ch == '+' || ch == '-' || ch == '/' );
281
330
}
282
331
283
332
static void add_rfc2047 (struct strbuf * sb , const char * line , int len ,
284
- const char * encoding )
333
+ const char * encoding , enum rfc2047_type type )
285
334
{
286
335
static const int max_length = 78 ; /* per rfc2822 */
287
336
static const int max_encoded_length = 76 ; /* per rfc2047 */
@@ -304,7 +353,7 @@ static void add_rfc2047(struct strbuf *sb, const char *line, int len,
304
353
line_len += strlen (encoding ) + 5 ; /* 5 for =??q? */
305
354
for (i = 0 ; i < len ; i ++ ) {
306
355
unsigned ch = line [i ] & 0xFF ;
307
- int is_special = is_rfc2047_special (ch );
356
+ int is_special = is_rfc2047_special (ch , type );
308
357
309
358
/*
310
359
* According to RFC 2047, we could encode the special character
@@ -358,11 +407,13 @@ void pp_user_info(const struct pretty_print_context *pp,
358
407
display_name_length = name_tail - line ;
359
408
strbuf_addstr (sb , "From: " );
360
409
if (!has_rfc822_specials (line , display_name_length )) {
361
- add_rfc2047 (sb , line , display_name_length , encoding );
410
+ add_rfc2047 (sb , line , display_name_length ,
411
+ encoding , RFC2047_ADDRESS );
362
412
} else {
363
413
struct strbuf quoted = STRBUF_INIT ;
364
414
add_rfc822_quoted (& quoted , line , display_name_length );
365
- add_rfc2047 (sb , quoted .buf , quoted .len , encoding );
415
+ add_rfc2047 (sb , quoted .buf , quoted .len ,
416
+ encoding , RFC2047_ADDRESS );
366
417
strbuf_release (& quoted );
367
418
}
368
419
if (namelen - display_name_length + last_line_length (sb ) > 78 ) {
@@ -1294,7 +1345,7 @@ void pp_title_line(const struct pretty_print_context *pp,
1294
1345
strbuf_grow (sb , title .len + 1024 );
1295
1346
if (pp -> subject ) {
1296
1347
strbuf_addstr (sb , pp -> subject );
1297
- add_rfc2047 (sb , title .buf , title .len , encoding );
1348
+ add_rfc2047 (sb , title .buf , title .len , encoding , RFC2047_SUBJECT );
1298
1349
} else {
1299
1350
strbuf_addbuf (sb , & title );
1300
1351
}
0 commit comments