Проблема с декодированием quoted-printable

236
15 мая 2018, 06:50

При декодировании заголовка email-сообщения возникла проблема. Если кодировка - quoted-printable, закодированные символы переводятся в знаки вопроса. Например, =D1=80=D0=B5=D1=82=D0=B2=D0=B8=D1=82=D0=BD=D1=83=D0=BB(=D0=B0) вместо ретвитнул(а) переводит в ??????????????????(??), причём декодер Base64 отображает все символы корректно.

    public static string DecodeEncodedLine(string text)
    {
        Regex regex = new Regex(@"\s*=\?(?<charset>.*?)\?(?<encoding>[qQbB])\?(?<value>.*?)\?=");
        string encoded = text;
        string decoded = string.Empty;
        while (encoded.Length > 0)
        {
            Match match = regex.Match(encoded);
            if (match.Success)
            {
                decoded += encoded.Substring(0, match.Index);
                string charset = match.Groups["charset"].Value;
                string encoding = match.Groups["encoding"].Value.ToUpper();
                string value = match.Groups["value"].Value;
                if (encoding.Equals("B"))
                {
                    var bytes = Convert.FromBase64String(value);
                    decoded += Encoding.GetEncoding(charset).GetString(bytes);
                }
                else if (encoding.Equals("Q"))
                {
                    Regex reg = new Regex(@"(\=([0-9A-F][0-9A-F]))", RegexOptions.IgnoreCase);
                    decoded += reg.Replace(value, new MatchEvaluator(m =>
                    {
                        byte[] bytes = new byte[m.Value.Length / 3];
                        for (int i = 0; i < bytes.Length; i++)
                        {
                            string hex = m.Value.Substring(i * 3 + 1, 2);
                            int iHex = Convert.ToInt32(hex, 16);
                            bytes[i] = Convert.ToByte(iHex);
                        }
                        return Encoding.GetEncoding(charset).GetString(bytes);
                    })).Replace('_', ' ');
                }
                else
                {
                    decoded += encoded;
                    break;
                }
                encoded = encoded.Substring(match.Index + match.Length);
            }
            else
            {
                decoded += encoded;
                break;
            }
        }
        return decoded;
    }

Также пробовал Attachment attachment = Attachment.CreateAttachmentFromString("", stringAttached); - результат тот же.

Answer 1

Вы декодируете байты по-одному, а нужно декодировать группами. Вот исправленный код для quoted-printable:

Regex reg = new Regex(@"(\=(?<byte>[0-9A-F][0-9A-F]))+", RegexOptions.IgnoreCase);
decoded += reg.Replace(value, new MatchEvaluator(m =>
{
    byte[] bytes = m.Groups["byte"].Captures.Cast<Capture>().Select(c => (byte)Convert.ToInt32(c.Value, 16)).ToArray();
    return Encoding.GetEncoding(charset).GetString(bytes);
})).Replace('_', ' ');
READ ALSO
Экранирование одинарных кавычек

Экранирование одинарных кавычек

Как туда правильно впихнуть одинарную кавычку ?

156
Резиновый дизайн с TableLayoutPanel

Резиновый дизайн с TableLayoutPanel

У меня есть TableLayoutPanel, в нем k столбцов и k строк

183
Как добавить Button в TableCell? ASP.NET

Как добавить Button в TableCell? ASP.NET

Собственно на странице есть таблицаВ эту таблицу динамически добавляется информация из базы данных

212
Как отловить статус с сервера, в Unity?

Как отловить статус с сервера, в Unity?

Нужно понять какой статус мне возвращает серверНапример если статус: 201, то регистрация успешна и т

171