]> git.cworth.org Git - sup/blob - lib/sup/mbox.rb
Merge branch 'speedy-index' into next
[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 /^$/: 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   def read_body f
69     body = []
70     f.each_line do |l|
71       break if l =~ BREAK_RE
72       body << l.chomp
73     end
74     body
75   end
76
77   module_function :read_header, :read_body
78 end
79 end