Class: MIME::Entity
Direct Known Subclasses
Instance Attribute Summary collapse
-
#content ⇒ Object
An Entity has Content.
-
#encoding ⇒ Object
Returns the value of attribute encoding.
-
#multipart_type ⇒ Object
readonly
An Entity has Content.
Instance Method Summary collapse
- #attachment? ⇒ Boolean (also: #file?)
-
#decoded_content ⇒ Object
Converts this data structure into a string, but decoded if necessary.
- #find_part(options) ⇒ Object
- #find_parts(options) ⇒ Object
-
#from_parsed(parsed) ⇒ Object
This means we have a structure from IETF::RFC2045.
-
#headers ⇒ Object
An Entity has Headers.
-
#initialize(arg = nil) ⇒ Entity
constructor
A new instance of Entity.
- #inspect ⇒ Object
-
#multipart? ⇒ Boolean
Macro Methods #.
-
#multipart_boundary ⇒ Object
Auto-generates a boundary if one doesn't yet exist.
- #parsed ⇒ Object
- #part_filename ⇒ Object
- #save_to_file(path = nil) ⇒ Object
-
#to_s ⇒ Object
Renders this data structure into a string, encoded.
Constructor Details
#initialize(arg = nil) ⇒ Entity
Returns a new instance of Entity.
13 14 15 16 17 18 19 20 |
# File 'lib/mime/entity.rb', line 13 def initialize(arg=nil) if arg.is_a?(String) @raw = arg from_parsed(IETF::RFC2045.parse_rfc2045_from(@raw)) elsif arg.is_a?(Hash) @headers = arg end end |
Instance Attribute Details
#content ⇒ Object
An Entity has Content. IF the Content-Type is a multipart type, the content will be one or more Entities.
68 69 70 |
# File 'lib/mime/entity.rb', line 68 def content @content end |
#encoding ⇒ Object
Returns the value of attribute encoding.
101 102 103 |
# File 'lib/mime/entity.rb', line 101 def encoding @encoding end |
#multipart_type ⇒ Object (readonly)
An Entity has Content. IF the Content-Type is a multipart type, the content will be one or more Entities.
68 69 70 |
# File 'lib/mime/entity.rb', line 68 def multipart_type @multipart_type end |
Instance Method Details
#attachment? ⇒ Boolean Also known as: file?
91 92 93 |
# File 'lib/mime/entity.rb', line 91 def headers['content-disposition'] =~ /^attachment(?=;|$)/ || headers['content-disposition'] =~ /^form-data;.* filename=[\"\']?[^\"\']+[\"\']?/ end |
#decoded_content ⇒ Object
Converts this data structure into a string, but decoded if necessary
154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/mime/entity.rb', line 154 def decoded_content return nil if @content.is_a?(Array) case encoding.to_s.downcase when 'quoted-printable' @content.unpack('M')[0] when 'base64' @content.unpack('m')[0] else @content end end |
#find_part(options) ⇒ Object
105 106 107 |
# File 'lib/mime/entity.rb', line 105 def find_part() find_parts().first end |
#find_parts(options) ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/mime/entity.rb', line 108 def find_parts() parts = [] # Do I match your search? iam = true iam = false if [:content_type] && headers['content-type'] !~ /^#{[:content_type]}(?=;|$)/ iam = false if [:content_disposition] && headers['content-disposition'] !~ /^#{[:content_disposition]}(?=;|$)/ parts << self if iam # Do any of my children match your search? content.each do |part| parts.concat part.find_parts() end if multipart? return parts end |
#from_parsed(parsed) ⇒ Object
This means we have a structure from IETF::RFC2045. Entity is: [headers, content], while content may be an array of Entities. Or, :boundary, :content
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/mime/entity.rb', line 33 def from_parsed(parsed) case parsed when Array if parsed[0].is_a?(Hash) && (parsed[1].is_a?(Hash) || parsed[1].is_a?(String)) @headers = parsed[0] @content = parsed[1].is_a?(Hash) ? parsed[1][:content].collect {|p| Entity.new.from_parsed(p)} : parsed[1] if parsed[1].is_a?(Hash) @multipart_type = parsed[1][:type] @multipart_boundary = parsed[1][:boundary] end else raise "IETF PARSING FAIL!" end return self when Hash if parsed.has_key?(:type) && parsed.has_key?(:boundary) && parsed.has_key?(:content) @content = parsed[:content].is_a?(Array) ? parsed[:content].collect {|p| Entity.new.from_parsed(p)} : parsed[:content] else raise "IETF PARSING FAIL!" end return self end raise ArgumentError, "Must pass in either: [an array with two elements: headers(hash) and content(string or array)] OR [a hash containing :type, :boundary, and :content(being the former or a string)]" end |
#headers ⇒ Object
An Entity has Headers.
62 63 64 |
# File 'lib/mime/entity.rb', line 62 def headers @headers ||= {} end |
#inspect ⇒ Object
22 23 24 |
# File 'lib/mime/entity.rb', line 22 def inspect "<#{self.class.name}##{object_id} Headers:{#{headers.collect {|k,v| "#{k}=#{v}"}.join(' ')}} content:#{multipart? ? 'multipart' : 'flat'}>" end |
#multipart? ⇒ Boolean
Macro Methods #
73 74 75 |
# File 'lib/mime/entity.rb', line 73 def multipart? !!(headers['content-type'] =~ /multipart\//) end |
#multipart_boundary ⇒ Object
Auto-generates a boundary if one doesn't yet exist.
82 83 84 85 86 87 88 89 90 |
# File 'lib/mime/entity.rb', line 82 def multipart_boundary return nil unless multipart? @multipart_boundary || begin # Content-Type: multipart/mixed; boundary=000e0cd28d1282f4ba04788017e5 @multipart_boundary = String.random(25) headers['content-type'] = "multipart/#{multipart_type}; boundary=#{@multipart_boundary}" @multipart_boundary end end |
#parsed ⇒ Object
26 27 28 |
# File 'lib/mime/entity.rb', line 26 def parsed IETF::RFC2045.parse_rfc2045_from(@raw) end |
#part_filename ⇒ Object
95 96 97 98 99 100 |
# File 'lib/mime/entity.rb', line 95 def part_filename # Content-Disposition: attachment; filename="summary.txt" if headers['content-disposition'] =~ /; filename=[\"\']?([^\"\']+)/ $1 end end |
#save_to_file(path = nil) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/mime/entity.rb', line 122 def save_to_file(path=nil) filename = path if path && !File.exists?(path) # If path doesn't exist, assume it's a filename filename ||= path + '/' + part_filename if path && # If path does exist, and we're saving an attachment, use the attachment filename filename ||= ( ? part_filename : path) # If there is no path and we're saving an attachment, use the attachment filename; otherwise use path (whether it is present or not) filename ||= '.' # No path supplied, and not saving an attachment. We'll just save it in the current directory. if File.directory?(filename) i = 0 begin i += 1 filename = filename + "/attachment-#{i}" end until !File.exists(filename) end # After all that trouble to get a filename to save to... File.open(filename, 'w') do |file| file << decoded_content end end |
#to_s ⇒ Object
Renders this data structure into a string, encoded
144 145 146 147 148 149 150 151 |
# File 'lib/mime/entity.rb', line 144 def to_s multipart_boundary # initialize the boundary if necessary headers.inject('') {|a,(k,v)| a << "#{MIME.capitalize_header(k)}: #{v}\r\n"} + "\r\n" + if content.is_a?(Array) "\r\n--#{multipart_boundary}\r\n" + content.collect {|part| part.to_s }.join("\r\n--#{multipart_boundary}\r\n") + "\r\n--#{multipart_boundary}--\r\n" else content.to_s end end |