Cum pot codifica fișiere xml la xfdl (base64-gzip)?

Înainte de a citi orice altceva, vă rugăm să faceți timp pentru a citi firul original .

Prezentare generală: un fișier .xfdl este un fișier .xml gzipped care a fost apoi codificat în baza64. Vreau să dezactivați codul .xfdl în xml, pe care apoi îl pot modifica și apoi re-codifica înapoi într-un fișier .xfdl.

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

Am fost capabil să ia un fișier .xfdl și să îl codifică de la base64 folosind uudeview:

uudeview -i yourform.xfdl

Apoi a decomprimat-o folosind gunzip

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

Xml produs este 100% lizibil și arată minunat. Fără modificarea xml-ului, atunci ar trebui să reușesc să îl recomprim folosind gzip:

gzip yourform-unpacked.xml

Apoi re-codat în baza 64:

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

If my thinking is correct, the original file and the re-encoded file should be equal. If I put yourform.xfdl and yourform_reencoded.xfdl into beyond compare, however, they do not match up. Also, the original file can be viewed in an http://www.grants.gov/help/download_software.jsp#pureedge">.xfdl viewer. The viewer says that the re-encoded xfdl is unreadable.

Am încercat, de asemenea, uuenview pentru a re-codifica în base64, de asemenea, produce aceleași rezultate. Orice ajutor ar fi apreciat.

0
fr hi bn

8 răspunsuri

Interesant, o să fac o lovitură. Variațiile nu sunt însă ușoare. Fișierul nou codificat este mai lung și când se compară binarul dintre înainte și după, datele nu se potrivesc aproape deloc.

Înainte (primele trei linii)

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

După (primele trei linii):

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

După cum puteți vedea codul H4SI se potrivesc, atunci după aceea este pandemoniu.

0
adăugat
Dar dacă nu utilizați exact aceeași implementare gzip, v-ați aștepta vreodată ca H4sI să fie același. "Pandemonium" este normal :-)
adăugat autor Rory Alsop, sursa

Diferitele implementări ale algoritmului gzip vor produce fișiere ușor diferite, dar totuși corecte, de asemenea, nivelul de compresie al fișierului original poate fi diferit de cel pe care îl executați.

0
adăugat

Din câte știu, nu puteți găsi nivelul de comprimare al unui fișier deja comprimat. Când comprimați fișierul, puteți specifica nivelul de compresie cu - # unde # este de la 1 la 9 (1 este cea mai rapidă comprimare și 9 este cel mai comprimat fișier). În practică, nu ar trebui să comparați niciodată un fișier comprimat cu unul care a fost extras și recomprimat, ușoarele variații pot apărea cu ușurință în sus. În cazul tău, aș compara versiunile codate de base64 în loc de versiunile gzip'd.

0
adăugat

Va trebui să introduceți următoarea linie la începutul fișierului XFDL:

application / vnd.xfdl; conținut-codare = "base64-gzip"

După ce ați generat fișierul codat base64, deschideți-l într-un editor de text și inserați linia de mai sus pe primul rând. Asigurați-vă că blocul base64'ed începe la începutul liniei a doua.

Salvați-l și încercați-l în Vizualizator! Dacă tot nu funcționează, este posibil ca modificările făcute în xml să o facă neconformă într-un anumit mod. În acest caz, după ce XML-ul a fost modificat, dar înainte de a fi codificat gzipped și base64, salvați-l cu o extensie de fișier .xfdl și încercați să îl deschideți cu instrumentul Viewer. Vizualizatorul ar trebui să poată analiza și afișa fișierul necomprimat / necriptat dacă este într-un format XFDL valid.

0
adăugat

gzip va pune numele fișierului în antetul fișierului, astfel încât un fișier gzipp să aibă o lungime diferită, în funcție de numele fișierului fișierului necomprimat.

Dacă gzip acționează pe un flux, numele fișierului este omis și fișierul este puțin mai scurt, deci ar trebui să funcționeze următoarele:

gzip yourform-unpacked.xml.gz

Apoi re-codat în baza 64: base64 -e yourform-unpacked.xml.gz yourform_reencoded.xfdl

poate că aceasta va produce un fișier de aceeași lungime

0
adăugat

Verificați aceste:

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

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

Ei sunt în Python, nu Ruby, dar asta ar trebui să te apropie destul de mult.

Și algoritmul este de fapt pentru fișiere cu antet "application / x-xfdl; content-encoding =" asc-gzip "'în loc de' application / vnd.xfdl; conținut-codare = "base64-gzip"“ Dar vestea bună este că PureEdge (aka IBM Lotus Forms) va deschide acest format fără probleme.

Apoi, la început, este o decodare base64-gzip (în Python) pentru a putea face o plimbare completă:

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
adăugat
(Acesta nu este blogul meu, BTW.) Și creditul pentru acea magie MAX_WBITS: stackoverflow.com/questions/1838699/…
adăugat autor CrazyPyro, sursa

Am făcut acest lucru în Java cu ajutorul clasei Base64 de la http://iharder.net/base64 .

Am lucrat la o aplicație pentru a face manipulare în Java. Decodez fișierul, creez un document DOM din xml apoi îl scriu înapoi în fișier.

Codul meu în Java pentru a citi fișierul arată astfel:

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

Codul meu în java arată astfel pentru a scrie fișierul pe disc:

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

Sper că vă ajută.

0
adăugat

Am lucrat la ceva de genul asta și acest lucru ar trebui să funcționeze pentru php. Trebuie să aveți un folder tmp care poate fi scris și fișierul PHP să fie numit 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 "
"; 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>ORIGINAL</td><td>GZIP HEADER:".$header."</td><td>XML CONVERTED</td></tr>"; echo "<tr><td></td><td>GZIP TAIL:".$tail."</td><td></td></tr>"; echo "<tr><td></td>"; echo "<td></td>"; echo "<td></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>FINAL FILE</td><td>RE-COMPRESSED FILE</td><td></td></tr>"; echo "<tr><td></td>"; echo "<td></td>"; echo "<td></td></tr>"; echo "</table>"; echo "
"; } echo "</body></html>"; ?>
0
adăugat