2010-10-04 15 views
5

Próbuję znaleźć sposób na sparsowanie łańcucha base64 z większym ciągiem.Ustal, czy ciąg zawiera ciąg znaków base64 wewnątrz niego

Mam ciąg "Hello <base64 content> World" i chcę móc przetworzyć zawartość base64 i przekonwertować ją z powrotem na ciąg znaków. "Hello Awesome World"

Odpowiedzi w C# preferowane.

Edytuj: Zaktualizowany bardziej realnym przykładem.

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

Zostało to pobrane z 1 próbki. Problem polega na tym, że treść ... różni się nieco od jednego rekordu do drugiego.

+1

Czy treść base64 ograniczony w żaden sposób ? – jball

+1

To jest problem XY. Prawdziwym problemem jest X: jak skończyłeś z takim stringiem. –

+0

@Hans Passant Zgadzam się, próbuję napisać narzędzie do naprawienia niektórych danych, które w jakiś sposób zostały uszkodzone. Naprawiliśmy już część tworzącą uszkodzone dane, ale teraz musimy ją naprawić na około 3 milionach rekordów. – Adam

Odpowiedz

4

W krótkim formularzu możesz:

  • podzielić ciąg na wszelkich znaków, które nie są ważne dane Base64 lub wyściółka
  • spróbować przekonwertować Każdy token
  • jeśli konwersja powiedzie, zadzwoń wymienić na Oryginalny łańcuch przełączyć token wartości przekształconego

W kodzie:

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

Bez ogranicznika można jednak konwertować tekst w formacie innym niż bazowy 64, który jest również ważny jako tekst zakodowany w formacie Base64.

Patrząc na przykład próbując przekształcić "Hello QXdlc29tZQ== World" do "Hello Awesome World" powyższy algorytm można łatwo wygenerować coś podobnego "ée¡Ý•Í½µ”¢¹]" próbując przekonwertować cały ciąg z base64 ponieważ nie ma ogranicznik między prostym i zakodowanego tekstu.

Update (w oparciu o komentarze):

Jeśli nie ma '\n' s w treści base64 i jest zawsze poprzedzone "Content-Transfer-Encoding: base64\n", to jest sposób:

  • podzielić ciąg na '\n'
  • iterować po wszystkich tokenach, aż do zakończenia tokena w "Content-Transfer-Encoding: base64"
  • następny token (jeśli istnieje) powinien zostać zdekodowany (jeśli to możliwe), a następnie zastąpić go ma de w oryginalnym ciąg
  • powrotnej do iteracji aż z tokenów

w postaci kodu:

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

Ostatnia część jest trudna. Na przykład, jeśli podzielisz i uzyskasz "aaBG" jako ciąg znaków, co zrobisz? To jest reprezentacja base64 "i F". Potrzebujesz heurystyki, aby zdecydować, której właśnie chcesz. – Yuliy

8

Nie ma niezawodny sposób, aby to zrobić. Skąd wiesz, że na przykład "Hello" nie jest łańcuchem base64? OK, to zły przykład, ponieważ base64 ma być dopełniony, aby długość była wielokrotnością 4, ale co z "przepełnieniem"? Ma on 8 znaków, jest poprawnym łańcuchem base64 (który będzie dekodować do "¢ ÷ ~ Z Z0"), mimo że jest to normalne słowo dla ludzkiego czytelnika. Po prostu nie da się ustalić, czy słowo jest zwykłym słowem, czy zakodowanym w standardzie64.

Fakt, że base64 zakodowany tekst osadzony w zwykłym tekście jest wyraźnie błędem projekt, proponuję coś z tym zrobić, a że próbuje zrobić coś niemożliwego ...

Powiązane problemy