From: Sam Roberts Date: 2003-04-18T09:44:36+09:00 Subject: Re: ANN: RFC 2047 decoding library (MIME format for non-ascii in mail headers) --BXVAT5kNtrzKuDFl Content-Type: text/plain; charset=us-ascii Content-Disposition: inline The last version of rfc2047.rb had a bug with stateful encodings, here's the corrected version. Thanks to Josef for pointing it out, and Nobu for pointing out how to fix it! Sam --BXVAT5kNtrzKuDFl Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="rfc2047.rb" # $Id: rfc2047.rb,v 1.3 2003/04/18 00:37:02 sam Exp $ # # An implementation of RFC 2047 decoding. # # This module depends on the iconv library by Nobuyoshi Nakada, which I've # heard may be distributed as a standard part of Ruby 1.8. Many thanks to him # for helping with building and using iconv. # # Thanks to "Josef 'Jupp' Schugt" for pointing out an error with # stateful character sets. # # Copyright (c) Sam Roberts 2003 # # This file is distributed under the same terms as Ruby. require 'iconv' module Rfc2047 WORD = %r{=\?([!#$%&'*+-/0-9A-Z\\^\`a-z{|}~]+)\?([BbQq])\?([!->@-~]+)\?=} # :nodoc: # Decodes a string, +from+, containing RFC 2047 encoded words into a target # character set, +target+. See iconv_open(3) for information on the # supported target encodings. If one of the encoded words cannot be # converted to the target encoding, it is left in its encoded form. def Rfc2047.decode_to(target, from) out = from.gsub(WORD) do |word| charset, encoding, text = $1, $2, $3 # B64 or QP decode, as necessary: case encoding when 'b', 'B' #puts text text = text.unpack('m*')[0] #puts text.dump when 'q', 'Q' # RFC 2047 has a variant of quoted printable where a ' ' character # can be represented as an '_', rather than =32, so convert # any of these that we find before doing the QP decoding. text = text.tr("_", " ") text = text.unpack('M*')[0] # Don't need an else, because no other values can be matched in a # WORD. end # Convert: # # Remember - Iconv.open(to, from)! begin i = Iconv.open(target, charset) text = i.iconv(text) text += i.close #puts text.dump rescue Errno::EINVAL, Iconv::IllegalSequence # Replace with the entire matched encoded word, a NOOP. text = word end end end end --BXVAT5kNtrzKuDFl--