]> git.cworth.org Git - sup/blob - lib/sup/mbox.rb
e9787ca9718ddde67881bea94ff3e304e853302d
[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   HEADER_RE = /\s*(.*?)\s*/
15
16   def read_header f
17     header = {}
18     last = nil
19
20     ## i do it in this weird way because i am trying to speed things up
21     ## when scanning over large mbox files.
22     while(line = f.gets)
23       case line
24       ## these three can occur multiple times, and we want the first one
25       when /^(Delivered-To):#{HEADER_RE}$/i,
26         /^(X-Original-To):#{HEADER_RE}$/i,
27         /^(Envelope-To):#{HEADER_RE}$/i: header[last = $1] ||= $2
28
29       when /^(From):#{HEADER_RE}$/i,
30         /^(To):#{HEADER_RE}$/i,
31         /^(Cc):#{HEADER_RE}$/i,
32         /^(Bcc):#{HEADER_RE}$/i,
33         /^(Subject):#{HEADER_RE}$/i,
34         /^(Date):#{HEADER_RE}$/i,
35         /^(References):#{HEADER_RE}$/i,
36         /^(In-Reply-To):#{HEADER_RE}$/i,
37         /^(Reply-To):#{HEADER_RE}$/i,
38         /^(List-Post):#{HEADER_RE}$/i,
39         /^(List-Subscribe):#{HEADER_RE}$/i,
40         /^(List-Unsubscribe):#{HEADER_RE}$/i,
41         /^(Status):#{HEADER_RE}$/i,
42         /^(X-\S+):#{HEADER_RE}$/: header[last = $1] = $2
43       when /^(Message-Id):#{HEADER_RE}$/i: header[mid_field = last = $1] = $2
44
45       when /^\r*$/: break
46       when /^\S+:/: last = nil # some other header we don't care about
47       else
48         header[last] += " " + line.chomp.gsub(/^\s+/, "") if last
49       end
50     end
51
52     if mid_field && header[mid_field] && header[mid_field] =~ /<(.*?)>/
53       header[mid_field] = $1
54     end
55
56     header.each do |k, v|
57       next unless Rfc2047.is_encoded? v
58       header[k] =
59         begin
60           Rfc2047.decode_to $encoding, v
61         rescue Errno::EINVAL, Iconv::InvalidEncoding, Iconv::IllegalSequence => e
62           Redwood::log "warning: error decoding RFC 2047 header (#{e.class.name}): #{e.message}"
63           v
64         end
65     end
66     header
67   end
68   
69   module_function :read_header
70 end
71 end