Class: RMail::Parser::MultipartReader
- Inherits:
-
PushbackReader
- Object
- PushbackReader
- RMail::Parser::MultipartReader
- Defined in:
- lib/rmail/parser/multipart.rb
Overview
A simple interface to facilitate parsing a multipart message.
The typical RubyMail user will have no use for this class. Although it is an example of how to use a PushbackReader, the typical RubyMail user will never use a PushbackReader either. ;-)
Instance Attribute Summary
Attributes inherited from PushbackReader
Instance Method Summary collapse
-
#delimiter ⇒ Object
Call this to retrieve the delimiter string that terminated the part just read.
-
#epilogue? ⇒ Boolean
Call this to determine if #read is currently returning strings from the epilogue portion of a mime multipart.
-
#initialize(input, boundary) ⇒ MultipartReader
constructor
Creates a MIME multipart parser.
-
#next_part ⇒ Object
Start reading the next part.
-
#preamble? ⇒ Boolean
Call this to determine if #read is currently returning strings from the preamble portion of a mime multipart.
-
#read_chunk(chunk_size) ⇒ Object
Returns the next chunk of data from the input stream as a string.
- #read_chunk_low(chunk_size) ⇒ Object
Methods inherited from PushbackReader
#eof, maybe_contains_re, #pushback, #read, #standard_read_chunk
Constructor Details
#initialize(input, boundary) ⇒ MultipartReader
Creates a MIME multipart parser.
input
is an object supporting a read
method that takes one argument, a suggested number of bytes to read, and returns either a string of bytes read or nil if there are no more bytes to read.
boundary
is the string boundary that separates the parts, without the “–” prefix.
This class is a suitable input source when parsing recursive multiparts.
54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/rmail/parser/multipart.rb', line 54 def initialize(input, boundary) super(input) escaped = Regexp.escape(boundary) @delimiter_re = /(?:\G|\n)--#{escaped}(--)?\s*?(\n|\z)/ @might_be_delimiter_re = might_be_delimiter_re(boundary) @caryover = nil @chunks = [] @eof = false @delimiter = nil @delimiter_is_last = false @in_epilogue = false @in_preamble = true end |
Instance Method Details
#delimiter ⇒ Object
Call this to retrieve the delimiter string that terminated the part just read. This is cleared by #next_part.
204 205 206 |
# File 'lib/rmail/parser/multipart.rb', line 204 def delimiter @delimiter end |
#epilogue? ⇒ Boolean
Call this to determine if #read is currently returning strings from the epilogue portion of a mime multipart.
198 199 200 |
# File 'lib/rmail/parser/multipart.rb', line 198 def epilogue? @in_epilogue end |
#next_part ⇒ Object
Start reading the next part. Returns true if there is a next part to read, or false if we have reached the end of the file.
177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/rmail/parser/multipart.rb', line 177 def next_part if @eof false else if @delimiter @delimiter = nil @in_preamble = false @in_epilogue = @delimiter_is_last end true end end |
#preamble? ⇒ Boolean
Call this to determine if #read is currently returning strings from the preamble portion of a mime multipart.
192 193 194 |
# File 'lib/rmail/parser/multipart.rb', line 192 def preamble? @in_preamble end |
#read_chunk(chunk_size) ⇒ Object
Returns the next chunk of data from the input stream as a string. The chunk_size is passed down to the read method of this object’s input stream to suggest a size to it, but don’t depend on the returned data being of any particular size.
If this method returns nil, you must call next_part to begin reading the next MIME part in the data stream.
75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/rmail/parser/multipart.rb', line 75 def read_chunk(chunk_size) chunk = read_chunk_low(chunk_size) if chunk if @in_epilogue while more = read_chunk_low(chunk_size) chunk << more end end end chunk end |
#read_chunk_low(chunk_size) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/rmail/parser/multipart.rb', line 87 def read_chunk_low(chunk_size) if @pushback return standard_read_chunk(chunk_size) end input_gave_nil = false loop { return nil if @eof || @delimiter unless @chunks.empty? chunk, @delimiter, @delimiter_is_last = @chunks.shift return chunk end chunk = standard_read_chunk(chunk_size) if chunk.nil? input_gave_nil = true end if @caryover if chunk @caryover << chunk end chunk = @caryover @caryover = nil end if chunk.nil? @eof = true return nil elsif @in_epilogue return chunk end start = 0 found_last_delimiter = false while !found_last_delimiter and (start < chunk.length) and (found = chunk.index(@delimiter_re, start)) if $~[2] == '' and !input_gave_nil break end delimiter = $~[0] # check if delimiter had the trailing -- if $~.begin(1) found_last_delimiter = true end temp = if found == start nil else chunk[start, found - start] end @chunks << [ temp, delimiter, found_last_delimiter ] start = $~.end(0) end chunk = chunk[start..-1] if start > 0 # If something that looks like a delimiter exists at the end # of this chunk, refrain from returning it. unless found_last_delimiter or input_gave_nil start = chunk.rindex(/\n/) || 0 if chunk.index(@might_be_delimiter_re, start) @caryover = chunk[start..-1] chunk[start..-1] = '' chunk = nil if chunk.length == 0 end end unless chunk.nil? @chunks << [ chunk, nil, false ] end chunk, @delimiter, @delimiter_is_last = @chunks.shift if chunk return chunk end } end |