确定字符串是否包含其中的base64字符串

时间:2010-10-04 18:20:55

标签: c# .net parsing string

我正试图找出一种用更大的字符串解析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 个答案:

答案 0 :(得分:8)

没有可靠的方法来做到这一点。你怎么知道,例如,“Hello”不是base64字符串?好吧,这是一个不好的例子,因为base64应该被填充,因此长度是4的倍数,但是“溢出”呢?它是8个字符长,它是一个有效的base64字符串(它将解码为“¢÷«~Z0”),即使它显然是人类读者的正常单词。你无法确定一个单词是普通单词还是base64编码文本。

你在普通文本中嵌入base64编码文本的事实显然是一个设计错误,我建议你做一些事情,而不是尝试做一些不可能的事情......

答案 1 :(得分:4)

简而言之,您可以:

  • 将字符串拆分为任何非有效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"的示例,通过尝试从base64转换整个字符串,可以轻松生成类似"ée¡Ý•Í½µ”¢¹]"的内容,因为之间没有分隔符纯文本和编码文本。

更新(根据评论):

如果base64内容中没有'\n',并且它始终以"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;
}