Attachment name is being retrieved from the wrong place

May 25, 2010 at 5:35 PM

My BlackBerry sends image attachments like this:

--part35937-boundary-2085680160-1785510977
Content-Transfer-Encoding: base64
Content-Type: application/octet-stream; name="=?utf-8?B?VklEIDAwMDAxLTIwMTAwNTI\
1LTEyMzYuM0dQ?="
Content-disposition: attachment; filename="VID 00001-20100525-1236.3GP"

AAAAHGZ0eXAzZ3A0AAABADNncDUzZ3A0aXNvbQAHbaVtZGF0AAABsAgAAAG1CQAAAQAAAAEgAIRA
A+g8ILCiHwAAAbYQwTwlo+v8X0KY4oB5///PW8ox9dqKQcRr3ZQmNq9bAPLgOK2mN27mNNMsgHtA
...

The problem is that Koolwired.IMAP gets the filename from the Content-Type line, not the Content-disposition line, when I look at part.FileName.

Is this a bug, is there a workaround, or is there a way for me to get it to retrieve the filename from the Content-disposition line?

 

Sep 2, 2011 at 1:50 PM
Edited Sep 2, 2011 at 2:03 PM
This bugs happens alot, here's the solution:

ImapMessageBodyPart.cs

else if ((match = Regex.Match(data, attachment, RegexOptions.ExplicitCapture)).Success)
            {
                this.Attachment = true;
                this.ContentType.MediaType = string.Format("{0}/{1}", match.Groups["type"].Value.Replace("\"", ""), match.Groups["subtype"].Value.Replace("\"", ""));
                if(ParseNIL(match.Groups["attr"].Value) == null)
                {
                    if(data.IndexOf("(\"attachment\" (\"filename\"") != -1)
                    {
                        string name = data.Substring(data.IndexOf("(\"attachment\" (\"filename\"") + "(\"attachment\" (\"filename\"".Length);
                        name = name.Substring(name.IndexOf("\"") + 1);
                        name = name.Substring(0, name.IndexOf("\"))"));
                        FileName = name;
                    }
                }
                else ParseFileName(ParseNIL(match.Groups["attr"].Value));
                this.ContentID = ParseNIL(match.Groups["id"].Value);
                this.ContentDescription = ParseNIL(match.Groups["desc"].Value);
                this.ContentEncoding = ParseEncoding(ParseNIL(match.Groups["encoding"].Value));
                if(ContentEncoding != BodyPartEncoding.BASE64)
                {
                    /*ContentType.CharSet = data.Substring(data.IndexOf("(\"charset\" ") + "(\"charset\" ".Length);
                    ContentType.CharSet = ContentType.CharSet.Substring(ContentType.CharSet.IndexOf("\"") + 1);
                    ContentType.CharSet = ContentType.CharSet.Substring(0, ContentType.CharSet.IndexOf("\""));*/
                    ParseCharacterSet(ParseNIL(match.Groups["attr"].Value));
                }
                this.Size = Convert.ToInt64(ParseNIL(match.Groups["size"].Value));
                try { this.Lines = Convert.ToInt64(ParseNIL(match.Groups["lines"].Value)); }
                catch
                {
                    Lines = 0;
                }
                this.Disposition = ParseNIL(match.Groups["disposition"].Value);
                this.ContentLanguage = ParseNIL(match.Groups["lang"].Value);
            }
            else
                throw new Exception("Invalid format could not parse body part headers.");

This also includes a fix for charset. (It detects sometimes - more often than not - text and html as attachments - though they don't have the "attachment" tag, this ensures they get the charset).

I also added this to avoid so many exceptions (looking on the step trace is hell because these nullreference exceptions on Encoding.

public Encoding Encoding
        {
            get
            {
                try
                {
                    if(ContentType.CharSet == null)
                    {
                        switch (ContentEncoding)
                        {
                            case BodyPartEncoding.UTF7:
                                return System.Text.Encoding.UTF7;
                                break;
                            case BodyPartEncoding.UTF8:
                                return System.Text.Encoding.UTF8;
                                break;
                            default:
                                return System.Text.Encoding.Default;
                                break;
                        }
                    }
                    return System.Text.Encoding.GetEncoding(this.ContentType.CharSet.Split('/')[1]);
                }
                catch (NullReferenceException)
                {
                    switch(ContentEncoding)
                    {
                        case BodyPartEncoding.UTF7:
                            return System.Text.Encoding.UTF7;
                            break;
                        case BodyPartEncoding.UTF8:
                            return System.Text.Encoding.UTF8;
                            break;
                        default:
                            return System.Text.Encoding.Default;
                            break;
                    }
                }
            }
        }