Package: mpack Version: 1.6-18 The munpack utility which is part of the mpack package does not handle attachment filenames that are split into parts. The attached patch fixes this.
I have tested the patched version against a variety of split filenames formats, some mail senders add a ; to the end of each part, some don't. And it have worked fine for all the mails that I've tested it against so far. I have attached the patch as a file since Gmail is known to mess up inlined patches. Regards, Henrik Holst
Description: fix munpack fail to decode splitted attachment filename --- mpack-1.6.orig/decode.c +++ mpack-1.6/decode.c @@ -513,6 +513,50 @@ return value; } +static int copyFilename(char **in, char **out, char **buffer, int *alloced, int *left) +{ + if (*alloced == 0) { + *buffer = xmalloc(*alloced = VALUEGROWSIZE); + *out = *buffer; + *left = *alloced - 1; + } + + /* Copy value into buffer */ + if (**in == '\"') { + /* Quoted-string */ + (*in)++; + while (**in && **in != '\"') { + if (!--(*left)) { + *alloced += VALUEGROWSIZE; + *left += VALUEGROWSIZE; + *buffer = xrealloc(*buffer, *alloced); + *out = *buffer + *alloced - *left - 2; + } + if (**in == '\\') { + (*in)++; + if (!**in) return 0; + } + *(*out)++ = *(*in)++; + } + if (!**in) return 0; + } + else { + /* Just a token */ + while (**in && !isspace((unsigned char)(**in)) && + **in != '(') { + if (!--(*left)) { + *alloced += VALUEGROWSIZE; + *left += VALUEGROWSIZE; + *buffer = xrealloc(*buffer, *alloced); + *out = *buffer + *alloced - *left - 2; + } + *(*out)++ = *(*in)++; + } + } + **out = '\0'; + return 1; +} + /* * Get the value of the "filename" parameter in a Content-Disposition: * header. Returns a pointer to a static buffer containing the value, or @@ -523,8 +567,9 @@ { static char *value; static int alloced = 0; - int left; - char *to; + int parts = 0; + int left = alloced - 1; + char *to = value; if (!disposition) return 0; @@ -532,21 +577,21 @@ for (;;) { /* Skip until we find ";" */ while (*disposition != ';') { - if (!*disposition) return 0; + if (!disposition) goto early_exit; else if (*disposition == '\"') { ++disposition; while (*disposition && *disposition != '\"') { if (*disposition == '\\') { ++disposition; - if (!*disposition) return 0; + if (!disposition) goto early_exit; } ++disposition; } - if (!*disposition) return 0; + if (!disposition) goto early_exit; } else if (*disposition == '(') { SkipWhitespace(&disposition); - if (!disposition) return 0; + if (!disposition) goto early_exit; disposition--; } disposition++; @@ -554,8 +599,10 @@ /* Skip over ";" and trailing whitespace */ disposition++; + +decode_next_part: SkipWhitespace(&disposition); - if (!disposition) return 0; + if (!disposition) goto early_exit; /* * If we're not looking at a "filename" token, go back @@ -564,60 +611,43 @@ */ if (strncasecmp(disposition, "filename", 8) != 0) continue; disposition += 8; + if (*disposition == '*') { /* filename is split into parts */ + disposition++; + parts++; + while (isdigit ((unsigned char)*disposition) != 0) + disposition++; + } if (!isspace(*disposition) && *disposition != '=' && *disposition != '(') { continue; } SkipWhitespace(&disposition); - if (!disposition) return 0; + if (!disposition) goto early_exit; /* If we're looking at a "=", we found what we're looking for */ - if (*disposition++ == '=') break; - } + if (*disposition++ == '=') { + SkipWhitespace(&disposition); + if (!disposition) goto early_exit; - SkipWhitespace(&disposition); - if (!disposition) return 0; - - if (!alloced) { - value = xmalloc(alloced = VALUEGROWSIZE); - } + if (copyFilename(&disposition, &to, &value, &alloced, &left) == 0) { + parts--; + goto early_exit; + } - /* Copy value into buffer */ - to = value; - left = alloced - 1; - if (*disposition == '\"') { - /* Quoted-string */ - disposition++; - while (*disposition && *disposition != '\"') { - if (!--left) { - alloced += VALUEGROWSIZE; - left += VALUEGROWSIZE; - value = xrealloc(value, alloced); - to = value + alloced - left - 2; - } - if (*disposition == '\\') { - disposition++; - if (!*disposition) return 0; - } - *to++ = *disposition++; - } - if (!*disposition) return 0; - } - else { - /* Just a token */ - while (*disposition && !isspace(*disposition) && - *disposition != '(') { - if (!--left) { - alloced += VALUEGROWSIZE; - left += VALUEGROWSIZE; - value = xrealloc(value, alloced); - to = value + alloced - left - 2; - } - *to++ = *disposition++; + if (*disposition == '\"') disposition++; + + if (parts) + goto decode_next_part; + + return value; } } - *to = '\0'; - return value; + +early_exit: + if (parts) + return value; + + return 0; } /*