Проблема комбинации файла JPG+Zip с форматом Zip

Если по Открытому исходному коду, Вы действительно имели в виду "свободный", то Microsoft предбыстрый анализ является хорошей. Только для Windows, конечно. Это полностью интегрируется в Visual Studio & компилятор. например:

cl /analyze Sample.cpp

11
задан Tom Ritter 30 November 2009 в 14:55
поделиться

4 ответа

На самом деле это состоит из двух частей :)

Во-первых, что бы люди ни говорили, zip-файлы не могут технически дословно помещаться в конец файлов. Конец записи центрального каталога имеет значение, которое указывает байтовое смещение от начала текущего диска (если у вас только один файл .zip, это означает текущий файл). Сейчас многие процессоры игнорируют это, хотя zip-папка Windows этого не делает, поэтому вам нужно исправить это значение, чтобы она работала в проводнике Windows (не то, чтобы вас это волновало; P) См. Zip APPNOTE для получения информации о формат файла. Обычно вы находите в шестнадцатеричном редакторе (или пишете инструмент) значение «смещения начала центрального каталога относительно начального номера диска». Затем найдите первую "подпись заголовка центрального файла" (шестнадцатеричное значение 504b0102) и установите значение для этого смещения.

Увы, это не исправляет 7zip, но это связано с тем, как 7zip пытается угадать формат файла. По сути, он будет искать только первые ~ 4 МБ для двоичной последовательности 504b0304, если не найдет, он предполагает, что это не Zip, и пробует другие форматы архива. Очевидно, поэтому добавление еще одного файла ломает вещи, это увеличивает предел поиска.

Теперь, чтобы исправить это, вам нужно добавить эту шестнадцатеричную строку в jpeg, не нарушая ее. Один из способов сделать это - добавить сразу после заголовка FFD8 JPEG SOI следующие шестнадцатеричные данные, FFEF0005504B030400. Это добавляет настраиваемый блок с вашей последовательностью и является правильным, поэтому заголовки jpeg должны просто игнорировать его.

t исправить 7zip, но это связано с тем, что 7zip пытается угадать формат файла. По сути, он будет искать только первые ~ 4 МБ для двоичной последовательности 504b0304, если не найдет, он предполагает, что это не Zip, и пробует другие форматы архива. Очевидно, поэтому добавление еще одного файла ломает вещи, это увеличивает предел поиска.

Теперь, чтобы исправить это, вам нужно добавить эту шестнадцатеричную строку в jpeg, не нарушая ее. Один из способов сделать это - добавить сразу после заголовка FFD8 JPEG SOI следующие шестнадцатеричные данные, FFEF0005504B030400. Это добавляет настраиваемый блок с вашей последовательностью и является правильным, поэтому заголовки jpeg должны просто игнорировать его.

t исправить 7zip, но это связано с тем, что 7zip пытается угадать формат файла. По сути, он будет искать только первые ~ 4 МБ для двоичной последовательности 504b0304, если не найдет, он предполагает, что это не Zip, и пробует другие форматы архива. Очевидно, поэтому добавление еще одного файла ломает вещи, оно увеличивает предел поиска.

Теперь, чтобы исправить это, вам нужно добавить эту шестнадцатеричную строку в jpeg, не нарушая ее. Один из способов сделать это - добавить сразу после заголовка FFD8 JPEG SOI следующие шестнадцатеричные данные, FFEF0005504B030400. Это добавляет настраиваемый блок с вашей последовательностью и является правильным, поэтому заголовки jpeg должны просто игнорировать его.

Очевидно, поэтому добавление еще одного файла ломает вещи, оно увеличивает предел поиска.

Теперь, чтобы исправить это, вам нужно добавить эту шестнадцатеричную строку в jpeg, не нарушая ее. Один из способов сделать это - добавить сразу после заголовка FFD8 JPEG SOI следующие шестнадцатеричные данные, FFEF0005504B030400. Это добавляет настраиваемый блок с вашей последовательностью и является правильным, поэтому заголовки jpeg должны просто игнорировать его.

Очевидно, поэтому добавление еще одного файла ломает вещи, оно увеличивает предел поиска.

Теперь, чтобы исправить это, вам нужно добавить эту шестнадцатеричную строку в jpeg, не нарушая ее. Один из способов сделать это - добавить сразу после заголовка FFD8 JPEG SOI следующие шестнадцатеричные данные, FFEF0005504B030400. Это добавляет настраиваемый блок с вашей последовательностью и является правильным, поэтому заголовки jpeg должны просто игнорировать его.

10
ответ дан 3 December 2019 в 01:44
поделиться

Я загрузил исходный код для 7-Zip и выяснил, что является причиной этого.

В CPP / 7zip / UI / Common / OpenArchive.cpp вы увидите следующее :

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

Это означает, что поиск заголовка будет выполняться только в первых 4194304 байтах файла. Если его там нет, 7-Zip считает его недопустимым файлом.

Вы можете удвоить это ограничение, изменив 1 << 22 на 1 << 23 . Я протестировал это изменение, перестроив 7-Zip, и оно работает.

РЕДАКТИРОВАТЬ : Чтобы обойти эту проблему, вы можете загрузить исходный код , внести вышеуказанное изменение и собрать его. Я построил его с помощью VS 2008. Откройте командную строку VS, перейдите в местоположение-извлеченного-источника \ CPP \ 7zip \ Bundles и введите «nmake». Затем в каталоге Alone запустите "7za t nonworking.jpg".

21
ответ дан 3 December 2019 в 01:44
поделиться

Итак, для всех, кто задает этот вопрос, вот история:

Да, Энди буквально прав в том, почему 7-Zip не работает с файлом, но это не помогает моему проблема, поскольку я не могу убедить людей использовать МОЮ версию 7-Zip.

тиранид, однако, дал мне решение.

  • Во-первых, добавление небольшой строки байтов в JPG, как он предлагает, позволит открывать 7-Zip Это. Однако он немного отличается от действительного фрагмента JPG, он должен быть FFEF00 07 504B030400 - длина была меньше на 2 байта.
  • Это позволяет 7-Zip открывать его, но не извлекать файлы, он молча терпит неудачу. Это связано с тем, что записи в центральном каталоге имеют внутренние указатели / смещения, указывающие на запись в файле. Поскольку перед этим вы поставили кучу всего, вам нужно исправить все эти указатели!
  • Чтобы открыть zip-архив с помощью встроенной в Windows поддержки zip-архива, вам необходимо, как говорит тиранид, исправить «смещение начала центрального каталога относительно начального номера диска». Вот сценарий python для выполнения последних двух, хотя это фрагмент, а не 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()
4
ответ дан 3 December 2019 в 01:44
поделиться

Вы можете создавать гибридные файлы JPG + ZIP, используя DotNetZip . DotNetZip может сохранять в поток, и он достаточно умен, чтобы распознать исходное смещение уже существующего потока, прежде чем он начнет записывать в него zip-содержимое. Следовательно, в псевдокоде вы можете получить JPG + ZIP следующим образом:

 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

Все смещения рассчитаны правильно. Тот же метод используется для создания самораспаковывающегося архива. Вы можете открыть поток в EXE, затем перейти к концу и записать содержимое ZIP в этот поток. Если вы сделаете это таким образом, все смещения будут рассчитаны правильно.

Другое дело - по поводу одного из комментариев в другом посте ... ZIP может иметь произвольные данные в начале и в конце файла. Насколько я знаю, не требуется, чтобы центральный каталог zip располагался в конце файла, хотя это типично.

2
ответ дан 3 December 2019 в 01:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: