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

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

Обзор: файл .xfdl - это файл .xml, сжатый в формате gzip, который затем был закодирован в 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, он также дает те же результаты. Любая помощь будет оценена по достоинству.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
6 239
8

Ответы 8

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

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

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

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

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

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

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

Как вы можете видеть, соответствие H4SI, то после этого наступает ад.

Но если вы не используете точно такую ​​же реализацию gzip, можно ожидать, что H4sI будет таким же. «Пандемониум» это нормально :-)

Rory Alsop 29.03.2011 12:04

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

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

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

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

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

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

gzip yourform-unpacked.xml.gz

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

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

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

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)

(Кстати, это не мой блог.) И кредит на магию MAX_WBITS: stackoverflow.com/questions/1838699/…

CrazyPyro 17.02.2011 00:49

Я сделал это на 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();      
    }

Надеюсь, это поможет.

Я работал над чем-то подобным, и это должно работать для 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>";
    ?>

Другие вопросы по теме