#-- # rbmh/rmail.rb : rbmhshow 0.4.2 # # Copyright (C) 2004--2005 Merlin Hughes # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # #++ # RMail tweaking # Add in the extra methods and attributes I need. # Could do this on a per-object basis if appropriate. class RMail::StreamParser def parse_mime input = RMail::Parser::PushbackReader.new(@input) input.chunk_size = @chunk_size if @chunk_size parse_low(input, 1) return nil end end class RMail::Message attr_accessor :context, :parent, :raw, :path # TODO: dump path, have flag for reshow or somesuch def show(out) @context.handlers[type].show(self, out) end def store(parts, path) @context.handlers[type].store(self, parts, path) end def type # TODO: enable type guessing from suffixes/content? # basically some .htm attachments have type app.../octet... header.content_type("type/unspecified") end def section if @parent.nil? nil else i = 1 parts = @parent.body i += 1 until parts.nil? || (i > parts.length) or self.equal?(parts[i - 1]) prefix = @parent.section prefix ? "#{prefix}.#{i}" : i.to_s end end def filename name = header.param("Content-Type", "name") || header.param("Content-Disposition", "filename") if name name.tr('/', '_') else suffix = @context.suffixes[type] suffix = suffix ? ".#{suffix}" : "" infix = (@parent.nil? or @parent.type != "multipart/alternative") ? section : @parent.section prefix = infix ? "part-" : "body" "#{prefix}#{infix}#{suffix}" end end # TODO: cope with path not being set (e.g., app/p7 S/MIME) def msgpath msgpath = @path mhpath = "#{context.profile.path}/" if mhpath == msgpath[0, mhpath.length] msgpath = msgpath[mhpath.length, msgpath.length - mhpath.length] end msgpath end def folder msgpath =~ MessageRE $1 end def number path =~ MessageRE $2 end def display_name msgpath =~ MessageRE "Message #{$1}\\:#{$2}" end MessageRE = /(.*)\/([^\/]*)$/ end # Globals are evil but the reader is local to the parser... # Could make these statics of the MultipartReader, but whatever # The functioning of this is really dependent on the order of # method calls in parsing: # # Parser creates a MultipartReader, then calls start_multipart_body. # My implementation of that method checks to see if multipart/signed # and if so, invokes capture_begin which returns an array that will # hold the raw body parts. The parser then calls MpReader.next_part # which grabs this array, and starts capturing each part into the # array, ignoring preamble/postamble. $capture_raw = nil # really horrendous hack to capture the raw parts of a multipart/signed class RMail::Parser::MultipartReader alias :orig_read_chunk :read_chunk def read_chunk(chunk_size) chunk = orig_read_chunk(chunk_size) if @raw and (not preamble?) and (not epilogue?) if chunk @raw << chunk else @capture_raw << @raw end end chunk end alias :old_next_part :next_part def next_part if $capture_raw @capture_raw = $capture_raw $capture_raw = nil end @raw = "" if @capture_raw old_next_part end alias :old_pushback :pushback def pushback(s) if @raw index = @raw.length - s.length @raw[index..-1] = '' end old_pushback(s) end end module RBMH class Parser end def Parser.capture_raw $capture_raw = [] end end # module RBMH