NeoMutt  2019-12-07-168-gc45f47
Teaching an old dog new tricks
DOXYGEN
rfc2231.h File Reference

RFC2231 MIME Charset routines. More...

#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...
 
struct ParameterList rfc2231_encode_string (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  ;
284  encoded = (t[0] == '*');
285  t[0] = '\0';
286 
287  /* RFC2231 says that the index starts at 0 and increments by 1,
288  * thus an overflow should never occur in a valid message, thus
289  * the value INT_MAX in case of overflow does not really matter
290  * (the goal is just to avoid undefined behaviour). */
291  if (mutt_str_atoi(s, &index) != 0)
292  index = INT_MAX;
293 
294  conttmp = parameter_new();
295  conttmp->attribute = np->attribute;
296  conttmp->value = np->value;
297  conttmp->encoded = encoded;
298  conttmp->index = index;
299 
300  np->attribute = NULL;
301  np->value = NULL;
302  TAILQ_REMOVE(pl, np, entries);
303  FREE(&np);
304 
305  list_insert(&conthead, conttmp);
306  }
307  }
308 
309  if (conthead)
310  {
311  join_continuations(pl, conthead);
312  dirty = true;
313  }
314 
315  if (dirty)
317 }
char * attribute
Parameter name.
Definition: parameter.h:34
char * C_AssumedCharset
Config: If a message is missing a character set, assume this character set.
Definition: charset.c:53
int mutt_ch_convert_string(char **ps, const char *from, const char *to, int flags)
Convert a string between encodings.
Definition: charset.c:748
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: string.c:262
#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:651
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:834
bool C_Rfc2047Parameters
Config: Decode RFC2047-encoded MIME parameters.
Definition: rfc2231.c:49
static void join_continuations(struct ParameterList *pl, struct Rfc2231Parameter *par)
Process continuation parameters.
Definition: rfc2231.c:184
static const char encoded[]
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
int mutt_ch_convert_nonmime_string(char **ps)
Try to convert a string using a list of character sets.
Definition: charset.c:301
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
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:54
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
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:81
MIME section parameter.
Definition: rfc2231.c:54
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()

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

Encode a string to be suitable for an RFC2231 header.

Parameters
attributeName of attribute to encode
valueValue of attribute to encode
Return values
objString encoded as a ParameterList
objError: empty object

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

Definition at line 328 of file rfc2231.c.

329 {
330  struct ParameterList pl;
331  TAILQ_INIT(&pl);
332 
333  if (!attribute || !value)
334  return pl;
335 
336  bool encode = false;
337  bool add_quotes = false;
338  bool free_src_value = false;
339  bool split = false;
340  int continuation_number = 0;
341  size_t dest_value_len = 0, max_value_len = 0, cur_value_len = 0;
342  char *cur = NULL, *charset = NULL, *src_value = NULL;
343  struct Parameter *current = NULL;
344 
345  struct Buffer *cur_attribute = mutt_buffer_pool_get();
346  struct Buffer *cur_value = mutt_buffer_pool_get();
347 
348  // Perform charset conversion
349  for (cur = value; *cur; cur++)
350  {
351  if ((*cur < 0x20) || (*cur >= 0x7f))
352  {
353  encode = true;
354  break;
355  }
356  }
357 
358  if (encode)
359  {
360  if (C_Charset && C_SendCharset)
361  {
362  charset = mutt_ch_choose(C_Charset, C_SendCharset, value,
363  mutt_str_strlen(value), &src_value, NULL);
364  }
365  if (src_value)
366  free_src_value = true;
367  if (!charset)
368  charset = mutt_str_strdup(C_Charset ? C_Charset : "unknown-8bit");
369  }
370  if (!src_value)
371  src_value = value;
372 
373  // Count the size the resultant value will need in total
374  if (encode)
375  dest_value_len = mutt_str_strlen(charset) + 2; /* charset'' prefix */
376 
377  for (cur = src_value; *cur; cur++)
378  {
379  dest_value_len++;
380 
381  if (encode)
382  {
383  /* These get converted to %xx so need a total of three chars */
384  if ((*cur < 0x20) || (*cur >= 0x7f) || strchr(MimeSpecials, *cur) ||
385  strchr("*'%", *cur))
386  {
387  dest_value_len += 2;
388  }
389  }
390  else
391  {
392  /* rfc822_cat() will add outer quotes if it finds MimeSpecials. */
393  if (!add_quotes && strchr(MimeSpecials, *cur))
394  add_quotes = true;
395  /* rfc822_cat() will add a backslash if it finds '\' or '"'. */
396  if ((*cur == '\\') || (*cur == '"'))
397  dest_value_len++;
398  }
399  }
400 
401  // Determine if need to split into parameter value continuations
402  max_value_len = 78 - // rfc suggested line length
403  1 - // Leading tab on continuation line
404  mutt_str_strlen(attribute) - // attribute
405  (encode ? 1 : 0) - // '*' encoding marker
406  1 - // '='
407  (add_quotes ? 2 : 0) - // "...."
408  1; // ';'
409 
410  if (max_value_len < 30)
411  max_value_len = 30;
412 
413  if (dest_value_len > max_value_len)
414  {
415  split = true;
416  max_value_len -= 4; /* '*n' continuation number and extra encoding
417  * space to keep loop below simpler */
418  }
419 
420  // Generate list of parameter continuations
421  cur = src_value;
422  if (encode)
423  {
424  mutt_buffer_printf(cur_value, "%s''", charset);
425  cur_value_len = mutt_buffer_len(cur_value);
426  }
427 
428  while (*cur)
429  {
430  current = mutt_param_new();
431  TAILQ_INSERT_TAIL(&pl, current, entries);
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 pl;
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:428
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_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:1030
struct Parameter * mutt_param_new(void)
Create a new Parameter.
Definition: parameter.c:39
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
char * mutt_buffer_strdup(struct Buffer *buf)
Copy a Buffer&#39;s string.
Definition: buffer.c:432
String manipulation buffer.
Definition: buffer.h:33
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:689
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
char * C_SendCharset
Config: Character sets for outgoing mail.
Definition: email_globals.c:38
#define TAILQ_INIT(head)
Definition: queue.h:758
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
char * value
Parameter value.
Definition: parameter.h:35
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
Attribute associated with a MIME part.
Definition: parameter.h:32
#define FREE(x)
Definition: memory.h:40
char * C_Charset
Config: Default character set for displaying text on screen.
Definition: charset.c:54
+ 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.