NeoMutt  2020-11-20
Teaching an old dog new tricks
DOXYGEN
rfc2231.h File Reference

RFC2231 MIME Charset routines. More...

#include <stddef.h>
#include <stdbool.h>
+ Include dependency graph for rfc2231.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void rfc2231_decode_parameters (struct ParameterList *pl)
 Decode a Parameter list. More...
 
size_t rfc2231_encode_string (struct ParameterList *head, const char *attribute, char *value)
 Encode a string to be suitable for an RFC2231 header. More...
 

Variables

bool C_Rfc2047Parameters
 Config: Decode RFC2047-encoded MIME parameters. More...
 

Detailed Description

RFC2231 MIME Charset routines.

Authors
  • Thomas Roessler

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file rfc2231.h.

Function Documentation

◆ rfc2231_decode_parameters()

void rfc2231_decode_parameters ( struct ParameterList *  pl)

Decode a Parameter list.

Parameters
plList to decode

Definition at line 235 of file rfc2231.c.

236 {
237  if (!pl)
238  return;
239 
240  struct Rfc2231Parameter *conthead = NULL;
241  struct Rfc2231Parameter *conttmp = NULL;
242 
243  char *s = NULL, *t = NULL;
244  char charset[256];
245 
246  bool encoded;
247  int index;
248  bool dirty = false; /* set when we may have created empty parameters. */
249 
251 
252  struct Parameter *np = NULL, *tmp = NULL;
253  TAILQ_FOREACH_SAFE(np, pl, entries, tmp)
254  {
255  s = strchr(np->attribute, '*');
256  if (!s)
257  {
258  /* Using RFC2047 encoding in MIME parameters is explicitly
259  * forbidden by that document. Nevertheless, it's being
260  * generated by some software, including certain Lotus Notes to
261  * Internet Gateways. So we actually decode it. */
262 
263  if (C_Rfc2047Parameters && np->value && strstr(np->value, "=?"))
264  rfc2047_decode(&np->value);
265  else if (C_AssumedCharset)
267  }
268  else if (s[1] == '\0')
269  {
270  s[0] = '\0';
271 
272  s = get_charset(np->value, charset, sizeof(charset));
273  decode_one(np->value, s);
276  dirty = true;
277  }
278  else
279  {
280  s[0] = '\0';
281  s++; /* let s point to the first character of index. */
282  for (t = s; (t[0] != '\0') && isdigit((unsigned char) t[0]); t++)
283  ; // do nothing
284 
285  encoded = (t[0] == '*');
286  t[0] = '\0';
287 
288  /* RFC2231 says that the index starts at 0 and increments by 1,
289  * thus an overflow should never occur in a valid message, thus
290  * the value INT_MAX in case of overflow does not really matter
291  * (the goal is just to avoid undefined behaviour). */
292  if (mutt_str_atoi(s, &index) != 0)
293  index = INT_MAX;
294 
295  conttmp = parameter_new();
296  conttmp->attribute = np->attribute;
297  conttmp->value = np->value;
298  conttmp->encoded = encoded;
299  conttmp->index = index;
300 
301  np->attribute = NULL;
302  np->value = NULL;
303  TAILQ_REMOVE(pl, np, entries);
304  FREE(&np);
305 
306  list_insert(&conthead, conttmp);
307  }
308  }
309 
310  if (conthead)
311  {
312  join_continuations(pl, conthead);
313  dirty = true;
314  }
315 
316  if (dirty)
318 }
char * attribute
Parameter name.
Definition: parameter.h:34
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: string.c:252
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:754
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:728
static void list_insert(struct Rfc2231Parameter **list, struct Rfc2231Parameter *par)
Insert parameter into an ordered list.
Definition: rfc2231.c:146
void rfc2047_decode(char **pd)
Decode any RFC2047-encoded header fields.
Definition: rfc2047.c:639
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:834
bool C_Rfc2047Parameters
Config: Decode RFC2047-encoded MIME parameters.
Definition: rfc2231.c:49
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
static void join_continuations(struct ParameterList *pl, struct Rfc2231Parameter *par)
Process continuation parameters.
Definition: rfc2231.c:184
int mutt_ch_convert_nonmime_string(char **ps)
Try to convert a string using a list of character sets.
Definition: charset.c:309
static void decode_one(char *dest, char *src)
Decode one percent-encoded character.
Definition: rfc2231.c:110
static char * get_charset(char *value, char *charset, size_t chslen)
Get the charset from an RFC2231 header.
Definition: rfc2231.c:87
char * value
Parameter value.
Definition: parameter.h:35
static void purge_empty_parameters(struct ParameterList *pl)
Remove any ill-formed Parameters from a list.
Definition: rfc2231.c:67
char * attribute
Definition: rfc2231.c:56
Attribute associated with a MIME part.
Definition: parameter.h:32
#define FREE(x)
Definition: memory.h:40
static struct Rfc2231Parameter * parameter_new(void)
Create a new Rfc2231Parameter.
Definition: rfc2231.c:133
int mutt_mb_filter_unprintable(char **s)
Replace unprintable characters.
Definition: mbyte.c:424
char * C_AssumedCharset
Config: If a message is missing a character set, assume this character set.
Definition: charset.c:52
MIME section parameter.
Definition: rfc2231.c:54
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
char * value
Definition: rfc2231.c:57
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ rfc2231_encode_string()

size_t rfc2231_encode_string ( struct ParameterList *  head,
const char *  attribute,
char *  value 
)

Encode a string to be suitable for an RFC2231 header.

Parameters
headString encoded as a ParameterList, empty on error
attributeName of attribute to encode
valueValue of attribute to encode
Return values
numNumber of Parameters in the List

If the value is large, the list will contain continuation lines.

Definition at line 329 of file rfc2231.c.

330 {
331  if (!attribute || !value)
332  return 0;
333 
334  size_t count = 0;
335  bool encode = false;
336  bool add_quotes = false;
337  bool free_src_value = false;
338  bool split = false;
339  int continuation_number = 0;
340  size_t dest_value_len = 0, max_value_len = 0, cur_value_len = 0;
341  char *cur = NULL, *charset = NULL, *src_value = NULL;
342  struct Parameter *current = NULL;
343 
344  struct Buffer *cur_attribute = mutt_buffer_pool_get();
345  struct Buffer *cur_value = mutt_buffer_pool_get();
346 
347  // Perform charset conversion
348  for (cur = value; *cur; cur++)
349  {
350  if ((*cur < 0x20) || (*cur >= 0x7f))
351  {
352  encode = true;
353  break;
354  }
355  }
356 
357  if (encode)
358  {
359  if (C_Charset && C_SendCharset)
360  {
361  charset = mutt_ch_choose(C_Charset, C_SendCharset, value,
362  mutt_str_len(value), &src_value, NULL);
363  }
364  if (src_value)
365  free_src_value = true;
366  if (!charset)
367  charset = mutt_str_dup(C_Charset ? C_Charset : "unknown-8bit");
368  }
369  if (!src_value)
370  src_value = value;
371 
372  // Count the size the resultant value will need in total
373  if (encode)
374  dest_value_len = mutt_str_len(charset) + 2; /* charset'' prefix */
375 
376  for (cur = src_value; *cur; cur++)
377  {
378  dest_value_len++;
379 
380  if (encode)
381  {
382  /* These get converted to %xx so need a total of three chars */
383  if ((*cur < 0x20) || (*cur >= 0x7f) || strchr(MimeSpecials, *cur) ||
384  strchr("*'%", *cur))
385  {
386  dest_value_len += 2;
387  }
388  }
389  else
390  {
391  /* rfc822_cat() will add outer quotes if it finds MimeSpecials. */
392  if (!add_quotes && strchr(MimeSpecials, *cur))
393  add_quotes = true;
394  /* rfc822_cat() will add a backslash if it finds '\' or '"'. */
395  if ((*cur == '\\') || (*cur == '"'))
396  dest_value_len++;
397  }
398  }
399 
400  // Determine if need to split into parameter value continuations
401  max_value_len = 78 - // rfc suggested line length
402  1 - // Leading tab on continuation line
403  mutt_str_len(attribute) - // attribute
404  (encode ? 1 : 0) - // '*' encoding marker
405  1 - // '='
406  (add_quotes ? 2 : 0) - // "...."
407  1; // ';'
408 
409  if (max_value_len < 30)
410  max_value_len = 30;
411 
412  if (dest_value_len > max_value_len)
413  {
414  split = true;
415  max_value_len -= 4; /* '*n' continuation number and extra encoding
416  * space to keep loop below simpler */
417  }
418 
419  // Generate list of parameter continuations
420  cur = src_value;
421  if (encode)
422  {
423  mutt_buffer_printf(cur_value, "%s''", charset);
424  cur_value_len = mutt_buffer_len(cur_value);
425  }
426 
427  while (*cur)
428  {
429  current = mutt_param_new();
430  TAILQ_INSERT_TAIL(head, current, entries);
431  count++;
432 
433  mutt_buffer_strcpy(cur_attribute, attribute);
434  if (split)
435  mutt_buffer_add_printf(cur_attribute, "*%d", continuation_number++);
436  if (encode)
437  mutt_buffer_addch(cur_attribute, '*');
438 
439  while (*cur && (!split || (cur_value_len < max_value_len)))
440  {
441  if (encode)
442  {
443  if ((*cur < 0x20) || (*cur >= 0x7f) || strchr(MimeSpecials, *cur) ||
444  strchr("*'%", *cur))
445  {
446  mutt_buffer_add_printf(cur_value, "%%%02X", (unsigned char) *cur);
447  cur_value_len += 3;
448  }
449  else
450  {
451  mutt_buffer_addch(cur_value, *cur);
452  cur_value_len++;
453  }
454  }
455  else
456  {
457  mutt_buffer_addch(cur_value, *cur);
458  cur_value_len++;
459  if ((*cur == '\\') || (*cur == '"'))
460  cur_value_len++;
461  }
462 
463  cur++;
464  }
465 
466  current->attribute = mutt_buffer_strdup(cur_attribute);
467  current->value = mutt_buffer_strdup(cur_value);
468 
469  mutt_buffer_reset(cur_value);
470  cur_value_len = 0;
471  }
472 
473  mutt_buffer_pool_release(&cur_attribute);
474  mutt_buffer_pool_release(&cur_value);
475 
476  FREE(&charset);
477  if (free_src_value)
478  FREE(&src_value);
479 
480  return count;
481 }
char * attribute
Parameter name.
Definition: parameter.h:34
static int encode(const char *d, size_t dlen, int col, const char *fromcode, const char *charsets, char **e, size_t *elen, const char *specials)
RFC2047-encode a string.
Definition: rfc2047.c:415
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
struct Parameter * mutt_param_new(void)
Create a new Parameter.
Definition: parameter.c:39
char * mutt_ch_choose(const char *fromcode, const char *charsets, const char *u, size_t ulen, char **d, size_t *dlen)
Figure the best charset to encode a string.
Definition: charset.c:1036
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
int mutt_buffer_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:203
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:356
const char MimeSpecials[]
Characters that need special treatment in MIME.
Definition: mime.c:67
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:802
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
char * value
Parameter value.
Definition: parameter.h:35
Attribute associated with a MIME part.
Definition: parameter.h:32
#define FREE(x)
Definition: memory.h:40
char * C_SendCharset
Config: Character sets for outgoing mail.
Definition: globals.c:38
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:53
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ C_Rfc2047Parameters

bool C_Rfc2047Parameters

Config: Decode RFC2047-encoded MIME parameters.

Definition at line 49 of file rfc2231.c.