Domanda

Spero che tu abbia sentito parlare di neat hack che ti consente di combinare un file JPG e un file Zip in un singolo file ed è un file valido (o almeno leggibile) per entrambi i formati. Bene, mi sono reso conto che dal momento che JPG lascia alla fine cose arbitrarie e ZIP all'inizio, potresti inserire un altro formato lì - nel mezzo. Ai fini di questa domanda, supponiamo che i dati intermedi siano dati binari arbitrari garantiti per non entrare in conflitto con i formati JPG o ZIP (il che significa che non contiene l'intestazione zip magica 0x04034b50). Illustrazione:

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

Sto catturando in questo modo:

  

cat " mss_1600.jpg " file fileab   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 "   quot &; & randomzipfile.zip quot; gt &; temp.zip

Questo produce un file di 6.318 KB. non si apre in 7-Zip. Tuttavia, quando gatto uno in meno "doppio" (quindi invece di 13 filea eb, 12):

  

cat " mss_1600.jpg " file fileab   filea fileb filea fileb filea   fileb filea fileb filea fileb filea   fileb filea fileb filea fileb filea   fileb filea fileb filea fileb   quot &; & null.bytes quot; quot &; & randomzipfile.zip quot; gt &;   temp.zip

Produce un file da 5.996 KB che si apre in 7-Zip.

Quindi so che i miei dati binari arbitrari non hanno l'intestazione del file zip magico per rovinarli. Ho file di riferimento di jpg + dati + zip funzionanti e jpg + dati + zip non funzionanti (salva-perché il browser pensa che siano immagini e aggiungi il estensioni zip da soli).

Voglio sapere perché fallisce con 13 combinazioni e non con 12. Per i punti bonus, devo aggirarlo in qualche modo.

È stato utile?

Soluzione

In realtà è una risposta in due parti davvero :)

In primo luogo, indipendentemente da ciò che la gente dice, i file zip non possono tecnicamente essere messi alla fine dei file. La fine del record della directory centrale ha un valore che indica l'offset di byte dall'inizio del disco corrente (se si dispone di un solo file .zip, significa che il file corrente). Ora molti processori lo ignorano, sebbene la cartella zip di Windows non lo faccia, quindi è necessario correggere quel valore per farlo funzionare in Windows Explorer (non che ti interessi; P) Vedi Zip APPNOTE per informazioni sul formato del file. Fondamentalmente si trova in un editor esadecimale (o si scrive uno strumento) per trovare & Quot; offset dell'inizio della directory centrale rispetto al numero del disco iniziale & Quot; valore. Quindi trova la prima & Quot; firma dell'intestazione del file centrale & Quot; (esadecimale di 504b0102) e imposta il valore su quell'offset.

Ora purtroppo non risolve 7zip ma ciò è dovuto al modo in cui 7zip tenta di indovinare il formato del file. Fondamentalmente cercherà solo la prima ~ 4MiB per la sequenza binaria 504b0304, se non la trova presuppone che non sia Zip e prova i suoi altri formati di archivio. Questo è ovviamente il motivo per cui l'aggiunta di un altro file rompe le cose, lo spinge oltre il limite per la ricerca.

Ora, per risolverlo, ciò che devi fare è aggiungere quella stringa esadecimale al jpeg senza romperla. Un modo per farlo è quello di aggiungere subito dopo l'intestazione SOI JPEG FFD8 i seguenti dati esadecimali, FFEF0005504B030400. Ciò aggiunge un blocco personalizzato con la sequenza ed è corretto, quindi le intestazioni jpeg dovrebbero semplicemente ignorarlo.

Altri suggerimenti

Ho scaricato la fonte per 7-Zip e ho capito cosa sta causando questo.

In CPP / 7zip / UI / Common / OpenArchive.cpp, vedrai quanto segue:

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

Ciò significa che verranno cercati solo i primi 4194304 byte del file per l'intestazione. Se non viene trovato lì, 7-Zip lo considera un file non valido.

Puoi raddoppiare quel limite cambiando 1 << 22 in 1 << 23. Ho provato quella modifica ricostruendo 7-Zip e funziona.

MODIFICA : per aggirare questo problema, puoi scaricare la fonte , apporta la modifica sopra e creala. L'ho creato usando VS 2008. Apri il prompt dei comandi di VS, vai a extracted-source-location \ CPP \ 7zip \ Bundles e digita 'nmake'. Quindi nella directory Alone esegui "7za t nonworking.jpg" e dovresti vedere "Tutto ok".

Quindi per chiunque trovi questa domanda, ecco la storia:

Sì, Andy ha letteralmente ragione sul motivo per cui 7-Zip non riesce nel file, ma non aiuta il mio problema poiché non riesco proprio a convincere la gente a usare la MIA versione di 7-Zip.

il tiranide mi ha comunque fornito la soluzione.

  • Prima di tutto, aggiungendo un piccolo bytestring al JPG poiché suggerisce che 7-Zip lo aprirà. Tuttavia, è leggermente diverso da un frammento JPG valido, deve essere FFEF00 07 504B030400 - la lunghezza era fuori di 2 byte.
  • Questo consente a 7-Zip di aprirlo, ma non estrarre i file, non riesce in silenzio. Questo perché le voci nella directory centrale hanno puntatori / offset interni che puntano alla voce del file. Dato che hai messo un sacco di cose prima, devi correggere tutti quei puntatori!
  • Per aprire la zip con il supporto per zip incorporato di Windows, è necessario, come dice Tyranid, correggere " offset dell'inizio della directory centrale rispetto al numero del disco iniziale " ;. Ecco uno script Python per fare gli ultimi due, sebbene sia un frammento, non copypasta pronto per l'uso

#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()

Puoi produrre file JPG + ZIP ibridi usando DotNetZip . DotNetZip può salvare su un flusso ed è abbastanza intelligente da riconoscere l'offset originale di un flusso preesistente prima che inizi a scrivere il contenuto zip in esso. Pertanto nello pseudo codice, puoi ottenere un JPG + ZIP in questo modo:

 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

Tutti gli offset sono calcolati correttamente. La stessa tecnica viene utilizzata per produrre un archivio autoestraente. Puoi aprire lo stream su EXE, quindi cercare fino alla fine e scrivere il contenuto ZIP su quello stream. Tutti gli offset vengono calcolati correttamente se lo fai in questo modo.

Un'altra cosa - per quanto riguarda uno dei commenti in un altro post ... ZIP può avere dati arbitrari all'inizio e alla fine del file. Non è necessario per quanto ne so che la directory centrale zip deve trovarsi alla fine del file, sebbene ciò sia tipico.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top