]> git.cworth.org Git - sup/blob - lib/sup/mbox.rb
encoding and rfc2047 header support
[sup] / lib / sup / mbox.rb
1 require "sup/mbox/loader"
2 require "sup/mbox/ssh-file"
3 require "sup/mbox/ssh-loader"
4 require "sup/rfc2047"
5
6 module Redwood
7
8 ## some utility functions. actually these are not mbox-specific at all
9 ## and should be moved somewhere else.
10 ##
11 ## TODO: move functionality to somewhere better, like message.rb
12 module MBox
13   BREAK_RE = /^From \S+/
14
15   def read_header f
16     header = {}
17     last = nil
18
19     ## i do it in this weird way because i am trying to speed things up
20     ## when scanning over large mbox files.
21     while(line = f.gets)
22       case line
23       when /^(From):\s+(.*?)\s*$/i,
24         /^(To):\s+(.*?)\s*$/i,
25         /^(Cc):\s+(.*?)\s*$/i,
26         /^(Bcc):\s+(.*?)\s*$/i,
27         /^(Subject):\s+(.*?)\s*$/i,
28         /^(Date):\s+(.*?)\s*$/i,
29         /^(References):\s+(.*?)\s*$/i,
30         /^(In-Reply-To):\s+(.*?)\s*$/i,
31         /^(Reply-To):\s+(.*?)\s*$/i,
32         /^(List-Post):\s+(.*?)\s*$/i,
33         /^(Status):\s+(.*?)\s*$/i: header[last = $1] = $2
34       when /^(Message-Id):\s+(.*?)\s*$/i: header[mid_field = last = $1] = $2
35
36       ## these next three can occur multiple times, and we want the
37       ## first one
38       when /^(Delivered-To):\s+(.*)$/i,
39         /^(X-Original-To):\s+(.*)$/i,
40         /^(Envelope-To):\s+(.*)$/i: header[last = $1] ||= $2
41
42       when /^$/: break
43       when /:/: last = nil # some other header we don't care about
44       else
45         header[last] += " " + line.chomp.gsub(/^\s+/, "") if last
46       end
47     end
48
49     if mid_field && header[mid_field] && header[mid_field] =~ /<(.*?)>/
50       header[mid_field] = $1
51     end
52
53     header.each do |k, v|
54       next unless Rfc2047.is_encoded? v
55       header[k] =
56         begin
57           Rfc2047.decode_to $encoding, v
58         rescue Errno::EINVAL, Icon::InvalidEncoding, Iconv::IllegalSequence => e
59           Redwood::log "warning: error decoding RFC 2047 header: #{e.message}"
60           v
61         end
62     end
63     header
64   end
65   
66   def read_body f
67     body = []
68     f.each_line do |l|
69       break if l =~ BREAK_RE
70       body << l.chomp
71     end
72     body
73   end
74
75   module_function :read_header, :read_body
76 end
77 end