|
@@ -0,0 +1,146 @@
|
|
|
+
|
|
|
+use_file_names = true
|
|
|
+include_file_names = false
|
|
|
+
|
|
|
+loop do
|
|
|
+
|
|
|
+
|
|
|
+ if ARGF.read(2) != "PK"
|
|
|
+ if ARGF.eof?
|
|
|
+ exit
|
|
|
+ end
|
|
|
+ warn "Input is not a zip file"
|
|
|
+ exit 1
|
|
|
+ end
|
|
|
+
|
|
|
+ if !(ARGF.read(2) == "\003\004") # file header
|
|
|
+ exit
|
|
|
+ end
|
|
|
+
|
|
|
+ version = ARGF.read(2).unpack("v").first
|
|
|
+
|
|
|
+ # i should use this to sort out some incompatible file formats....
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ bitflag = ( ARGF.read(2).unpack("v").first)
|
|
|
+
|
|
|
+ use_data_descriptor = bitflag[3] == 1
|
|
|
+
|
|
|
+ # should check for things that are unsupported for sure....
|
|
|
+ c_method = ARGF.read(2).unpack("v").first
|
|
|
+ if c_method != 8
|
|
|
+ warn "Unknown compression method"
|
|
|
+ end
|
|
|
+
|
|
|
+ if c_method > 255
|
|
|
+ warn "Unsupported compression method"
|
|
|
+ exit 1
|
|
|
+ end
|
|
|
+ last_mod_time = ARGF.read(2) # unsupported until i know how to convert dos to unix time
|
|
|
+ last_mod_date = ARGF.read(2) # unsupported until i know how to convert dos to unix time
|
|
|
+
|
|
|
+ crc_32 = ARGF.read(4).unpack("V").first
|
|
|
+
|
|
|
+ size = ARGF.read(4).unpack("V").first
|
|
|
+ if use_data_descriptor
|
|
|
+ size = :auto
|
|
|
+ end
|
|
|
+
|
|
|
+ uncompressed_size = ARGF.read(4).unpack("V").first
|
|
|
+
|
|
|
+ file_name_length = ARGF.read(2).unpack("v").first
|
|
|
+ extra_field_length = ARGF.read(2).unpack("v").first
|
|
|
+
|
|
|
+ file_name = ARGF.read(file_name_length)
|
|
|
+ ARGF.read(extra_field_length) # extra field.. no use (yet?)
|
|
|
+
|
|
|
+ file_name2 = file_name
|
|
|
+ if use_file_names
|
|
|
+ outfile = nil
|
|
|
+ while !outfile
|
|
|
+
|
|
|
+ if !(file_name2 =~ /\//)
|
|
|
+ used_filename = file_name2
|
|
|
+ outfile = File.open("#{file_name2}.deflate","w")
|
|
|
+ end
|
|
|
+ file_name2 = "zip2gz_file%05i" % rand(100000)
|
|
|
+
|
|
|
+ end
|
|
|
+ else
|
|
|
+ outfile = STDOUT
|
|
|
+ end
|
|
|
+
|
|
|
+
|
|
|
+ #generate gz header
|
|
|
+ #outfile.print "\x1f\x8b"
|
|
|
+ #outfile.putc c_method
|
|
|
+
|
|
|
+ flags = 0
|
|
|
+
|
|
|
+ if include_file_names && !file_name.empty?
|
|
|
+ flags |= 0b1000
|
|
|
+ end
|
|
|
+
|
|
|
+ #outfile.print flags.chr
|
|
|
+ #outfile.print [0].pack("V") # no time conversion (yet)
|
|
|
+ #outfile.print 2.chr # maybe copy first 3 bits of the zip extra flags? default to maximum compression
|
|
|
+ #outfile.print 255.chr # this is stored in the central directory... (same for comments) we don't parse this...
|
|
|
+
|
|
|
+ #if include_file_names && !file_name.empty?
|
|
|
+ # outfile.print file_name.tr("\x00"," ")+"\x00"
|
|
|
+ #end
|
|
|
+
|
|
|
+ if size != :auto
|
|
|
+ blocks = size / 0x100
|
|
|
+ rest = size & 0xFF
|
|
|
+
|
|
|
+ blocks.times do
|
|
|
+ outfile.print ARGF.read(0x100)
|
|
|
+ end
|
|
|
+
|
|
|
+ outfile.print ARGF.read(rest)
|
|
|
+ else
|
|
|
+
|
|
|
+ size = -14
|
|
|
+
|
|
|
+ buffer = ""
|
|
|
+ loop do
|
|
|
+ buffer << ARGF.getc
|
|
|
+ size += 1
|
|
|
+ if buffer.size > 14
|
|
|
+ outfile.putc buffer[0]
|
|
|
+ buffer[0,1] = ""
|
|
|
+ end
|
|
|
+
|
|
|
+ if buffer.size == 14
|
|
|
+ crc, c_size, u_size, magic_number = buffer.unpack("VVVa2")
|
|
|
+ if c_size == size && c_size <= u_size && magic_number == "PK"
|
|
|
+
|
|
|
+ break
|
|
|
+
|
|
|
+ ARGF.ungetc "K"
|
|
|
+ ARGF.ungetc "P"
|
|
|
+ uncompressed_size = u_size
|
|
|
+ crc_32 = crc
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ #outfile.print [crc_32, uncompressed_size ].pack("VV")
|
|
|
+ if file_name.empty?
|
|
|
+ warn "Successfully wrote file crc32:%08X length:%i to %s" % [crc_32, size, (outfile == STDOUT ? "stdout" : "#{used_filename}.deflate")]
|
|
|
+ else
|
|
|
+ warn "Successfully wrote file \"%s\" crc32:%08X length:%i to %s" % [file_name, crc_32, size, (outfile == STDOUT ? "stdout" : "#{used_filename}.deflate")]
|
|
|
+ end
|
|
|
+
|
|
|
+ if use_file_names
|
|
|
+ outfile.close
|
|
|
+ end
|
|
|
+
|
|
|
+end
|
|
|
+
|
|
|
+
|