2010-10-04 9 views
5

J'essaie de trouver un moyen d'analyser une chaîne base64 avec une chaîne plus grande.Déterminez si une chaîne contient une chaîne base64 à l'intérieur

J'ai la chaîne "Hello <base64 content> World" et je veux être en mesure d'analyser le contenu base64 et le convertir en une chaîne. "Hello Awesome World"

Réponses en C# préférées.

Édition: Mise à jour avec un exemple plus réel.

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

Ceci est pris de 1 échantillon. Le problème est que le contenu varie beaucoup d'un enregistrement à l'autre.

+1

est la teneur en base64 délimité de quelque manière que ? – jball

+1

Ceci est un problème XY. Le vrai problème est X: comment vous êtes-vous retrouvé avec une chaîne comme ça? –

+0

@Hans Passant Je suis d'accord, j'essaie d'écrire un outil pour corriger certaines données qui étaient corrompues en quelque sorte. Nous avons déjà réparé la partie rendant les données corrompues, mais maintenant nous devons le réparer sur environ 3 millions d'enregistrements. – Adam

Répondre

4

En forme courte, vous pouvez:

  • diviser la chaîne sur tous les caractères qui ne sont pas des données de base64 valides ou padding
  • essayer de convertir chaque jeton
  • si la conversion réussit, appelez remplacer le chaîne d'origine pour passer le jeton avec la valeur convertie

Dans le code:

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

Cependant, sans délimiteur, vous pouvez finir par convertir du texte non-base64 qui est également valide en tant que texte codé en base64.

En regardant votre exemple d'essayer de convertir "Hello QXdlc29tZQ== World"-"Hello Awesome World" l'algorithme ci-dessus pourrait facilement générer quelque chose comme "ée¡Ý•Í½µ”¢¹]" en essayant de convertir toute la chaîne de base64 puisqu'il n'y a pas delimiter entre le texte brut et codé.

Mise à jour (en fonction des commentaires):

S'il n'y a pas '\n' s dans la teneur en base64 et il est toujours précédé d'"Content-Transfer-Encoding: base64\n", alors il y a un moyen:

  • diviser la chaîne sur '\n'
  • sur tous les itérer jetons jusqu'à ce qu'un jeton se termine dans "Content-Transfer-Encoding: base64"
  • le prochain jeton (s'il y en a) doit être décodé (si possible) et le remplacement devrait être ma de la chaîne d'origine
  • de retour à jusqu'à épuisement des itération jetons

Dans le code:

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 dernière partie est la partie difficile. Par exemple, si vous divisez et obtenez "aaBG" comme chaîne, que faites-vous? C'est la représentation base64 de "i F". Vous auriez besoin d'une heuristique pour décider quel est celui que vous voulez réellement. – Yuliy

8

Il n'y a aucun moyen fiable de le faire. Comment sauriez-vous que, par exemple, "Hello" n'est pas une chaîne base64? OK, c'est un mauvais exemple parce que base64 est censé être rembourré de sorte que la longueur est un multiple de 4, mais qu'en est-il de "débordement"? Il est long de 8 caractères, c'est une chaîne base64 valide (il décoderait en "¢ ÷" ~ Z0 "), même si c'est évidemment un mot normal pour un lecteur humain. Il n'y a aucun moyen de savoir avec certitude si un mot est un mot normal ou un texte encodé en base64.

Le fait que vous avez base64 texte codé intégré dans le texte normal est clairement une erreur de conception, je vous suggère de faire quelque chose plutôt que d'essayer de faire quelque chose d'impossible ...

Questions connexes