From: John Browning Date: 2007-02-27T04:48:36+09:00 Subject: Re: [QUIZ] Mailing List Files (#115) --Apple-Mail-2-938571758 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed #!/usr/bin/env ruby # require 'net/http' require 'strscan' require 'cgi' class GetAttachments def initialize(id) @id = id @url = "blade.nagaokaut.ac.jp" @params = "/cgi-bin/scat.rb/ruby/ruby-talk/" + @id @attachments = Array.new end def store_attachments # get the attachment, then store it. self.fetch_attachments self.save_attachments end def fetch_attachments # get the page and extract email from pre tags @page = Net::HTTP.get(@url, @params) @page =~ /\(.+)\<\/pre\>/im @email = $1 # get rid of everything before the first part separator # NB boundary separators assumed to start with -- No RFC guarantee this is always right. @email.sub!(/\A([^-]|-[^-])+/m, '') # create a scanner and grab header / body pairs @mime_scanner = StringScanner.new(@email) # this regex looks for a boundary line beginning -- then a line beginning Content then other header stuff then a blank line then body stuff # then either another of the same or a boundary then an empty line. Lookahead ?= prevents using part of next token. while @mime_scanner.scan(/(^--.+?\nContent.*?^\s*$)(.*?)(?=^--.+? \n(Content|^\s*$))/im) do attachment = Hash.new # translate html escapes and get rid of html mark-up that seems to creep into body, plus starting and trailing spaces attachment[:header] = CGI.unescapeHTML( @mime_scanner[1] ) attachment[:body] = CGI.unescapeHTML( @mime_scanner[2].gsub(/\A \s+/,'').chomp.gsub(/\<[^\>]*\>/, '') ) @attachments = @attachments << attachment end end def save_attachments @attachments.each do |a| # skip parts that aren't attachments next if !(a[:header] =~ /Content-Disposition:\s*attachment/i) # grab file name and encoding. # quit with error if no filename. if ( a[:header] =~ /filename\s*\=\s*\"?([a-z\-\_\ 0-9\.\%\$\@ \!]+)\"?\s*(\n|\;)/i || a[:header] =~ /name\s*\=\s*\"?([a-z\-\_\ 0-9\. \%\$]+)\"?\s*(\n|\;)/i ) # do above as || to favor filename over name, which may be unnecessary # NB hasty assumptions about file name characters filename = $1 else puts "Could not parse filename for attachment from #{a [:header]}" exit 1 end if ( a[:header] =~ /Content-Transfer-Encoding:\s*\"?([a-z\- \_0-9]+)\"?\s*?(\n|\;)/i ) encoding = $1 end # if the filename specifies a directory and it exists, use it. Otherwise just put in pwd. # NB clobbers any files with same name as attachment. if ( File.exist?(File.dirname(filename)) ) file = File.new(filename, "w+") else file = File.new(filename = File.basename(filename), "w+") end # decode if necessary case encoding when /base64/i file << a[:body].unpack("m").first when /quoted-printable/i file << a[:body].unpack("M").first else file << a[:body] end # notify what's been done, clean up and go home file.close puts "Stored attachment from message #{@id} at #{@url} in # {File.expand_path(filename)}" exit 0 end end end ARGV.each do |arg| @ga = GetAttachments.new(arg) @ga.store_attachments end ........................................................................ ............................ John Browning On 23 Feb 2007, at 14:00, Ruby Quiz wrote: > The three rules of Ruby Quiz: > > 1. Please do not post any solutions or spoiler discussion for this > quiz until > 48 hours have passed from the time on this message. > > 2. Support Ruby Quiz by submitting ideas as often as you can: > > http://www.rubyquiz.com/ > > 3. Enjoy! > > Suggestion: A [QUIZ] in the subject of emails about the problem > helps everyone > on Ruby Talk follow the discussion. Please reply to the original > quiz message, > if you can. > > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- > =-=-=-=-=-=-= > > The Ruby Talk mailing list archives will show files attached to > incoming > messages. However, it's not always easy to get at the data from > these files > using the archives alone. The attachments are sometimes displayed in > not-too-readable formats: > > http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/190780 > > http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/226884 > > This is tough for those of us who like to play with Ruby Quiz > solutions. > > This week's quiz is to write a program that takes a message id > number as a > command-line argument and "downloads" any attachments from that > message. Assume > message ids are for Ruby Talk posts by default, but you may want to > provide an > option to override that so we can support lists like Ruby Core as > well. > > If no path is given, write the attachments to the working > directory. When there > is a path, your code should place the files there instead. > > --Apple-Mail-2-938571758--