2008-08-09 20 views
2

Bevor Sie etwas anderes lesen, lesen Sie bitte die original thread.Wie kann ich XML-Dateien in xfdl (base64-gzip) codieren?

Übersicht: Eine .xfdl-Datei ist eine gezippte .xml-Datei, die dann in base64 codiert wurde. Ich möchte die .xfdl in xml decodieren, die ich dann modifizieren und dann wieder in eine .xfdl Datei umkodieren kann.

XFDL> xml.gz> xml> xml.gz> XFDL

ich in der Lage gewesen, eine .xfdl Datei zu nehmen und De-kodieren sie von base64 mit uudeview:

uudeview -i yourform.xfdl 

decommpressed es dann

mit gunzip
gunzip -S "" <UNKNOWN.001> yourform-unpacked.xml 

Das erzeugte xML 100% lesbar und sieht wunderbar. Ohne Änderung dann die xml, sollte ich in der Lage sein, es erneut zu komprimieren gzip:

gzip yourform-unpacked.xml 

Dann in Base-64-neu codiert:

base64 -e yourform-unpacked.xml.gz yourform_reencoded.xfdl 

Wenn mein Denken richtig ist, die ursprüngliche Datei und die neu codierte Datei sollte gleich sein. Wenn ich yourform.xfdl und yourform_reencoded.xfdl in den Vergleich vergleiche, stimmen sie jedoch nicht überein. Außerdem kann die Originaldatei in einem http://www.grants.gov/help/download_software.jsp#pureedge">.xfdl-Viewer angezeigt werden. Der Viewer sagt, dass das neu codierte xfdl nicht lesbar ist.

I Ich habe auch versucht, Uuenview in Base64 neu zu kodieren, es erzeugt auch die gleichen Ergebnisse. Jede Hilfe würde geschätzt werden.

Antwort

0

Verschiedene Implementierungen des Gzip-Algorithmus werden immer etwas andere, aber immer noch korrekte Dateien, auch die Komprimierungsstufe der Originaldatei kann anders sein als die, auf der Sie sie ausführen.

2

Soweit ich weiß, können Sie die Komprimierungsstufe einer bereits komprimierten Datei nicht finden.Wenn Sie die Datei komprimieren, können Sie die Datei angeben Komprimierungsstufe mit - #, wobei # von 1 bis 9 ist (1 ist die schnellste Komprimierung und 9 die am stärksten komprimierte Datei). In der Praxis sollten Sie niemals eine komprimierte Datei mit einer extrahierten und rekomprimierten Datei vergleichen, leichte Abweichungen können leicht auftreten. In Ihrem Fall würde ich die Base64-kodierten Versionen anstelle der Gzip-Versionen vergleichen.

0

Interessant, ich gebe es eine Chance. Die Variationen sind jedoch nicht gering. Die neu codierte Datei ist länger und beim Vergleichen der Binärzahlen von Vorher und Nachher stimmen die Daten kaum überein.

Vor (die ersten drei Zeilen)

H4sIAAAAAAAAC+19eZOiyNb3/34K3r4RT/WEU40ssvTtrhuIuKK44Bo3YoJdFAFZ3D79C6hVVhUq 
dsnUVN/qmIkSOLlwlt/JPCfJ/PGf9dwAlorj6pb58wv0LfcFUEzJknVT+/ml2uXuCSJP3kNf/vOQ 
+TEsFVkgoDfdn18mnmd/B8HVavWt5TsKI2vKN8magyENiH3Lf9kRfpd817PmF+jpiOhQRFZcXTMV 

Nach (die ersten drei Zeilen):

H4sICJ/YnEgAAzEyNDQ2LTExNjk2NzUueGZkbC54bWwA7D1pU+JK19/9FV2+H5wpByEhJMRH 
uRUgCMom4DBYt2oqkAZyDQlmQZ1f/3YSNqGzKT3oDH6RdE4vOXuf08vFP88TFcygYSq6dnlM 
naWOAdQGuqxoo8vjSruRyGYzfII6/id3dPGjVKwCBK+Zl8djy5qeJ5NPT09nTduAojyCZwN9 

Wie Sie H4SI Match sehen können, dann nach, dass es Pandämonium.

+0

Aber wenn Sie genau die gleiche gzip-Implementierung verwenden, würden Sie immer nur die H4sI erwarten, dass das gleiche sein. "Pandemonium" ist normal :-) –

1

Sie müssen die folgende Zeile am Anfang der XFDL-Datei setzen:

application/vnd.xfdl; content-encoding="base64-gzip"

Nachdem Sie die Base64-codierte Datei generiert haben, öffnen Sie sie in einem Texteditor und fügen Sie den Zeile oben in der ersten Zeile. Stellen Sie sicher, dass der base64-Block am Anfang der zweiten Zeile beginnt.

Speichern Sie es und versuchen Sie es im Viewer! Wenn es immer noch nicht funktioniert, kann es sein, dass die Änderungen, die an XML vorgenommen wurden, es in gewisser Weise nicht konform gemacht haben. Nachdem der XML-Code geändert wurde, aber bevor er gezippt und base64-codiert wurde, speichern Sie ihn in der Dateierweiterung .xfdl und versuchen Sie, ihn mit dem Viewer-Tool zu öffnen. Der Viewer sollte in der Lage sein, die unkomprimierte/uncodierte Datei zu analysieren und anzuzeigen, wenn sie in einem gültigen XFDL-Format vorliegt.

0

gzip fügt den Dateinamen in den Header der Datei ein, so dass die Länge einer gezippten Datei abhängig vom Dateinamen der unkomprimierten Datei variiert.

Wenn gzip wirkt auf einen Strom, wird der Dateiname weggelassen und die Datei ist etwas kürzer, so sollten folgende Arbeiten:

gzip yourform-unpacked.xml.gz

Dann neu codiert in base64: base64 -e yourform-unpacked.xml.gz yourform_reencoded.xfdl

vielleicht wird dies eine Datei mit der gleichen Länge produziert

1

überprüfen sie diese heraus:

http://www.ourada.org/blog/archives/375

http://www.ourada.org/blog/archives/390

Sie in Python sind, Ruby nicht, aber das sollte man ziemlich nahe kommen.

Und der Algorithmus ist eigentlich für Dateien mit dem Header 'application/x-xfdl; content-encoding = "asc-gzip"' anstatt 'application/vnd.xfdl; content-encoding = "base64-gzip" ' Aber die gute Nachricht ist, dass PureEdge (alias IBM Lotus Forms) dieses Format problemlos öffnen wird.

Dann um das Ganze abzurunden, hier ist ein base64-gzip decode (in Python), so können Sie die volle Rundreise machen:

with open(filename, 'r') as f: 
    header = f.readline() 
    if header == 'application/vnd.xfdl; content-encoding="base64-gzip"\n': 
    decoded = b'' 
    for line in f: 
     decoded += base64.b64decode(line.encode("ISO-8859-1")) 
    xml = zlib.decompress(decoded, zlib.MAX_WBITS + 16) 
+0

(Das ist nicht mein Blog, BTW.) Und Anerkennung für die Magie MAX_WBITS: http://StackOverflow.com/Questions/1838699/How-CanI-Ide-Compress-Agzip-stream -mit-zlib – CrazyPyro

1

ich dies mit Hilfe der Base64-Klasse in Java tat aus http://iharder.net/base64.

Ich habe an einer Anwendung gearbeitet, um die Manipulation von Formularen in Java zu tun. Ich dekodiere die Datei, erstelle ein DOM-Dokument aus dem XML und schreibe es in die Datei zurück.

Mein Code in Java, die Datei zu lesen wie folgt aussieht:

public XFDLDocument(String inputFile) 
     throws IOException, 
      ParserConfigurationException, 
      SAXException 

{ 
    fileLocation = inputFile; 

    try{ 

     //create file object 
     File f = new File(inputFile); 
     if(!f.exists()) { 
      throw new IOException("Specified File could not be found!"); 
     } 

     //open file stream from file 
     FileInputStream fis = new FileInputStream(inputFile); 

     //Skip past the MIME header 
     fis.skip(FILE_HEADER_BLOCK.length()); 

     //Decompress from base 64     
     Base64.InputStream bis = new Base64.InputStream(fis, 
       Base64.DECODE); 

     //UnZIP the resulting stream 
     GZIPInputStream gis = new GZIPInputStream(bis); 

     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder db = dbf.newDocumentBuilder(); 
     doc = db.parse(gis); 

     gis.close(); 
     bis.close(); 
     fis.close(); 

    } 
    catch (ParserConfigurationException pce) { 
     throw new ParserConfigurationException("Error parsing XFDL from file."); 
    } 
    catch (SAXException saxe) { 
     throw new SAXException("Error parsing XFDL into XML Document."); 
    } 
} 

in Java Mein Code sieht wie folgt aus der Datei auf der Festplatte zu schreiben:

/** 
    * Saves the current document to the specified location 
    * @param destination Desired destination for the file. 
    * @param asXML True if output needs should be as un-encoded XML not Base64/GZIP 
    * @throws IOException File cannot be created at specified location 
    * @throws TransformerConfigurationExample 
    * @throws TransformerException 
    */ 
    public void saveFile(String destination, boolean asXML) 
     throws IOException, 
      TransformerConfigurationException, 
      TransformerException 
     { 

     BufferedWriter bf = new BufferedWriter(new FileWriter(destination)); 
     bf.write(FILE_HEADER_BLOCK); 
     bf.newLine(); 
     bf.flush(); 
     bf.close(); 

     OutputStream outStream; 
     if(!asXML) { 
      outStream = new GZIPOutputStream(
       new Base64.OutputStream(
         new FileOutputStream(destination, true))); 
     } else { 
      outStream = new FileOutputStream(destination, true); 
     } 

     Transformer t = TransformerFactory.newInstance().newTransformer(); 
     t.transform(new DOMSource(doc), new StreamResult(outStream)); 

     outStream.flush(); 
     outStream.close();  
    } 

Hoffnung, das hilft.

1

Ich habe an so etwas gearbeitet und das sollte für PHP funktionieren.Sie müssen einen beschreibbaren tmp-Ordner haben und die php-Datei muss den Namen beispiel.php haben!

<?php 
    function gzdecode($data) { 
     $len = strlen($data); 
     if ($len < 18 || strcmp(substr($data,0,2),"\x1f\x8b")) { 
      echo "FILE NOT GZIP FORMAT"; 
      return null; // Not GZIP format (See RFC 1952) 
     } 
     $method = ord(substr($data,2,1)); // Compression method 
     $flags = ord(substr($data,3,1)); // Flags 
     if ($flags & 31 != $flags) { 
      // Reserved bits are set -- NOT ALLOWED by RFC 1952 
      echo "RESERVED BITS ARE SET. VERY BAD"; 
      return null; 
     } 
     // NOTE: $mtime may be negative (PHP integer limitations) 
     $mtime = unpack("V", substr($data,4,4)); 
     $mtime = $mtime[1]; 
     $xfl = substr($data,8,1); 
     $os = substr($data,8,1); 
     $headerlen = 10; 
     $extralen = 0; 
     $extra  = ""; 
     if ($flags & 4) { 
      // 2-byte length prefixed EXTRA data in header 
      if ($len - $headerlen - 2 < 8) { 
       return false; // Invalid format 
       echo "INVALID FORMAT"; 
      } 
      $extralen = unpack("v",substr($data,8,2)); 
      $extralen = $extralen[1]; 
      if ($len - $headerlen - 2 - $extralen < 8) { 
       return false; // Invalid format 
       echo "INVALID FORMAT"; 
      } 
      $extra = substr($data,10,$extralen); 
      $headerlen += 2 + $extralen; 
     } 

     $filenamelen = 0; 
     $filename = ""; 
     if ($flags & 8) { 
      // C-style string file NAME data in header 
      if ($len - $headerlen - 1 < 8) { 
       return false; // Invalid format 
       echo "INVALID FORMAT"; 
      } 
      $filenamelen = strpos(substr($data,8+$extralen),chr(0)); 
      if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) { 
       return false; // Invalid format 
       echo "INVALID FORMAT"; 
      } 
      $filename = substr($data,$headerlen,$filenamelen); 
      $headerlen += $filenamelen + 1; 
     } 

     $commentlen = 0; 
     $comment = ""; 
     if ($flags & 16) { 
      // C-style string COMMENT data in header 
      if ($len - $headerlen - 1 < 8) { 
       return false; // Invalid format 
       echo "INVALID FORMAT"; 
      } 
      $commentlen = strpos(substr($data,8+$extralen+$filenamelen),chr(0)); 
      if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) { 
       return false; // Invalid header format 
       echo "INVALID FORMAT"; 
      } 
      $comment = substr($data,$headerlen,$commentlen); 
      $headerlen += $commentlen + 1; 
     } 

     $headercrc = ""; 
     if ($flags & 1) { 
      // 2-bytes (lowest order) of CRC32 on header present 
      if ($len - $headerlen - 2 < 8) { 
       return false; // Invalid format 
       echo "INVALID FORMAT"; 
      } 
      $calccrc = crc32(substr($data,0,$headerlen)) & 0xffff; 
      $headercrc = unpack("v", substr($data,$headerlen,2)); 
      $headercrc = $headercrc[1]; 
      if ($headercrc != $calccrc) { 
       echo "BAD CRC"; 
       return false; // Bad header CRC 
      } 
      $headerlen += 2; 
     } 

     // GZIP FOOTER - These be negative due to PHP's limitations 
     $datacrc = unpack("V",substr($data,-8,4)); 
     $datacrc = $datacrc[1]; 
     $isize = unpack("V",substr($data,-4)); 
     $isize = $isize[1]; 

     // Perform the decompression: 
     $bodylen = $len-$headerlen-8; 
     if ($bodylen < 1) { 
      // This should never happen - IMPLEMENTATION BUG! 
      echo "BIG OOPS"; 
      return null; 
     } 
     $body = substr($data,$headerlen,$bodylen); 
     $data = ""; 
     if ($bodylen > 0) { 
      switch ($method) { 
       case 8: 
        // Currently the only supported compression method: 
        $data = gzinflate($body); 
        break; 
       default: 
        // Unknown compression method 
        echo "UNKNOWN COMPRESSION METHOD"; 
       return false; 
      } 
     } else { 
      // I'm not sure if zero-byte body content is allowed. 
      // Allow it for now... Do nothing... 
      echo "ITS EMPTY"; 
     } 

     // Verifiy decompressed size and CRC32: 
     // NOTE: This may fail with large data sizes depending on how 
     //  PHP's integer limitations affect strlen() since $isize 
     //  may be negative for large sizes. 
     if ($isize != strlen($data) || crc32($data) != $datacrc) { 
      // Bad format! Length or CRC doesn't match! 
      echo "LENGTH OR CRC DO NOT MATCH"; 
      return false; 
     } 
     return $data; 
    } 
    echo "<html><head></head><body>"; 
    if (empty($_REQUEST['upload'])) { 
     echo <<<_END 
    <form enctype="multipart/form-data" action="example.php" method="POST"> 
    <input type="hidden" name="MAX_FILE_SIZE" value="100000" /> 
    <table> 
    <th> 
    <input name="uploadedfile" type="file" /> 
    </th> 
    <tr> 
    <td><input type="submit" name="upload" value="Convert File" /></td> 
    </tr> 
    </table> 
    </form> 
    _END; 

    } 
    if (!empty($_REQUEST['upload'])) { 
     $file   = "tmp/" . $_FILES['uploadedfile']['name']; 
     $orgfile  = $_FILES['uploadedfile']['name']; 
     $name   = str_replace(".xfdl", "", $orgfile); 
     $convertedfile = "tmp/" . $name . ".xml"; 
     $compressedfile = "tmp/" . $name . ".gz"; 
     $finalfile  = "tmp/" . $name . "new.xfdl"; 
     $target_path = "tmp/"; 
     $target_path = $target_path . basename($_FILES['uploadedfile']['name']); 
     if (move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) { 
     } else { 
      echo "There was an error uploading the file, please try again!"; 
     } 
     $firstline  = "application/vnd.xfdl; content-encoding=\"base64-gzip\"\n"; 
     $data   = file($file); 
     $data   = array_slice($data, 1); 
     $raw   = implode($data); 
     $decoded  = base64_decode($raw); 
     $decompressed = gzdecode($decoded); 
     $compressed  = gzencode($decompressed); 
     $encoded  = base64_encode($compressed); 
     $decoded2  = base64_decode($encoded); 
     $decompressed2 = gzdecode($decoded2); 
     $header   = bin2hex(substr($decoded, 0, 10)); 
     $tail   = bin2hex(substr($decoded, -8)); 
     $header2  = bin2hex(substr($compressed, 0, 10)); 
     $tail2   = bin2hex(substr($compressed, -8)); 
     $header3  = bin2hex(substr($decoded2, 0, 10)); 
     $tail3   = bin2hex(substr($decoded2, -8)); 
     $filehandle  = fopen($compressedfile, 'w'); 
     fwrite($filehandle, $decoded); 
     fclose($filehandle); 
     $filehandle  = fopen($convertedfile, 'w'); 
     fwrite($filehandle, $decompressed); 
     fclose($filehandle); 
     $filehandle  = fopen($finalfile, 'w'); 
     fwrite($filehandle, $firstline); 
     fwrite($filehandle, $encoded); 
     fclose($filehandle); 
     echo "<center>"; 
     echo "<table style='text-align:center' >"; 
     echo "<tr><th>Stage 1</th>"; 
     echo "<th>Stage 2</th>"; 
     echo "<th>Stage 3</th></tr>"; 
     echo "<tr><td>RAW DATA -></td><td>DECODED DATA -></td><td>UNCOMPRESSED DATA -></td></tr>"; 
     echo "<tr><td>LENGTH: ".strlen($raw)."</td>"; 
     echo "<td>LENGTH: ".strlen($decoded)."</td>"; 
     echo "<td>LENGTH: ".strlen($decompressed)."</td></tr>"; 
     echo "<tr><td><a href='tmp/".$orgfile."'/>ORIGINAL</a></td><td>GZIP HEADER:".$header."</td><td><a href='".$convertedfile."'/>XML CONVERTED</a></td></tr>"; 
     echo "<tr><td></td><td>GZIP TAIL:".$tail."</td><td></td></tr>"; 
     echo "<tr><td><textarea cols='30' rows='20'>" . $raw . "</textarea></td>"; 
     echo "<td><textarea cols='30' rows='20'>" . $decoded . "</textarea></td>"; 
     echo "<td><textarea cols='30' rows='20'>" . $decompressed . "</textarea></td></tr>"; 
     echo "<tr><th>Stage 6</th>"; 
     echo "<th>Stage 5</th>"; 
     echo "<th>Stage 4</th></tr>"; 
     echo "<tr><td>ENCODED DATA <-</td><td>COMPRESSED DATA <-</td><td>UNCOMPRESSED DATA <-</td></tr>"; 
     echo "<tr><td>LENGTH: ".strlen($encoded)."</td>"; 
     echo "<td>LENGTH: ".strlen($compressed)."</td>"; 
     echo "<td>LENGTH: ".strlen($decompressed)."</td></tr>"; 
     echo "<tr><td></td><td>GZIP HEADER:".$header2."</td><td></td></tr>"; 
     echo "<tr><td></td><td>GZIP TAIL:".$tail2."</td><td></td></tr>"; 
     echo "<tr><td><a href='".$finalfile."'/>FINAL FILE</a></td><td><a href='".$compressedfile."'/>RE-COMPRESSED FILE</a></td><td></td></tr>"; 
     echo "<tr><td><textarea cols='30' rows='20'>" . $encoded . "</textarea></td>"; 
     echo "<td><textarea cols='30' rows='20'>" . $compressed . "</textarea></td>"; 
     echo "<td><textarea cols='30' rows='20'>" . $decompressed . "</textarea></td></tr>"; 
     echo "</table>"; 
     echo "</center>"; 
    } 
    echo "</body></html>"; 
    ?>