lib/sup/util.rb in sup-1.0 vs lib/sup/util.rb in sup-1.1

- old
+ new

@@ -2,18 +2,19 @@ require 'thread' require 'lockfile' require 'mime/types' require 'pathname' +require 'rmail' require 'set' require 'enumerator' require 'benchmark' require 'unicode' require 'unicode/display_width' require 'fileutils' -class Lockfile +module ExtendedLockfile def gen_lock_id Hash[ 'host' => "#{ Socket.gethostname }", 'pid' => "#{ Process.pid }", 'ppid' => "#{ Process.ppid }", @@ -35,10 +36,11 @@ h end def touch_yourself; touch path end end +Lockfile.send :prepend, ExtendedLockfile class File # platform safe file.link which attempts a copy if hard-linking fails def self.safe_link src, dest begin @@ -104,11 +106,11 @@ end a end end - class Serialize + module CustomizedSerialize ## Don't add MIME-Version headers on serialization. Sup sometimes want's to serialize ## message parts where these headers are not needed and messing with the message on ## serialization breaks gpg signatures. The commented section shows the original RMail ## code. def calculate_boundaries(message) @@ -116,52 +118,11 @@ # unless message.header['MIME-Version'] # message.header['MIME-Version'] = "1.0" # end end end - - class Header - - # Convert to ASCII before trying to match with regexp - class Field - - class << self - def parse(field) - field = field.dup.to_s - field = field.fix_encoding!.ascii - if field =~ EXTRACT_FIELD_NAME_RE - [ $1, $'.chomp ] - else - [ "", Field.value_strip(field) ] - end - end - end - end - - ## Be more cautious about invalid content-type headers - ## the original RMail code calls - ## value.strip.split(/\s*;\s*/)[0].downcase - ## without checking if split returned an element - - # This returns the full content type of this message converted to - # lower case. - # - # If there is no content type header, returns the passed block is - # executed and its return value is returned. If no block is passed, - # the value of the +default+ argument is returned. - def content_type(default = nil) - if value = self['content-type'] and ct = value.strip.split(/\s*;\s*/)[0] - return ct.downcase - else - if block_given? - yield - else - default - end - end - end - end + Serialize.send :prepend, CustomizedSerialize end class Module def bool_reader *args args.each { |sym| class_eval %{ def #{sym}?; @#{sym}; end } } @@ -390,12 +351,27 @@ fail "Could not create valid #{to_encoding.inspect} string out of: '#{self.to_s}'." unless valid_encoding? self end + ## Decodes UTF-7 and returns the resulting decoded string as UTF-8. + ## + ## Ruby doesn't supply a UTF-7 encoding natively. There is + ## Net::IMAP::decode_utf7 which only handles the IMAP "modified UTF-7" + ## encoding. This implementation is inspired by that one but handles + ## standard UTF-7 shift characters and not the IMAP-specific variation. + def decode_utf7 + gsub(/\+([^-]+)?-/) { + if $1 + ($1 + "===").unpack("m")[0].encode(Encoding::UTF_8, Encoding::UTF_16BE) + else + "+" + end + } + end + def normalize_whitespace - fix_encoding! gsub(/\t/, " ").gsub(/\r/, "") end unless method_defined? :ord def ord @@ -403,11 +379,11 @@ end end unless method_defined? :each def each &b - each_line &b + each_line(&b) end end ## takes a list of words, and returns an array of symbols. typically used in ## Sup for translating Xapian's representation of a list of labels (a string) @@ -505,11 +481,13 @@ ret = [] each_with_index { |x, i| ret << yield(x, i) } ret end - def sum; inject(0) { |x, y| x + y }; end + if not method_defined? :sum + def sum; inject(0) { |x, y| x + y }; end + end def map_to_hash ret = {} each { |x| ret[x] = yield(x) } ret @@ -561,10 +539,12 @@ class Array def flatten_one_level inject([]) { |a, e| a + e } end - def to_h; Hash[*flatten]; end + if not method_defined? :to_h + def to_h; Hash[*flatten_one_level]; end + end def rest; self[1..-1]; end def to_boolean_h; Hash[*map { |x| [x, true] }.flatten]; end def last= e; self[-1] = e end