Pergunta

Esperamos que você já ouviu falar do puro hack que permite combinar um JPG e um arquivo Zip em um único arquivo e é um arquivo válido (ou pelo menos legível) para ambos os formatos. Bem, eu percebi que desde JPG permite coisas arbitrária no final e CEP no início, você poderia ficar mais um formato de lá - no meio. Para efeitos da presente pergunta, assuma os dados do meio é arbitrária dados binários guarenteed não entrar em conflito com o JPG ou ZIP formatos (o que significa que não contém o cabeçalho zip mágica 0x04034b50). Ilustração:

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

Estou catting assim:

cat "mss_1600.jpg" fileb fileA 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

Isso produz um arquivo de 6.318 KB. É não aberto no 7-Zip. No entanto, quando um gato menos 'duplo' (assim, em vez de 13 fileA e b de, 12):

cat "mss_1600.jpg" fileb fileA 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

Ele produz um arquivo de 5.996 KB que não aberto no 7-Zip.

Então, eu sei que meus dados binários arbitrários não tem a magia Zip cabeçalho do arquivo para estragar tudo. Tenho arquivos de referência do trabalhando jpg + dados + zip e não-trabalho jpg + dados + zip (guardar como causa o navegador acha que eles são imagens, e adicione o zip extensões você mesmo).

Eu quero saber por que ele falha com 13 combinações e não faz com 12. Para pontos de bônus, eu preciso contornar isso de alguma forma.

Foi útil?

Solução

Na verdade, é uma resposta de duas partes realmente :)

Em primeiro lugar não importa o que as pessoas dizem arquivos zip não pode tecnicamente ser colocado na íntegra no final de arquivos. O fim do registo diretório central tem um valor que indica o deslocamento do início do disco atual byte (se você tiver apenas um arquivo .zip, isso significa que o arquivo atual). Agora um monte de processadores ignorar este, embora o Windows' feche pasta não faz isso que você precisa para corrigir o valor para fazê-lo funcionar no Windows Explorer (não que você pode cuidar; P) See Zip appnote para obter informações sobre o formato de arquivo. Basicamente você encontrar em um editor hexadecimal (ou escrever uma ferramenta) para encontrar o "offset do início do diretório central em relação ao número de disco de partida" de valor. Em seguida, localize o primeiro "assinatura cabeçalho do arquivo central" (hex de 504b0102) e defina o valor para esse deslocamento.

Agora, infelizmente isso não corrigir 7zip mas isso é devido à forma como 7zip tenta adivinhar o formato de arquivo. Basicamente, ele só irá procurar o primeiro 4MiB ~ para a seqüência binária 504b0304, se não encontrá-lo ele assume que não é Zip e tenta seus outros formatos de arquivo. Esta é, obviamente, porque a adição de um mais quebras de arquivo coisas, ele empurra-lo sobre o limite para a pesquisa.

Agora, para corrigi-lo o que você precisa fazer é adicionar essa string hex ao jpeg sem quebrá-lo. Uma maneira de fazer isso é adicionar logo após o cabeçalho FFD8 JPEG SOI os seguintes dados hexadecimais, FFEF0005504B030400. Que adiciona um bloco personalizado com a sua sequência e é correto para cabeçalhos jpeg deve simplesmente ignorá-la.

Outras dicas

Eu baixei a fonte para 7-Zip e descobri o que está causando isso aconteça.

Em CPP / 7zip / UI / Common / OpenArchive.cpp, você verá o seguinte:

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

Isso significa que apenas os primeiros 4194304 bytes do arquivo será procurado o cabeçalho. Se não for encontrado ali, 7-Zip considera um arquivo inválido.

Você pode duplicar esse limite, alterando 1 << 22 para 1 << 23. Eu testei essa mudança reconstruindo 7-Zip e ele funciona.

Editar : Para contornar esse problema, você pode baixar o código fonte , fazer a mudança acima, e construí-lo. Eu construí-lo usando o comando VS 2008. Abra o VS pronta, vá para extraído-source-localização \ CPP \ 7zip \ Pacotes e tipo 'nmake'. Em seguida, no Sozinho prazo diretório '7za t nonworking.jpg' e você deve ver 'tudo está OK'.

Assim, para qualquer outra pessoa encontrar esta pergunta, aqui está a história:

Sim, Andy é literalmente correta a respeito de porque o 7-Zip está a falhar no arquivo, mas isso não ajuda o meu problema desde que eu não pode obter exatamente as pessoas a usar a minha versão do 7-Zip.

Tyranid no entanto tem-me a solução.

  • Em primeiro lugar, adicionando uma pequena bytestring ao JPG como ele sugere permitirá que 7-Zip abri-lo. No entanto, é um pouco fora de um fragmento JPG válido, ele precisa ser FFEF00 07 504B030400 -. O comprimento estava fora por 2 bytes
  • Isso permite que 7-Zip abri-lo, mas não extrair arquivos, ele falha silenciosamente. Isso ocorre porque as entradas no diretório central tem ponteiros / deslocamentos internos que apontam para a entrada do arquivo. Desde que você colocar um monte de coisas antes disso, você precisa corrigir todos esses ponteiros!
  • Para que o ZIP aberto com o Windows construído em zip suporte, você precisa, como Tyranid diz, corrigir o "deslocamento do início do diretório central em relação ao número de disco de partida". Aqui está um script python para fazer os dois últimos, embora seja um fragmento, não 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()

Você pode produzir híbridos JPG + ZIP arquivos usando DotNetZip . DotNetZip pode salvar a um fluxo, e é bastante inteligente para reconhecer o deslocamento de um fluxo pré-existente original antes de começar a escrever o conteúdo zip nele. Portanto, em pseudo-código, você pode obter um JPG + ZIP desta maneira:

 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

Todos os deslocamentos são corretamente imaginou. A mesma técnica é utilizada para produzir um arquivo de extracção. Você pode abrir o fluxo no EXE, em seguida, procurar para o fim, e escrever o conteúdo ZIP para esse fluxo. Todos os deslocamentos são calculados corretamente se você fazê-lo desta forma.

Outra coisa - sobre um dos comentários em outro post ... ZIP pode ter dados arbitrários no início e no final do arquivo. Não há nenhuma exigência, tanto quanto eu sei que o zip necessidades diretório central para estar no final do arquivo, no entanto, que é típico.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top