Frage

Hoffentlich haben Sie die ordentlich Hack , die Sie kombinieren, um ein JPG und eine Zip-Datei in eine einzige Datei und es ist eine gültige (oder zumindest lesbar) Datei für beiden Formate können. Nun, ich erkennen, dass da JPG beliebiges Material am Ende läßt und ZIP am Anfang, Sie ein weiteres Format in dort bleiben konnten - in der Mitte. Für die Zwecke dieser Frage übernimmt die mittleren Daten guarenteed nicht beliebige binäre Daten mit dem JPG oder ZIP-Formate in Konflikt geraten (was bedeuten, es nicht den magischen zip-Header enthält 0x04034b50). Illustration:

0xFFD8 <- start jpg data end -> 0xFFD9 ... ARBITRARY BINARY DATA ... 0x04034b50 <- start zip file ... EOF

Ich bin catting wie folgt aus:

  

cat "mss_1600.jpg" filea FILEB   filea FILEB filea FILEB filea   FILEB filea FILEB filea FILEB filea   FILEB filea FILEB filea FILEB filea   FILEB filea FILEB filea FILEB filea   FILEB "null.bytes"   "Randomzipfile.zip"> temp.zip

Dies erzeugt eine 6318 KB Datei. Es nicht , öffnet in 7-Zip. Allerdings, wenn ich Katze eine weniger 'doppelte' (so statt 13 filea und bs, 12):

  

cat "mss_1600.jpg" filea FILEB   filea FILEB filea FILEB filea   FILEB filea FILEB filea FILEB filea   FILEB filea FILEB filea FILEB filea   FILEB filea FILEB filea FILEB   "Null.bytes" "randomzipfile.zip">   temp.zip

Es produziert eine 5.996 KB-Datei, die funktioniert , öffnet in 7-Zip.

So weiß ich meine beliebigen binären Daten nicht den Magie Zip Datei-Header haben es vermasseln. Ich habe Referenzdateien des Arbeits jpg + Daten + zip und die nicht-Arbeits jpg + Daten + zip (save-als Ursache der Browser sie sind Bilder denkt, und fügen sie die zip Erweiterungen selbst).

Ich möchte wissen, warum es mit 13 Kombinationen versagt und nicht mit 12. Für Bonuspunkte, ich brauche irgendwie, dies zu umgehen.

War es hilfreich?

Lösung

Eigentlich ist es eine zweiteilige Antwort wirklich :)

Zum einen, egal, was die Leute sagen, zip-Dateien können nicht technisch am Ende der Dateien gesetzt wörtlich werden. Das Ende des zentralen Verzeichniseintrags hat einen Wert, der das Byte vom Beginn der aktuellen Platte Offset gibt (wenn Sie nur eine ZIP-Datei, das bedeutet, dass die aktuelle Datei). Jetzt ignoriert Menge Prozessoren dies, obwohl Windows-Zip-Ordner nicht so müssen Sie diesen Wert korrigieren, um es in Windows-Explorer funktioniert (nicht, dass Sie vielleicht interessieren; P) Siehe Zip appNote für Informationen über das Dateiformat. Grundsätzlich finden Sie in einem Hex-Editor (oder ein Werkzeug schreiben), um den „Offset des Beginns des zentralen Verzeichnisses in Bezug auf die Startplattennummer“ Wert zu finden. Dann finden Sie die erste „zentrale Datei-Header-Signatur“ (hex von 504b0102) und legen Sie den Wert, dass gegenüber.

Nun leider, dass nicht 7zip nicht beheben, aber das ist aufgrund der Art und Weise 7zip das Dateiformat zu erraten versucht. Grundsätzlich wird es nur suchen, die erste ~ 4MiB für die binäre Folge 504B0304, wenn sie nicht finden, dass es nimmt es nicht Zip ist und versucht, seine anderen Archiv-Formate. Dies ist offensichtlich, warum das Hinzufügen einer weiteren Datei Dinge bricht, es schiebt es über die Grenze für die Suche.

Nun, es zu beheben, was Sie tun müssen, ist auf die jpeg, dass Hex-String hinzufügen, ohne es zu brechen. Eine Möglichkeit, dies zu tun, ist hinzuzufügen, kurz nach der FFD8 JPEG SOI-Header der folgenden Hex-Daten, FFEF0005504B030400. Das fügt einen benutzerdefinierten Block mit Ihrer Sequenz und ist richtig so jpeg Header sollte es einfach ignorieren.

Andere Tipps

heruntergeladen ich die Quelle für 7-Zip und herausgefunden, was dies geschieht verursacht.

In CPP / 7zip / UI / Common / OpenArchive.cpp, sehen Sie wie folgt vor:

// Static-SFX (for Linux) can be big.
const UInt64 kMaxCheckStartPosition = 1 << 22;

Das bedeutet, dass nur der erste 4194304 Bytes der Datei für den Header gesucht werden. Wenn es dort nicht gefunden wird, 7-Zip hält es für eine ungültige Datei.

Sie können diese Grenze verdoppeln, indem 1 << 22 zu 1 << 23 ändern. Getestet habe ich diese Änderung durch den Umbau 7-Zip und es funktioniert.

Bearbeiten : Um dieses Problem zu erhalten, können Sie , machen die obige Änderung, und es bauen. Ich baute es VS 2008. Öffnen Sie die VS Eingabeaufforderung, navigieren Sie zu extrahiert-Source-Standort \ CPP \ 7zip \ Bundles und geben Sie 'nmake'. Dann im Allein Verzeichnis run ‚7za t nonworking.jpg‘ und Sie sollten sehen, ‚Alles ist in Ordnung.‘

Also für jemanden anderen diese Frage zu finden, hier ist die Geschichte:

Ja, Andy ist buchstäblich richtig, warum 7-Zip auf die Datei fehlschlägt, aber es hat mein Problem nicht helfen, da ich nicht genau können die Menschen bekommen meine Version von 7-Zip zu verwenden.

Tyraniden aber hat mir die Lösung.

  • Zunächst einmal, eine kleine bytestring zum JPG Hinzufügen wie er läßt schlägt vor, 7-Zip öffnen. Es ist jedoch leicht von einem gültigen JPG-Fragmente aus, muss es FFEF00 07 504B030400 sein - die Länge war weg von 2 Bytes
  • .
  • Auf diese Weise kann 7-Zip öffnen, aber keine Dateien extrahieren, es nicht still. Dies liegt daran, dass die Einträge im zentralen Verzeichnis haben interne Zeiger / Offsets, die für den Eintrag der Datei verweisen. Da Sie ein paar Sachen vor, dass setzen, müssen Sie alle diese Hinweise korrigieren!
  • zip-Archiv hat offen mit Windows im Zip-Unterstützung gebaut, müssen Sie, wie Tyraniden sagt, der „Offset des Beginns des zentralen Verzeichnisses in Bezug auf die Startplattennummer“ korrigieren. Hier ist ein Python-Skript, die letzten beiden zu tun, obwohl es ein Fragment ist, nicht Copypasta-ready-to-use

#Now we need to read the file and rewrite all the zip headers.  Fun!
torewrite = open(magicfilename, 'rb')
magicdata = torewrite.read()
torewrite.close()

#Change the Central Repository's Offset
offsetOfCentralRepro = magicdata.find('\x50\x4B\x01\x02') #this is the beginning of the central repo
start = len(magicdata) - 6 #it so happens, that on my files, the point is stored 2 bytes from the end.  so datadatadatdaata OF FS ET !! 00 00 EOF where OFFSET!! is the 4 bytes 00 00 are the last two bytes, then EOF
magicdata = magicdata[:start] + pack('I', offsetOfCentralRepro) + magicdata[start+4:]

#Now change the individual offsets in the central directory files
startOfCentralDirectoryEntry = magicdata.find('\x50\x4B\x01\x02', 0) #find the first central directory entry
startOfFileDirectoryEntry = magicdata.find('\x50\x4B\x03\x04', 10) #find the first file entry (we start at 10 because we have to skip past the first fake entry in the jpg)
while startOfCentralDirectoryEntry > 0:
    #Now I move a magic number of bytes past the entry (really! It's 42!)
    startOfCentralDirectoryEntry = startOfCentralDirectoryEntry + 42

    #get the current offset just to output something to the terminal
    (oldoffset,) = unpack('I', magicdata[startOfCentralDirectoryEntry : startOfCentralDirectoryEntry+4])
    print "Old Offset: ", oldoffset, " New Offset: ", startOfFileDirectoryEntry , " at ", startOfCentralDirectoryEntry
    #now replace it
    magicdata = magicdata[:startOfCentralDirectoryEntry] + pack('I', startOfFileDirectoryEntry) + magicdata[startOfCentralDirectoryEntry+4:]

    #now I move to the next central directory entry, and the next file entry
    startOfCentralDirectoryEntry = magicdata.find('\x50\x4B\x01\x02', startOfCentralDirectoryEntry)
    startOfFileDirectoryEntry = magicdata.find('\x50\x4B\x03\x04', startOfFileDirectoryEntry+1)

#Finally write the rewritten headers' data
towrite = open(magicfilename, 'wb')
towrite.write(magicdata)
towrite.close()

Sie können hybrid JPG + ZIP-Dateien erzeugen mit DotNetZip . DotNetZip kann zu einem Strom sparen, und es ist intelligent genug, um das Original zu erkennen Offset eines bereits bestehenden Stromes, bevor es zip Inhalt in sie beginnt zu schreiben. Daher in Pseudo-Code, können Sie eine JPG erhalten + ZIP auf diese Weise:

 open stream on an existing JPG file for update
 seek to the end of that stream
 open or create a zip file
 call ZipFile.Save to write zip content to the JPG stream
 close

Alle sind die Offsets korrekt abgebildet. Dieselbe Technik wird verwendet, um ein selbstextrahierendes Archiv zu erzeugen. Sie können den Stream auf der EXE öffnen, dann bis zum Ende suchen, und zu diesem Strom die ZIP-Inhalte schreiben. Alle Offsets korrekt berechnet, wenn Sie es auf diese Weise tun.

Ein andere Sache - in Bezug auf eine der Kommentare in einem anderen Beitrag ... ZIP kann am Anfang beliebige Daten hat und am Ende der Datei. Es gibt keine Anforderung, soweit ich weiß, dass der Reißverschluss zentrale Verzeichnis am Ende der Datei sein muss, aber das ist typisch.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top