Как я могу кодировать XML-файлы в xfdl (base64-gzip)?

Прежде чем читать что-либо еще, пожалуйста, найдите время, чтобы прочитать оригинальную ветку .

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

xfdl> xml.gz> xml> xml.gz> xfdl

Я смог взять файл .xfdl и расшифровать его из base64 с помощью uudeview:

uudeview -i yourform.xfdl

Затем распаковал его с помощью gunzip

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

Созданный XML-файл читается на 100% и выглядит великолепно. Не изменяя затем xml, я смогу снова сжать его, используя gzip:

gzip yourform-unpacked.xml

Затем перекодируем в base-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 программе просмотра. Программа просмотра сообщает, что перекодированный xfdl не читается.

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

9.08.2008 15:20:45
8 ОТВЕТОВ

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

0
9.08.2008 15:57:40

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

2
9.08.2008 16:56:56

Интересно, я сделаю это. Однако различия не незначительны. Недавно закодированный файл длиннее, и при сравнении двоичных файлов до и после данные почти не совпадают.

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

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
7.02.2016 17:58:52
Но если вы не используете точно такую ​​же реализацию gzip, вы всегда ожидаете, что H4sI будет таким же. «Пандемониум» нормальный :-)
Rory Alsop 29.03.2011 08:04:11

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

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

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

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

1
7.02.2016 17:57:57

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

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

gzip yourform-unpacked.xml.gz

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

может быть, это даст файл одинаковой длины

0
8.10.2009 19:28:39

Проверьте это:

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

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

Они на Python, а не на Ruby, но это должно вас довольно близко познакомить.

И алгоритм на самом деле для файлов с заголовком '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)
1
16.02.2011 20:43:17
(Это не мой блог, кстати.) И заслуга в этом волшебстве MAX_WBITS: stackoverflow.com/questions/1838699/…
CrazyPyro 16.02.2011 21:49:59

Я сделал это на 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
28.03.2011 22:46:01

Я работал над чем-то вроде этого, и это должно работать для 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>";
    ?>
1
17.01.2012 22:57:27