require 'net/http' require 'rubygems' require 'hpricot' module MMS2R ## # Sprint version of MMS2R::Media # # Sprint is an annoying carrier because they think they # are so important that they don't actually transmit # user generated content (like images or videos) directly # in the MMS message. Instead, what they do is hijack the # media that is sent from the cellular subscriber and place # that content on a content server. In place of the media # the recipient receives a HTML part telling the recipient # how great Sprint is with links back to their content server. # Then the recipient has to click through Sprint more pages # to view the content. # # The default subject on these messages from the # carrier is "You have new Picture Mail!" class MMS2R::SprintMedia < MMS2R::Media ## # MMS2R::SprintMedia has to override process() because Sprint # doesn't attach media (images, video, etc.) to its MMS. Media such # as images and videos are hosted on a Sprint content server. # MMS2R::SprintMedia has to pick apart an HTML attachment to find # the URL to the media on Sprint's content server and download # each piece of content. Any text message part of the MMS # if it exists is embedded in the html. def process @logger.info("#{self.class} processing") unless @logger.nil? #sprint MMS are multipart parts = @mail.parts #find the payload html doc = nil parts.each do |p| next unless self.class.part_type?(p).eql?('text/html') d = Hpricot(p.body) title = d.at('title').inner_html doc = d if title =~ /You have new Picture Mail!/ end return if doc.nil? #it was a dud # break it down sprint_phone_number(doc) sprint_process_text(doc) sprint_process_media(doc) end private ## # Digs out where Sprint hides the phone number def sprint_phone_number(doc) c = doc.search("/html/head/comment()").last t = c.content.gsub(/\s+/m," ").strip #@number returned in parent's get_number @number = / name="MDN">(\d+)</.match(t)[1] end ## # pulls out the user text form the MMS and adds the text # to media hash def sprint_process_text(doc) # there is at least one
 with MMS text if text has been included by
      # the user.  (note) we'll have to verify that if they attach multiple texts 
      # to the MMS then Sprint stacks it up in multiple 
's.  The only 
 
      # tag in the document is for text from the user.
      doc.search("/html/body//pre").each do |pre|
        type = 'text/plain'
        text = pre.inner_html.strip
        next if text.empty?
        type, text = transform_text(type, text)
        type, file = sprint_write_file(type, text.strip)
        add_file(type, file) unless type.nil? || file.nil?
      end
    end

    ##
    # Fetch all the media that is referred to in the doc

    def sprint_process_media(doc)
      srcs = Array.new
      # collect all the images in the document, even though
      # they are  tag some might actually refer to video.
      # To know the link refers to vide one must look at the 
      # content type on the http GET response.
      imgs = doc.search("/html/body//img")
      imgs.each do |i|
        src = i.attributes['src']
        # we don't want to double fetch content and we only
        # want to fetch media from the content server, you get
        # a clue about that as there is a RECIPIENT in the URI path
        # of real content
        next unless /mmps\/RECIPIENT\//.match(src)
        next if srcs.detect{|s| s.eql?(src)}
        srcs << src
      end

      #we've got the payload now, go fetch them
      cnt = 0
      srcs.each do |src|
        begin
          url = URI.parse(src)
          #res = Net::HTTP.get_response(url)
          #lets be vanilla stealth
          agent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)"
          res = Net::HTTP.start(url.host, url.port) do |http|
            req = Net::HTTP::Get.new(url.request_uri, {'User-Agent' => agent})
            http.request(req)
          end
        rescue
          @logger.error("#{self.class} processing error, #{$!}") unless @logger.nil?
          next
        end

        # setup the file path and file
        base = /\/RECIPIENT\/([^\/]+)\//.match(src)[1]
        type = res.content_type
        file_name = "#{base}-#{cnt}.#{self.class.default_ext(type)}"
        file = File.join(msg_tmp_dir(),File.basename(file_name))

        # write it and add it to the media hash
        type, file = sprint_write_file(type, res.body, file)
        add_file(type, file) unless type.nil? || file.nil?
        cnt = cnt + 1
      end

    end

    ##
    # Creates a temporary file based on the type

    def sprint_temp_file(type)
      file_name = "#{Time.now.to_f}.#{self.class.default_ext(type)}"
      File.join(msg_tmp_dir(),File.basename(file_name))
    end

    ##
    # Writes the content to a file and returns the type, file as a tuple.
    def sprint_write_file(type, content, file = nil)
      file = sprint_temp_file(type) if file.nil?
      @logger.info("#{self.class} writing file #{file}") unless @logger.nil?
      File.open(file,'w'){ |f|
        f.write(content)
      }
      return type, file
    end

  end
end