# File lib/sup/source.rb, line 70 def initialize uri, initial_offset=nil, usual=true, archived=false, id=nil raise ArgumentError, "id must be an integer: #{id.inspect}" unless id.is_a? Fixnum if id @uri = uri @cur_offset = initial_offset @usual = usual @archived = archived @id = id @dirty = false end
utility method to read a raw email header from an IO stream and turn it into a hash of key-value pairs. minor special semantics for certain headers.
THIS IS A SPEED-CRITICAL SECTION. Everything you do here will have a significant effect on Sup's processing speed of email from ALL sources. Little things like string interpolation, regexp interpolation, += vs <<, all have DRAMATIC effects. BE CAREFUL WHAT YOU DO!
# File lib/sup/source.rb, line 115 def self.parse_raw_email_header f header = {} last = nil while(line = f.gets) case line ## these three can occur multiple times, and we want the first one when /^(Delivered-To|X-Original-To|Envelope-To):\s*(.*?)\s*$/; header[last = $1.downcase] ||= $2 ## regular header: overwrite (not that we should see more than one) ## TODO: figure out whether just using the first occurrence changes ## anything (which would simplify the logic slightly) when /^([^:\s]+):\s*(.*?)\s*$/; header[last = $1.downcase] = $2 when /^\r*$/; break # blank line signifies end of header else if last header[last] << " " unless header[last].empty? header[last] << line.strip end end end %w(subject from to cc bcc).each do |k| v = header[k] or next next unless Rfc2047.is_encoded? v header[k] = begin Rfc2047.decode_to $encoding, v rescue Errno::EINVAL, Iconv::InvalidEncoding, Iconv::IllegalSequence => e #debug "warning: error decoding RFC 2047 header (#{e.class.name}): #{e.message}" v end end header end
# File lib/sup/source.rb, line 154 def Source.expand_filesystem_uri uri uri.gsub "~", File.expand_path("~") end
# File lib/sup/source.rb, line 87 def == o; o.uri == uri; end
check should throw a FatalSourceError or an OutOfSyncSourcError if it can detect a problem. it is called when the sup starts up to proactively notify the user of any source problems.
# File lib/sup/source.rb, line 94 def check; end
# File lib/sup/source.rb, line 88 def done?; start_offset.nil? || (self.cur_offset ||= start_offset) >= end_offset; end
yields successive offsets and labels, starting at cur_offset.
when implementing a source, you can overwrite either each or next. the default each just calls next over and over.
# File lib/sup/source.rb, line 100 def each self.cur_offset ||= start_offset until done? offset, labels = self.next yield offset, labels end end
overwrite me if you have a disk incarnation (currently used only for sup-sync-back)
# File lib/sup/source.rb, line 82 def file_path; nil end
# File lib/sup/source.rb, line 89 def is_source_for? uri; uri == @uri; end
# File lib/sup/source.rb, line 86 def reset!; seek_to! start_offset; end
# File lib/sup/source.rb, line 85 def seek_to! o; self.cur_offset = o; end
# File lib/sup/source.rb, line 84 def to_s; @uri.to_s; end
# File lib/sup/source.rb, line 158 def cur_offset= o @cur_offset = o @dirty = true end
convenience function
# File lib/sup/source.rb, line 152 def parse_raw_email_header f; self.class.parse_raw_email_header f end