kossch - 2009-05-08

Hi,

I found a missing feature in the library: Folder names are not - purely - sent in US-ASCII, as you can read here, in section 5.1.3. (Mailbox International Naming Convention):
http://www.ietf.org/rfc/rfc2060.txt

I searched for C# implementations, but didn't find any. Since I only need to do decoding to correctly display folder names I tried to implement that, and failed at it miserably XD

This is what I came up with:

        public string DecodeImapFolderName( string sEncodedName )
        {
            StringBuilder sb = new StringBuilder( sEncodedName.Length );
            int iNextAppendFrom = 0;

            int iStartAt;
            while( ( iStartAt = sEncodedName.IndexOf( '&', iNextAppendFrom ) ) != -1 )
            {
                // append the parts we skipped
                sb.Append( sEncodedName, iNextAppendFrom, iStartAt - iNextAppendFrom );

                int iEndAt = sEncodedName.IndexOf( '-', iStartAt + 1 );
                iNextAppendFrom = iEndAt + 1;

                // process the "&...-" part
                if( iStartAt + 1 == iEndAt )
                {
                    // "&-" -> '&'
                    sb.Append( '&' );
                }
                else
                {
                    // skip first and last characters
                    string str = sEncodedName.Substring( iStartAt + 1, iEndAt - iStartAt - 1 );

                    // ',' -> '/'
                    str = str.Replace( ',', '/' );

                    byte[] arr = Convert.FromBase64String( str );
                    sb.Append( Encoding.UTF7.GetString( arr ) );
                }
            }

            // append the rest
            sb.Append( sEncodedName, iNextAppendFrom, sEncodedName.Length - iNextAppendFrom );

            return sb.ToString();
        }

I'm pretty sure this is mostly correct, but it throws an exception at Convert.FromBase64String saying the input is too short to be base64 encoded. I'm sure it must be something trivial, but I just can't get my head around it. I guess I must have misunderstood the specification...

Anyways, as a quick fix I can recommend this function:

            public string DecodeImapFolderName3( string sEncodedName )
            {
                StringBuilder sb = new StringBuilder( sEncodedName.Length );
                int iNextAppendFrom = 0;

                int iStartAt;
                while( ( iStartAt = sEncodedName.IndexOf( '&', iNextAppendFrom ) ) != -1 )
                {
                    // append the parts we skipped
                    sb.Append( sEncodedName, iNextAppendFrom, iStartAt - iNextAppendFrom );

                    int iEndAt = sEncodedName.IndexOf( '-', iStartAt + 1 );
                    iNextAppendFrom = iEndAt + 1;

                    // process the "&...-" part
                    if( iStartAt + 1 == iEndAt )
                    {
                        // "&-" -> '&'
                        sb.Append( '&' );
                    }
                    else
                    {
                        // skip first and last characters
                        string str = sEncodedName.Substring( iStartAt + 1, iEndAt - iStartAt - 1 );

                        // ',' -> '/'
                        str = str.Replace( ',', '/' );

                        str = '+' + str + '-';
                        byte[] arr = Encoding.ASCII.GetBytes( str );
                        sb.Append( Encoding.UTF7.GetString( arr ) );
                    }
                }

                // append the rest
                sb.Append( sEncodedName, iNextAppendFrom, sEncodedName.Length - iNextAppendFrom );

                return sb.ToString();
            }

As you can see, this is almost the same as before, but at the end I "mask" the encoded part so that the UTF7 encoding could deal with it. Although this is really bad from a programming point :)  it get's the job done... mostly :) It can deal with all the special letters in hungarian, the only problems I had were with '/', '\', and '~'.

I hope somebody smarter can see where the problem with the original is... :)

Akos