superp-rubyzip 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,65 @@
1
+ module Zip
2
+ class Inflater < Decompressor #:nodoc:all
3
+ def initialize(input_stream)
4
+ super
5
+ @zlib_inflater = ::Zlib::Inflate.new(-Zlib::MAX_WBITS)
6
+ @output_buffer = ''
7
+ @has_returned_empty_string = false
8
+ end
9
+
10
+ def sysread(number_of_bytes = nil, buf = nil)
11
+ readEverything = number_of_bytes.nil?
12
+ while (readEverything || @output_buffer.bytesize < number_of_bytes)
13
+ break if internal_input_finished?
14
+ @output_buffer << internal_produce_input(buf)
15
+ end
16
+ return value_when_finished if @output_buffer.bytesize == 0 && input_finished?
17
+ end_index = number_of_bytes.nil? ? @output_buffer.bytesize : number_of_bytes
18
+ @output_buffer.slice!(0...end_index)
19
+ end
20
+
21
+ def produce_input
22
+ if (@output_buffer.empty?)
23
+ internal_produce_input
24
+ else
25
+ @output_buffer.slice!(0...(@output_buffer.length))
26
+ end
27
+ end
28
+
29
+ # to be used with produce_input, not read (as read may still have more data cached)
30
+ # is data cached anywhere other than @outputBuffer? the comment above may be wrong
31
+ def input_finished?
32
+ @output_buffer.empty? && internal_input_finished?
33
+ end
34
+
35
+ alias :eof :input_finished?
36
+ alias :eof? :input_finished?
37
+
38
+ private
39
+
40
+ def internal_produce_input(buf = nil)
41
+ retried = 0
42
+ begin
43
+ @zlib_inflater.inflate(@input_stream.read(Decompressor::CHUNK_SIZE, buf))
44
+ rescue Zlib::BufError
45
+ raise if retried >= 5 # how many times should we retry?
46
+ retried += 1
47
+ retry
48
+ end
49
+ end
50
+
51
+ def internal_input_finished?
52
+ @zlib_inflater.finished?
53
+ end
54
+
55
+ def value_when_finished # mimic behaviour of ruby File object.
56
+ return if @has_returned_empty_string
57
+ @has_returned_empty_string = true
58
+ ''
59
+ end
60
+ end
61
+ end
62
+
63
+ # Copyright (C) 2002, 2003 Thomas Sondergaard
64
+ # rubyzip is free software; you can redistribute it and/or
65
+ # modify it under the terms of the ruby license.
@@ -0,0 +1,145 @@
1
+ module Zip
2
+ # ZipInputStream is the basic class for reading zip entries in a
3
+ # zip file. It is possible to create a ZipInputStream object directly,
4
+ # passing the zip file name to the constructor, but more often than not
5
+ # the ZipInputStream will be obtained from a ZipFile (perhaps using the
6
+ # ZipFileSystem interface) object for a particular entry in the zip
7
+ # archive.
8
+ #
9
+ # A ZipInputStream inherits IOExtras::AbstractInputStream in order
10
+ # to provide an IO-like interface for reading from a single zip
11
+ # entry. Beyond methods for mimicking an IO-object it contains
12
+ # the method get_next_entry for iterating through the entries of
13
+ # an archive. get_next_entry returns a ZipEntry object that describes
14
+ # the zip entry the ZipInputStream is currently reading from.
15
+ #
16
+ # Example that creates a zip archive with ZipOutputStream and reads it
17
+ # back again with a ZipInputStream.
18
+ #
19
+ # require 'zip/zip'
20
+ #
21
+ # Zip::ZipOutputStream::open("my.zip") {
22
+ # |io|
23
+ #
24
+ # io.put_next_entry("first_entry.txt")
25
+ # io.write "Hello world!"
26
+ #
27
+ # io.put_next_entry("adir/first_entry.txt")
28
+ # io.write "Hello again!"
29
+ # }
30
+ #
31
+ #
32
+ # Zip::ZipInputStream::open("my.zip") {
33
+ # |io|
34
+ #
35
+ # while (entry = io.get_next_entry)
36
+ # puts "Contents of #{entry.name}: '#{io.read}'"
37
+ # end
38
+ # }
39
+ #
40
+ # java.util.zip.ZipInputStream is the original inspiration for this
41
+ # class.
42
+
43
+ class InputStream
44
+ include ::Zip::IOExtras::AbstractInputStream
45
+
46
+ # Opens the indicated zip file. An exception is thrown
47
+ # if the specified offset in the specified filename is
48
+ # not a local zip entry header.
49
+ def initialize(filename, offset = 0, io = nil)
50
+ super()
51
+ if (io.nil?)
52
+ @archiveIO = ::File.open(filename, "rb")
53
+ @archiveIO.seek(offset, IO::SEEK_SET)
54
+ else
55
+ @archiveIO = io
56
+ end
57
+ @decompressor = NullDecompressor.instance
58
+ @currentEntry = nil
59
+ end
60
+
61
+ def close
62
+ @archiveIO.close
63
+ end
64
+
65
+ # Same as #initialize but if a block is passed the opened
66
+ # stream is passed to the block and closed when the block
67
+ # returns.
68
+ def InputStream.open(filename)
69
+ return new(filename) unless block_given?
70
+
71
+ zio = new(filename)
72
+ yield zio
73
+ ensure
74
+ zio.close if zio
75
+ end
76
+
77
+ def InputStream.open_buffer(io)
78
+ return new('',0,io) unless block_given?
79
+ zio = new('',0,io)
80
+ yield zio
81
+ ensure
82
+ zio.close if zio
83
+ end
84
+
85
+ # Returns a ZipEntry object. It is necessary to call this
86
+ # method on a newly created ZipInputStream before reading from
87
+ # the first entry in the archive. Returns nil when there are
88
+ # no more entries.
89
+
90
+ def get_next_entry
91
+ @archiveIO.seek(@currentEntry.next_header_offset, IO::SEEK_SET) if @currentEntry
92
+ open_entry
93
+ end
94
+
95
+ # Rewinds the stream to the beginning of the current entry
96
+ def rewind
97
+ return if @currentEntry.nil?
98
+ @lineno = 0
99
+ @pos = 0
100
+ @archiveIO.seek(@currentEntry.local_header_offset,
101
+ IO::SEEK_SET)
102
+ open_entry
103
+ end
104
+
105
+ # Modeled after IO.sysread
106
+ def sysread(numberOfBytes = nil, buf = nil)
107
+ @decompressor.sysread(numberOfBytes, buf)
108
+ end
109
+
110
+ def eof
111
+ @output_buffer.empty? && @decompressor.eof
112
+ end
113
+ alias :eof? :eof
114
+
115
+ protected
116
+
117
+ def open_entry
118
+ @currentEntry = Entry.read_local_entry(@archiveIO)
119
+ if @currentEntry.nil?
120
+ @decompressor = NullDecompressor.instance
121
+ elsif @currentEntry.compression_method == Entry::STORED
122
+ @decompressor = PassThruDecompressor.new(@archiveIO, @currentEntry.size)
123
+ elsif @currentEntry.compression_method == Entry::DEFLATED
124
+ @decompressor = Inflater.new(@archiveIO)
125
+ else
126
+ raise ZipCompressionMethodError,
127
+ "Unsupported compression method #{@currentEntry.compression_method}"
128
+ end
129
+ flush
130
+ return @currentEntry
131
+ end
132
+
133
+ def produce_input
134
+ @decompressor.produce_input
135
+ end
136
+
137
+ def input_finished?
138
+ @decompressor.input_finished?
139
+ end
140
+ end
141
+ end
142
+
143
+ # Copyright (C) 2002, 2003 Thomas Sondergaard
144
+ # rubyzip is free software; you can redistribute it and/or
145
+ # modify it under the terms of the ruby license.
@@ -0,0 +1,186 @@
1
+ module Zip
2
+ module IOExtras #:nodoc:
3
+
4
+ CHUNK_SIZE = 131072
5
+
6
+ RANGE_ALL = 0..-1
7
+
8
+ def self.copy_stream(ostream, istream)
9
+ s = ''
10
+ ostream.write(istream.read(CHUNK_SIZE, s)) until istream.eof?
11
+ end
12
+
13
+ def self.copy_stream_n(ostream, istream, nbytes)
14
+ s = ''
15
+ toread = nbytes
16
+ while (toread > 0 && !istream.eof?)
17
+ tr = toread > CHUNK_SIZE ? CHUNK_SIZE : toread
18
+ ostream.write(istream.read(tr, s))
19
+ toread -= tr
20
+ end
21
+ end
22
+
23
+
24
+ # Implements kind_of? in order to pretend to be an IO object
25
+ module FakeIO
26
+ def kind_of?(object)
27
+ object == IO || super
28
+ end
29
+ end
30
+
31
+ # Implements many of the convenience methods of IO
32
+ # such as gets, getc, readline and readlines
33
+ # depends on: input_finished?, produce_input and read
34
+ module AbstractInputStream
35
+ include Enumerable
36
+ include FakeIO
37
+
38
+ def initialize
39
+ super
40
+ @lineno = 0
41
+ @pos = 0
42
+ @output_buffer = ""
43
+ end
44
+
45
+ attr_accessor :lineno
46
+ attr_reader :pos
47
+
48
+ def read(numberOfBytes = nil, buf = nil)
49
+ tbuf = nil
50
+
51
+ if @output_buffer.bytesize > 0
52
+ if numberOfBytes <= @output_buffer.bytesize
53
+ tbuf = @output_buffer.slice!(0, numberOfBytes)
54
+ else
55
+ numberOfBytes -= @output_buffer.bytesize if (numberOfBytes)
56
+ rbuf = sysread(numberOfBytes, buf)
57
+ tbuf = @output_buffer
58
+ tbuf << rbuf if (rbuf)
59
+ @output_buffer = ""
60
+ end
61
+ else
62
+ tbuf = sysread(numberOfBytes, buf)
63
+ end
64
+
65
+ @pos += tbuf.length
66
+
67
+ return nil unless (tbuf)
68
+
69
+ if buf
70
+ buf.replace(tbuf)
71
+ else
72
+ buf = tbuf
73
+ end
74
+
75
+ buf
76
+ end
77
+
78
+ def readlines(aSepString = $/)
79
+ retVal = []
80
+ each_line(aSepString) { |line| retVal << line }
81
+ retVal
82
+ end
83
+
84
+ def gets(aSepString = $/, numberOfBytes = nil)
85
+ @lineno = @lineno.next
86
+
87
+ if numberOfBytes.respond_to?(:to_int)
88
+ numberOfBytes = numberOfBytes.to_int
89
+ aSepString = aSepString.to_str if aSepString
90
+ elsif aSepString.respond_to?(:to_int)
91
+ numberOfBytes = aSepString.to_int
92
+ aSepString = $/
93
+ else
94
+ numberOfBytes = nil
95
+ aSepString = aSepString.to_str if aSepString
96
+ end
97
+
98
+ return read(numberOfBytes) if aSepString.nil?
99
+ aSepString = "#{$/}#{$/}" if aSepString.empty?
100
+
101
+ bufferIndex = 0
102
+ overLimit = (numberOfBytes && @output_buffer.bytesize >= numberOfBytes)
103
+ while ((matchIndex = @output_buffer.index(aSepString, bufferIndex)) == nil && !overLimit)
104
+ bufferIndex = [bufferIndex, @output_buffer.bytesize - aSepString.bytesize].max
105
+ if input_finished?
106
+ return @output_buffer.empty? ? nil : flush
107
+ end
108
+ @output_buffer << produce_input
109
+ overLimit = (numberOfBytes && @output_buffer.bytesize >= numberOfBytes)
110
+ end
111
+ sepIndex = [matchIndex + aSepString.bytesize, numberOfBytes || @output_buffer.bytesize].min
112
+ @pos += sepIndex
113
+ return @output_buffer.slice!(0...sepIndex)
114
+ end
115
+
116
+ def flush
117
+ retVal = @output_buffer
118
+ @output_buffer=""
119
+ return retVal
120
+ end
121
+
122
+ def readline(aSepString = $/)
123
+ retVal = gets(aSepString)
124
+ raise EOFError if retVal == nil
125
+ retVal
126
+ end
127
+
128
+ def each_line(aSepString = $/)
129
+ while true
130
+ yield readline(aSepString)
131
+ end
132
+ rescue EOFError
133
+ end
134
+
135
+ alias_method :each, :each_line
136
+ end
137
+
138
+
139
+ # Implements many of the output convenience methods of IO.
140
+ # relies on <<
141
+ module AbstractOutputStream
142
+ include FakeIO
143
+
144
+ def write(data)
145
+ self << data
146
+ data.to_s.bytesize
147
+ end
148
+
149
+
150
+ def print(*params)
151
+ self << params.join($,) << $\.to_s
152
+ end
153
+
154
+ def printf(aFormatString, *params)
155
+ self << sprintf(aFormatString, *params)
156
+ end
157
+
158
+ def putc(anObject)
159
+ self << case anObject
160
+ when Fixnum then
161
+ anObject.chr
162
+ when String then
163
+ anObject
164
+ else
165
+ raise TypeError, "putc: Only Fixnum and String supported"
166
+ end
167
+ anObject
168
+ end
169
+
170
+ def puts(*params)
171
+ params << "\n" if params.empty?
172
+ params.flatten.each do |element|
173
+ val = element.to_s
174
+ self << val
175
+ self << "\n" unless val[-1, 1] == "\n"
176
+ end
177
+ end
178
+
179
+ end
180
+
181
+ end # IOExtras namespace module
182
+ end
183
+
184
+ # Copyright (C) 2002-2004 Thomas Sondergaard
185
+ # rubyzip is free software; you can redistribute it and/or
186
+ # modify it under the terms of the ruby license.
@@ -0,0 +1,15 @@
1
+ module Zip
2
+ class NullCompressor < Compressor #:nodoc:all
3
+ include Singleton
4
+
5
+ def <<(data)
6
+ raise IOError, "closed stream"
7
+ end
8
+
9
+ attr_reader :size, :compressed_size
10
+ end
11
+ end
12
+
13
+ # Copyright (C) 2002, 2003 Thomas Sondergaard
14
+ # rubyzip is free software; you can redistribute it and/or
15
+ # modify it under the terms of the ruby license.
@@ -0,0 +1,27 @@
1
+ module Zip
2
+ class NullDecompressor #:nodoc:all
3
+ include Singleton
4
+
5
+ def sysread(numberOfBytes = nil, buf = nil)
6
+ nil
7
+ end
8
+
9
+ def produce_input
10
+ nil
11
+ end
12
+
13
+ def input_finished?
14
+ true
15
+ end
16
+
17
+ def eof
18
+ true
19
+ end
20
+
21
+ alias :eof? :eof
22
+ end
23
+ end
24
+
25
+ # Copyright (C) 2002, 2003 Thomas Sondergaard
26
+ # rubyzip is free software; you can redistribute it and/or
27
+ # modify it under the terms of the ruby license.
@@ -0,0 +1,9 @@
1
+ module Zip
2
+ class NullInputStream < NullDecompressor #:nodoc:all
3
+ include ::Zip::IOExtras::AbstractInputStream
4
+ end
5
+ end
6
+
7
+ # Copyright (C) 2002, 2003 Thomas Sondergaard
8
+ # rubyzip is free software; you can redistribute it and/or
9
+ # modify it under the terms of the ruby license.