Ejemplo n.º 1
0
        /// <summary>
        /// Decodes non-ascii word with MIME <b>encoded-word</b> method. Defined in RFC 2047 2.
        /// </summary>
        /// <param name="word">MIME encoded-word value.</param>
        /// <returns>Returns decoded word.</returns>
        /// <remarks>If <b>word</b> is not encoded-word or has invalid syntax, <b>word</b> is leaved as is.</remarks>
        /// <exception cref="ArgumentNullException">Is raised when <b>word</b> is null reference.</exception>
        public static string DecodeS(string word)
        {
            if (word == null)
            {
                throw new ArgumentNullException("word");
            }

            /* RFC 2047 2.
             *  encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
             *
             * RFC 2231.
             *  encoded-word := "=?" charset ["*" language] "?" encoded-text "?="
             */

            try{
                string[] parts = word.Split('?');
                // Not encoded-word.
                if (parts.Length != 5)
                {
                    return(word);
                }
                else if (parts[2].ToUpper() == "Q")
                {
                    return(MIME_Utils.QDecode(Encoding.GetEncoding(parts[1].Split('*')[0]), parts[3]));
                }
                else if (parts[2].ToUpper() == "B")
                {
                    return(Encoding.GetEncoding(parts[1].Split('*')[0]).GetString(Net_Utils.FromBase64(Encoding.Default.GetBytes(parts[3]))));
                }
                // Unknown encoding.
                else
                {
                    return(word);
                }
            }
            catch {
                // Failed to parse encoded-word, leave it as is. RFC 2047 6.3.
                return(word);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Reads RFC 2047 'encoded-word' from source stream.
        /// </summary>
        /// <returns>Returns RFC 2047 'encoded-word' or null if end of stream reached.</returns>
        /// <exception cref="InvalidOperationException">Is raised when source stream has no encoded-word at current position.</exception>
        public string EncodedWord()
        {
            /* RFC 2047 2.
             *  encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
             *
             *  encoded-text = 1*<Any printable ASCII character other than "?" or SPACE>
             *                 ; (but see "Use of encoded-words in message
             *                 ; headers", section 5)
             *
             *  An 'encoded-word' may not be more than 75 characters long, including
             *  'charset', 'encoding', 'encoded-text', and delimiters.  If it is
             *  desirable to encode more text than will fit in an 'encoded-word' of
             *  75 characters, multiple 'encoded-word's (separated by CRLF SPACE) may
             *  be used.
             */

            ToFirstChar();

            if (Peek(false) != '=')
            {
                throw new InvalidOperationException("No encoded-word available.");
            }

            StringBuilder retVal = new StringBuilder();

            while (true)
            {
                int index = m_Source.IndexOf("?=", m_Offset);
                // Invalid or not encoded-word.
                if (index == -1)
                {
                    retVal.Append(ToEnd());
                }
                else
                {
                    string encodedWord = m_Source.Substring(m_Offset, index - m_Offset + 2);

                    // Move index over encoded-word.
                    m_Offset += encodedWord.Length;

                    try{
                        string[] encodedWordParts = encodedWord.Split('?');
                        if (encodedWordParts[2].ToUpper() == "Q")
                        {
                            retVal.Append(MIME_Utils.QDecode(Encoding.GetEncoding(encodedWordParts[1]), encodedWordParts[3]));
                        }
                        else if (encodedWordParts[2].ToUpper() == "B")
                        {
                            retVal.Append(Encoding.GetEncoding(encodedWordParts[1]).GetString(Net_Utils.FromBase64(Encoding.Default.GetBytes(encodedWordParts[3]))));
                        }
                        // Failed to parse encoded-word, leave it as is. RFC 2047 6.3.
                        else
                        {
                            retVal.Append(encodedWord);
                        }
                    }
                    catch {
                        // Failed to parse encoded-word, leave it as is. RFC 2047 6.3.
                        retVal.Append(encodedWord);
                    }
                }

                // We have continuos encoded-word.
                if (m_Source.Substring(m_Offset).TrimStart().StartsWith("=?"))
                {
                    ToFirstChar();
                }
                // encoded-word does not continue.
                else
                {
                    break;
                }
            }

            return(retVal.ToString());
        }
        /// <summary>
        /// Decodes non-ascii text with MIME <b>encoded-word</b> method. Defined in RFC 2047 2.
        /// </summary>
        /// <param name="text">Text.</param>
        /// <returns>Returns decoded text.</returns>
        /// <exception cref="ArgumentNullException">Is raised when <b>text</b> is null reference.</exception>
        public static string DecodeTextS(string text)
        {
            if (text == null)
            {
                throw new ArgumentNullException("word");
            }

            /* RFC 2047 2.
             *  encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
             *
             *  encoded-text = 1*<Any printable ASCII character other than "?" or SPACE>
             *                 ; (but see "Use of encoded-words in message
             *                 ; headers", section 5)
             *
             *  An 'encoded-word' may not be more than 75 characters long, including
             *  'charset', 'encoding', 'encoded-text', and delimiters.  If it is
             *  desirable to encode more text than will fit in an 'encoded-word' of
             *  75 characters, multiple 'encoded-word's (separated by CRLF SPACE) may
             *  be used.
             *
             *  RFC 2231 updates.
             *      encoded-word := "=?" charset ["*" language] "?" encoded-text "?="
             */

            string retVal = text;

            retVal = encodedword_regex.Replace(retVal, delegate(Match m)
            {
                // We have encoded word, try to decode it.
                // Also if we have continuing encoded word, we need to skip all whitespaces between words.

                string encodedWord = m.Value;
                try
                {
                    if (string.Equals(m.Groups["encoding"].Value, "Q", StringComparison.InvariantCultureIgnoreCase))
                    {
                        encodedWord = MIME_Utils.QDecode(Encoding.GetEncoding(m.Groups["charset"].Value), m.Groups["value"].Value);
                    }
                    else if (string.Equals(m.Groups["encoding"].Value, "B", StringComparison.InvariantCultureIgnoreCase))
                    {
                        encodedWord = Encoding.GetEncoding(m.Groups["charset"].Value).GetString(Net_Utils.FromBase64(Encoding.Default.GetBytes(m.Groups["value"].Value)));
                    }
                    // Failed to parse encoded-word, leave it as is. RFC 2047 6.3.
                    // else{

                    // No continuing encoded-word, append whitespaces to retval.
                    Match mNext = encodedword_regex.Match(retVal, m.Index + m.Length);
                    if (!(mNext.Success && mNext.Index == (m.Index + m.Length)))
                    {
                        encodedWord += m.Groups["whitespaces"].Value;
                    }
                    // We have continuing encoded-word, so skip all whitespaces.
                    //else{

                    return(encodedWord);
                }
                catch
                {
                    // Failed to parse encoded-word, leave it as is. RFC 2047 6.3.
                    return(encodedWord);
                }
            });

            return(retVal);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Reads RFC 2047 (section 5) 'phrase' from source stream.
        /// </summary>
        /// <returns>Returns RFC 2047 (section 5) 'phrase' or null if end of stream reached.</returns>
        public string Phrase()
        {
            /* RFC 2047 5.
             *  phrase = 1*( encoded-word / word )
             *  word   = atom / quoted-string
             */

            int peek = Peek(true);

            if (peek == -1)
            {
                return(null);
            }
            else if (peek == '"')
            {
                return("\"" + QuotedString() + "\"");
            }
            else if (peek == '=')
            {
                return(EncodedWord());
            }
            else
            {
                string word = Atom();
                if (word == null)
                {
                    return(null);
                }

                // Try to encode invalid encoded-words if any mixed in text.
                word = encodedword_regex.Replace(word, delegate(Match m){
                    string encodedWord = m.Value;
                    try{
                        if (string.Equals(m.Groups["encoding"].Value, "Q", StringComparison.InvariantCultureIgnoreCase))
                        {
                            return(MIME_Utils.QDecode(Encoding.GetEncoding(m.Groups["charset"].Value), m.Groups["value"].Value));
                        }
                        else if (string.Equals(m.Groups["encoding"].Value, "B", StringComparison.InvariantCultureIgnoreCase))
                        {
                            return(Encoding.GetEncoding(m.Groups["charset"].Value).GetString(Net_Utils.FromBase64(Encoding.Default.GetBytes(m.Groups["value"].Value))));
                        }
                        // Failed to parse encoded-word, leave it as is. RFC 2047 6.3.
                        else
                        {
                            return(encodedWord);
                        }
                    }
                    catch {
                        // Failed to parse encoded-word, leave it as is. RFC 2047 6.3.
                        return(encodedWord);
                    }
                });

                return(word);
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Reads RFC 2047 'encoded-word' from source stream.
        /// </summary>
        /// <returns>Returns RFC 2047 'encoded-word' or null if end of stream reached.</returns>
        /// <exception cref="InvalidOperationException">Is raised when source stream has no encoded-word at current position.</exception>
        public string EncodedWord()
        {
            /* RFC 2047 2.
             *  encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
             *
             *  encoded-text = 1*<Any printable ASCII character other than "?" or SPACE>
             *                 ; (but see "Use of encoded-words in message
             *                 ; headers", section 5)
             *
             *  An 'encoded-word' may not be more than 75 characters long, including
             *  'charset', 'encoding', 'encoded-text', and delimiters.  If it is
             *  desirable to encode more text than will fit in an 'encoded-word' of
             *  75 characters, multiple 'encoded-word's (separated by CRLF SPACE) may
             *  be used.
             */

            ToFirstChar();

            if (Peek(false) != '=')
            {
                throw new InvalidOperationException("No encoded-word available.");
            }

            StringBuilder retVal = new StringBuilder();

            while (true)
            {
                Match match = encodedword_regex.Match(m_Source, m_Offset);
                if (match.Success && match.Index == m_Offset)
                {
                    string encodedWord = m_Source.Substring(m_Offset, match.Length);
                    // Move index over encoded-word.
                    m_Offset += match.Length;

                    try{
                        if (string.Equals(match.Groups["encoding"].Value, "Q", StringComparison.InvariantCultureIgnoreCase))
                        {
                            retVal.Append(MIME_Utils.QDecode(Encoding.GetEncoding(match.Groups["charset"].Value), match.Groups["value"].Value));
                        }
                        else if (string.Equals(match.Groups["encoding"].Value, "B", StringComparison.InvariantCultureIgnoreCase))
                        {
                            retVal.Append(Encoding.GetEncoding(match.Groups["charset"].Value).GetString(Net_Utils.FromBase64(Encoding.Default.GetBytes(match.Groups["value"].Value))));
                        }
                        // Failed to parse encoded-word, leave it as is. RFC 2047 6.3.
                        else
                        {
                            retVal.Append(encodedWord);
                        }
                    }
                    catch {
                        // Failed to parse encoded-word, leave it as is. RFC 2047 6.3.
                        retVal.Append(encodedWord);
                    }
                }
                else
                {
                    retVal.Append(Atom());
                }

                // We have continuos encoded-word.
                match = encodedword_regex.Match(m_Source, m_Offset);
                if (match.Success && match.Index == m_Offset)
                {
                    ToFirstChar();
                }
                // encoded-word does not continue.
                else
                {
                    break;
                }
            }

            return(retVal.ToString());
        }