سؤال

نأمل أن كنت قد سمعت من أنيق هاك التي تمكنك من الجمع بين JPG ملف مضغوط في ملف واحد و هو صالح (أو على الأقل قابل للقراءة) ملف لكل الأشكال.حسنا ، لقد أدركت منذ JPG يتيح التعسفي الاشياء في النهاية و الرمز البريدي في البداية ، يمكن أن عصا واحدة أكثر من شكل في هناك - في الوسط.لأغراض هذا السؤال نفترض وسط البيانات التعسفي البيانات الثنائية مقارعة لا تتعارض مع JPG أو الرمز البريدي صيغ (بمعنى أنها لا تحتوي على سحر الرمز البريدي رأس 0x04034b50).التوضيح:

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

أنا catting مثل هذا:

القط "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 "لاغية.بايت" "randomzipfile.zip" > temp.zip

هذا ينتج 6,318 KB file.ذلك لا فتح في 7-Zip.ومع ذلك ، عندما القط واحد أقل 'ضعف' (وذلك بدلا من 13 filea و ب ، 12):

القط "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 "لاغية.بايت" "randomzipfile.zip" > temp.الرمز البريدي

وتنتج 5,996 KB ملف لا فتح في 7-Zip.

لذلك أنا أعرف بلدي التعسفي البيانات الثنائية لا يجب السحر ملف مضغوط رأس المسمار.لدي ملفات مرجعية من العامل jpg+البيانات+الرمز البريدي و غير العامل jpg+البيانات+الرمز البريدي (حفظ-كما يسبب المتصفح يعتقد أنهم الصور و إضافة الرمز البريدي امتداد نفسك).

أريد أن أعرف لماذا فشل مع 13 تركيبات و لا مع 12.للحصول على نقاط المكافأة ، أنا بحاجة إلى الحصول على حول هذا بطريقة أو بأخرى.

هل كانت مفيدة؟

المحلول

في الواقع هو الجزء الثاني من الإجابة حقا :)

أولا بغض النظر عن ما يقوله الناس البريدي الملفات لا يمكن من الناحية الفنية توضع الحرفية في نهاية الملفات.نهاية الوسطى الدليل سجل يحتوي على قيمة مما يدل على إزاحة البايت من بداية القرص الحالي (إذا كان لديك واحد فقط .الرمز البريدي الملف يعني الملف الحالي).الآن الكثير من المعالجات تجاهل هذا, على الرغم من أن ويندوز' مجلد مضغوط لا تحتاج إلى تصحيح تلك القيمة جعلها تعمل في ويندوز إكسبلورر (ليس ذلك لك قد الرعاية ؛ P) انظر الرمز البريدي APPNOTE للحصول على معلومات حول تنسيق الملف.أساسا كنت تجد في محرر عرافة (أو كتابة أداة) للعثور على "إزاحة بدء من دليل مركزي فيما يتعلق انطلاق القرص رقم" قيمة.ثم العثور على أول "المركزية رأس ملف التوقيع" (عرافة من 504b0102) وتعيين القيمة إلى أن الإزاحة.

الآن للأسف هذا لا يصلح 7zip ولكن هذا يرجع إلى الطريقة 7zip يحاول تخمين تنسيق الملف.في الأساس هو فقط البحث الأول ~4MiB عن ثنائي التسلسل 504b0304 ، إذا لم يجد ذلك فإنه يفترض أنها ليست الرمز البريدي ويحاول غيرها من صيغ الأرشيف.ومن الواضح أن هذا هو السبب في إضافة واحد أكثر من ملف يكسر الأشياء, فإنه يدفع أكثر من حد البحث.

الآن لإصلاحه ما عليك القيام به هو إضافة أن hex string إلى jpeg دون كسرها.طريقة واحدة للقيام بذلك هو أن أضيف بعد FFD8 JPEG SOI رأس التالية عرافة البيانات ، FFEF0005504B030400 .أن يضيف كتلة المخصصة مع التسلسل الخاص بك هو الصحيح حتى jpeg رؤوس ينبغي تجاهله.

نصائح أخرى

أنا تحميل المصدر 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\حزم نوع 'nmake'.ثم في وحده دليل تشغيل '7za t nonworking.jpg و يجب أن نرى 'كل شيء على ما يرام'.

لذلك على أي شخص آخر أن يجد هذا السؤال: هنا القصة:

نعم اندي حرفيا الصحيح لماذا 7-Zip هو الفشل في الملف ولكنه لا يساعد مشكلتي منذ أنا لا يمكن أن يخرج الناس إلى استخدام الإصدار 7-Zip.

tyranid ومع ذلك حصلت لي الحل.

  • أول قبالة, إضافة صغيرة bytestring إلى JPG كما انه يوحي سوف تتيح 7-Zip فتحه.ومع ذلك, انها قليلا من صالح JPG جزء ، فإنه يحتاج إلى أن يكون FFEF00 07 504B030400 - طول بنسبة 2 بايت.
  • هذا يتيح 7-Zip فتحه ، ولكن ليس استخراج الملفات فشل بصمت.وذلك لأن الإدخالات في الدليل المركزي قد المؤشرات الداخلية/إزاحة التي تشير إلى دخول الملف.منذ كنت وضعت مجموعة من الأشياء قبل أن تحتاج إلى تصحيح كل تلك المؤشرات!
  • أن يكون الرمز البريدي مفتوحة مع ويندوز المدمج في دعم الرمز, كنت بحاجة إلى ذلك ، كما tyranid يقول تصحيح "إزاحة بدء من دليل مركزي فيما يتعلق انطلاق القرص رقم".هنا هو بيثون السيناريو للقيام الماضيين ، على الرغم من أنها جزء لا copypasta-جاهزة للاستخدام

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

يمكنك إنتاج الهجين JPG+الرمز البريدي الملفات باستخدام DotNetZip.DotNetZip يمكن حفظ إلى تيار ، و هو ذكي بما فيه الكفاية للاعتراف الأصلي إزاحة موجود من قبل تيار قبل أن يبدأ الكتابة والمحتوى في ذلك.ولذلك في البرمجية الزائفة ، يمكنك الحصول على JPG+الرمز البريدي من هذا الطريق:

 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, ثم تسعى إلى النهاية ، وكتابة الرمز البريدي المحتوى إلى أن تيار.كل إزاحة تحسب بشكل صحيح إذا كنت تفعل ذلك بهذه الطريقة.

شيء آخر - فيما يتعلق واحد من التعليقات في وظيفة أخرى...الرمز البريدي يمكن أن يكون تعسفيا البيانات في بداية و في نهاية الملف.لا يوجد شرط بقدر ما أعرف أن الرمز البريدي المركزية الدليل يجب أن يكون في نهاية الملف ، على الرغم من أن هذا هو الحال.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top