123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- 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
|