Определите, содержит ли строка строку base64 внутри нее - PullRequest
5 голосов
/ 04 октября 2010

Я пытаюсь найти способ разобрать строку base64 из строки большего размера.

У меня есть строка "Hello <base64 content> World", и я хочу иметь возможность проанализировать содержимое base64 и преобразовать его обратно в строку. "Hello Awesome World"

Ответы на C # предпочтительнее.

Редактировать: Обновлено с более реальным примером.

--abcdef
\n
Content-Type: Text/Plain;
Content-Transfer-Encoding: base64
\n
<base64 content>
\n
--abcdef--

Это взято из 1 образца. Проблема заключается в том, что содержимое .... варьируется от одной записи к другой.

Ответы [ 2 ]

8 голосов
/ 04 октября 2010

Нет надежного способа сделать это.Откуда вы знаете, что, например, «Hello» не является строкой base64?Хорошо, это плохой пример, потому что base64 должен быть дополнен так, чтобы длина была кратна 4, но как насчет «переполнения»?Длина 8 символов, это действительная строка base64 (она будет декодироваться как «¢ ÷« ~ Z0 »), хотя это, очевидно, обычное слово для читателя-человека.Просто невозможно точно сказать, является ли слово обычным словом или текстом в кодировке base64.

Тот факт, что текст в кодировке base64 встроен в обычный текст, явно является ошибкой проектирования, я предлагаю вам сделать что-тоскорее об этом, пытаясь сделать что-то невозможное ...

4 голосов
/ 04 октября 2010

В краткой форме вы могли бы:

  • разбить строку на любые символы, которые не являются допустимыми данными base64 или отступом
  • попробуйте конвертировать каждый токен
  • если преобразование выполнено успешно, вызовите replace в исходной строке, чтобы переключить токен с преобразованным значением

В коде:

var delimiters = new char[] { /* non-base64 ASCII chars */ };
var possibles = value.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
//need to tweak to include padding chars in matches, but still split on padding?
//maybe better off creating a regex to match base64 + padding
//and using Regex.Split?

foreach(var match in possibles)
{
    try
    {
        var converted = Convert.FromBase64String(match);
        var text = System.Text.Encoding.UTF8.GetString(converted);
        if(!string.IsNullOrEmpty(text))
        {
            value = value.Replace(match, text);
        }
    } 
    catch (System.ArgumentNullException) 
    {
        //handle it
    }
    catch (System.FormatException) 
    {
        //handle it
    }
}

Однако без разделителя вы можете в конечном итоге преобразовать текст не в формате base64, который также будет действительным как кодированный в base64 текст.

Глядя на ваш пример попытки конвертировать "Hello QXdlc29tZQ== World" в "Hello Awesome World", приведенный выше алгоритм может легко сгенерировать что-то вроде "ée¡Ý•Í½µ”¢¹]", пытаясь конвертировать всю строку из base64, поскольку нет разделителя между простым и закодированным текстом.

Обновление (на основе комментариев):

Если в содержимом base64 нет '\n' s и ему всегда предшествует "Content-Transfer-Encoding: base64\n", то есть способ:

  • разбить строку на '\n'
  • итерация по всем токенам, пока токен не заканчивается в "Content-Transfer-Encoding: base64"
  • следующий токен (если есть) должен быть декодирован (если возможно), а затем замена должна быть сделана в исходной строке
  • возврат к итерации до выхода из токенов

В коде:

private string ConvertMixedUpTextAndBase64(string value)
{
    var delimiters = new char[] { '\n' };
    var possibles = value.Split(delimiters, 
                                StringSplitOptions.RemoveEmptyEntries);

    for (int i = 0; i < possibles.Length - 1; i++)
    {
        if (possibles[i].EndsWith("Content-Transfer-Encoding: base64"))
        {
            var nextTokenPlain = DecodeBase64(possibles[i + 1]);
            if (!string.IsNullOrEmpty(nextTokenPlain))
            {
                value = value.Replace(possibles[i + 1], nextTokenPlain);
                i++;
            }
        }                
    }
    return value;
}

private string DecodeBase64(string text)
{
    string result = null;
    try
    {
        var converted = Convert.FromBase64String(text);
        result = System.Text.Encoding.UTF8.GetString(converted);
    }
    catch (System.ArgumentNullException)
    {
        //handle it
    }
    catch (System.FormatException)
    {
        //handle it
    }
    return result;
}
...