]> git.cworth.org Git - sup/blob - lib/sup/mbox.rb
f267b3b03aebbe846e7b3b08148cf7c72797a8a8
[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         /^(List-Subscribe):\s*(.*?)\s*$/i,
34         /^(List-Unsubscribe):\s*(.*?)\s*$/i,
35         /^(Status):\s*(.*?)\s*$/i: header[last = $1] = $2
36       when /^(Message-Id):\s*(.*?)\s*$/i: header[mid_field = last = $1] = $2
37
38       ## these next three can occur multiple times, and we want the
39       ## first one
40       when /^(Delivered-To):\s*(.*)$/i,
41         /^(X-Original-To):\s*(.*)$/i,
42         /^(Envelope-To):\s*(.*)$/i: header[last = $1] ||= $2
43
44       when /^\r*$/: break
45       when /^\S+:/: last = nil # some other header we don't care about
46       else
47         header[last] += " " + line.chomp.gsub(/^\s+/, "") if last
48       end
49     end
50
51     if mid_field && header[mid_field] && header[mid_field] =~ /<(.*?)>/
52       header[mid_field] = $1
53     end
54
55     header.each do |k, v|
56       next unless Rfc2047.is_encoded? v
57       header[k] =
58         begin
59           Rfc2047.decode_to $encoding, v
60         rescue Errno::EINVAL, Iconv::InvalidEncoding, Iconv::IllegalSequence => e
61           Redwood::log "warning: error decoding RFC 2047 header (#{e.class.name}): #{e.message}"
62           v
63         end
64     end
65     header
66   end
67   
68   ## never actually called
69   def read_body f
70     body = []
71     f.each_line do |l|
72       break if l =~ BREAK_RE
73       body << l.chomp
74     end
75     body
76   end
77
78   module_function :read_header, :read_body
79 end
80 end