2010-10-04 16 views
5

Estoy tratando de encontrar una manera de analizar una cadena de base 64 a partir de una cadena más grande.Determinar si una cadena contiene una cadena de base 64 dentro de ella

Tengo la cadena "Hello <base64 content> World" y quiero poder analizar el contenido de base64 y convertirlo de nuevo en una cadena. "Hello Awesome World"

Respuestas en C# preferidos.

Editar: Actualizado con un ejemplo más real.

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

Esto se toma de 1 muestra. El problema es que el Contenido ... varía bastante de un registro a otro.

+1

es el contenido delimitado base 64 en forma alguna ? – jball

+1

Este es un problema XY. El verdadero problema es X: cómo terminaste con una cadena así. –

+0

@Hans Passant Acepto, estoy intentando escribir una herramienta para corregir algunos datos que de alguna manera estaban corruptos. Ya hemos arreglado la parte que hace los datos corruptos, pero ahora tenemos que arreglarlo en aproximadamente 3 millones de registros. – Adam

Respuesta

4

En forma corta que podía:

  • dividir la cadena en cualquier caracteres que no son datos de base64 válidos o el relleno
  • intenta convertir cada ficha
  • si la conversión se realiza correctamente, llame a sustituir en el cadena original para cambiar el token con el valor convertido

En código:

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 
    } 
} 

Sin un delimitador sin embargo, se puede lograr la conversión de texto no-base 64 que pasa a ser válido también como base64 texto.

En cuanto a su ejemplo de tratar de convertir a "Hello QXdlc29tZQ== World""Hello Awesome World" el algoritmo anterior fácilmente podría generar algo así como "ée¡Ý•Í½µ”¢¹]" por tratar de convertir a toda la cadena desde la base 64 ya que no hay delimitador entre texto plano y codificado.

Update (basado en los comentarios):

Si no hay '\n' s en el contenido de base 64 y que siempre va precedida de "Content-Transfer-Encoding: base64\n", entonces hay una manera:

  • dividir la cadena en '\n'
  • iterar sobre todas las fichas hasta que un contador termina en "Content-Transfer-Encoding: base64"
  • la siguiente muestra (si las hay) debe ser decodificado (si es posible) y luego el reemplazo debe ser ma de la cadena original
  • retorno a iterando hasta que sin fichas

En el código:

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; 
} 
+2

La última parte es la parte difícil. Por ejemplo, si se divide y obtiene "aaBG" como su cadena, ¿qué hace? Esta es la representación base64 de "i F". Necesitarías un poco de heurística para decidir cuál es la que realmente deseas. – Yuliy

8

No hay manera confiable para hacerlo. ¿Cómo sabría que, por ejemplo, "Hola" no es una cadena base64? OK, es un mal ejemplo porque se supone que base64 debe estar acolchado para que la longitud sea un múltiplo de 4, pero ¿qué pasa con el "desbordamiento"? Tiene 8 caracteres, es una cadena base64 válida (se decodificaría a "¢ ÷« ~ Z0 "), aunque obviamente es una palabra normal para un lector humano. Simplemente no hay forma de que pueda decir con certeza si una palabra es una palabra normal o un texto codificado en base64.

El hecho de que usted ha base64 texto incrustado en texto normal es claramente un error de diseño, le sugiero que haga algo al respecto en lugar de que tratar de hacer algo imposible ...

Cuestiones relacionadas