2008-08-09 3 views
2

Перед чтением чего-нибудь еще, пожалуйста, найдите время, чтобы прочитать original thread.Как я могу кодировать xml-файлы в xfdl (base64-gzip)?

Обзор: Файл .xfdl представляет собой gzipped .xml-файл, который затем был закодирован в base64. Я хочу де-кодировать .xfdl в xml, который затем могу изменить, а затем снова перекодировать обратно в файл .xfdl.

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

Я был в состоянии взять .xfdl файл и де-закодировать его от base64 с помощью uudeview:

uudeview -i yourform.xfdl 

Тогда decommpressed его с помощью Gunzip

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

XML-производства является 100% читаемым и выглядит замечательно. Без изменения XML-то, я должен быть в состоянии повторно сжать его с помощью GZIP:

gzip yourform-unpacked.xml 

Затем повторно закодированный в базовой 64:

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

Если мое мышление является правильным, оригинальный файл и перекодированный файл должен быть равен. Однако, если я поместил yourform.xfdl и yourform_reencoded.xfdl в сравнение, они не совпадают. Кроме того, исходный файл можно просмотреть в http://www.grants.gov/help/download_software.jsp#pureedge">.xfdl viewer. Зритель говорит, что перекодированное xfdl нечитаемо.

I также пытались переустановить uuenview в base64, он также дает те же результаты. Любая помощь будет оценена.

ответ

0

Различные реализации алгоритма gzip всегда будут производить несколько разные, но все же правильные файлы, а также уровень сжатия исходный файл может отличаться от того, на котором вы его используете.

2

Насколько я знаю, вы не можете найти уровень сжатия уже сжатого файла. Когда вы сжимаете файл, вы можете указать уровень сжатия - #, где # - от 1 до 9 (1 - самое быстрое сжатие, а 9 - самый сжатый файл). На практике вы никогда не должны сравнивать сжатый файл с тем, который был извлечен и повторно сжат, небольшие изменения могут легко возникать. В вашем случае я бы сравнил версии с кодировкой base64 вместо версий gzip'd.

0

Интересно, я сделаю снимок. Однако вариации незначительны. Заново закодированный файл длиннее, и при сравнении двоичного файла до и после данные почти не совпадают.

До (первые три строки)

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

После (первые три строки):

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

Как вы можете видеть H4SI совпадают, то после столпотворения, что это.

+0

Но если вы не используете точно такую ​​же реализацию gzip, вы бы только ожидали, что H4sI будет таким же. «Pandemonium» - это нормально :-) – 2011-03-29 08:04:11

1

Вам нужно поместить следующую строку в начало файла XFDL:

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

После того как вы сформировали base64-кодировке, откройте его в текстовом редакторе и вставьте выше на первой строке. Убедитесь, что блок base64 запускается в начале второй строки.

Сохраните его и попробуйте в окне просмотра! Если он все еще не работает, возможно, что изменения, внесенные в XML, сделали его некорректным. В этом случае после того, как XML был изменен, но до того, как он был закодирован gzipped и base64, сохраните его с расширением файла .xfdl и попробуйте открыть его с помощью средства Viewer. Зритель должен иметь возможность анализировать и отображать несжатый/незарегистрированный файл, если он находится в допустимом формате XFDL.

0

gzip поместит имя файла в заголовок файла, так что файл с расширением gzipped будет меняться по длине в зависимости от имени файла несжатого файла.

Если GZIP действует на поток, имя файла опущено и файл немного короче, так что должно работать:

GZIP yourform-unpacked.xml.gz

Затем перекодируется в base64: base64 -e yourform-unpacked.xml.gz yourform_reencoded.xfdl

возможно это произведет файл такой же длины

1

Проверить их:

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

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

Они в Python, не рубин, но вы должны получить довольно близко.

И алгоритм на самом деле предназначен для файлов с заголовком 'application/x-xfdl; content-encoding = "asc-gzip"', а не 'application/vnd.xfdl; content-encoding = "base64-gzip" ' Но хорошей новостью является то, что PureEdge (иначе IBM Lotus Forms) откроет этот формат без проблем.

Затем в довершение, вот base64-GZIP декодирования (в Python), так что вы можете сделать полный туда-обратно:

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

(Это не мой блог, BTW.) И кредит для этой магии MAX_WBITS: http://stackoverflow.com/questions/1838699/how-can-i-decompress-a-gzip-stream -с-Zlib – CrazyPyro 2011-02-16 21:49:59

1

Я сделал это в Java с помощью класса Base64 из http://iharder.net/base64.

Я работаю над приложением, чтобы манипулировать формами на Java. Я декодирую файл, создаю документ DOM из XML, а затем записываю его обратно в файл.

Мой код в Java, чтобы прочитать файл выглядит следующим образом:

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."); 
    } 
} 

Мой код в Java выглядит так, чтобы записать файл на диск:

/** 
    * 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();  
    } 

Надежда, что помогает.

1

Я работал над чем-то подобным, и это должно работать на php.У вас должна быть доступная для записи папка tmp, а файл php - example.php!

<?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>"; 
    ?> 
Смежные вопросы