zip2raw.rb 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. use_file_names = true
  2. include_file_names = false
  3. loop do
  4. if ARGF.read(2) != "PK"
  5. if ARGF.eof?
  6. exit
  7. end
  8. warn "Input is not a zip file"
  9. exit 1
  10. end
  11. if !(ARGF.read(2) == "\003\004") # file header
  12. exit
  13. end
  14. version = ARGF.read(2).unpack("v").first
  15. # i should use this to sort out some incompatible file formats....
  16. bitflag = ( ARGF.read(2).unpack("v").first)
  17. use_data_descriptor = bitflag[3] == 1
  18. # should check for things that are unsupported for sure....
  19. c_method = ARGF.read(2).unpack("v").first
  20. if c_method != 8
  21. warn "Unknown compression method"
  22. end
  23. if c_method > 255
  24. warn "Unsupported compression method"
  25. exit 1
  26. end
  27. last_mod_time = ARGF.read(2) # unsupported until i know how to convert dos to unix time
  28. last_mod_date = ARGF.read(2) # unsupported until i know how to convert dos to unix time
  29. crc_32 = ARGF.read(4).unpack("V").first
  30. size = ARGF.read(4).unpack("V").first
  31. if use_data_descriptor
  32. size = :auto
  33. end
  34. uncompressed_size = ARGF.read(4).unpack("V").first
  35. file_name_length = ARGF.read(2).unpack("v").first
  36. extra_field_length = ARGF.read(2).unpack("v").first
  37. file_name = ARGF.read(file_name_length)
  38. ARGF.read(extra_field_length) # extra field.. no use (yet?)
  39. file_name2 = file_name
  40. if use_file_names
  41. outfile = nil
  42. while !outfile
  43. if !(file_name2 =~ /\//)
  44. used_filename = file_name2
  45. outfile = File.open("#{file_name2}.deflate","w")
  46. end
  47. file_name2 = "zip2gz_file%05i" % rand(100000)
  48. end
  49. else
  50. outfile = STDOUT
  51. end
  52. #generate gz header
  53. #outfile.print "\x1f\x8b"
  54. #outfile.putc c_method
  55. flags = 0
  56. if include_file_names && !file_name.empty?
  57. flags |= 0b1000
  58. end
  59. #outfile.print flags.chr
  60. #outfile.print [0].pack("V") # no time conversion (yet)
  61. #outfile.print 2.chr # maybe copy first 3 bits of the zip extra flags? default to maximum compression
  62. #outfile.print 255.chr # this is stored in the central directory... (same for comments) we don't parse this...
  63. #if include_file_names && !file_name.empty?
  64. # outfile.print file_name.tr("\x00"," ")+"\x00"
  65. #end
  66. if size != :auto
  67. blocks = size / 0x100
  68. rest = size & 0xFF
  69. blocks.times do
  70. outfile.print ARGF.read(0x100)
  71. end
  72. outfile.print ARGF.read(rest)
  73. else
  74. size = -14
  75. buffer = ""
  76. loop do
  77. buffer << ARGF.getc
  78. size += 1
  79. if buffer.size > 14
  80. outfile.putc buffer[0]
  81. buffer[0,1] = ""
  82. end
  83. if buffer.size == 14
  84. crc, c_size, u_size, magic_number = buffer.unpack("VVVa2")
  85. if c_size == size && c_size <= u_size && magic_number == "PK"
  86. break
  87. ARGF.ungetc "K"
  88. ARGF.ungetc "P"
  89. uncompressed_size = u_size
  90. crc_32 = crc
  91. end
  92. end
  93. end
  94. end
  95. #outfile.print [crc_32, uncompressed_size ].pack("VV")
  96. if file_name.empty?
  97. warn "Successfully wrote file crc32:%08X length:%i to %s" % [crc_32, size, (outfile == STDOUT ? "stdout" : "#{used_filename}.deflate")]
  98. else
  99. warn "Successfully wrote file \"%s\" crc32:%08X length:%i to %s" % [file_name, crc_32, size, (outfile == STDOUT ? "stdout" : "#{used_filename}.deflate")]
  100. end
  101. if use_file_names
  102. outfile.close
  103. end
  104. end