Pastie now auto-senses if line-wrap is a bad or good idea. Feedback?
## mark a section (Learn more)
This paste will be private.
#!/usr/bin/env ruby # use it like so: Net::HTTP.multi_post_form(url, params) require 'net/http' class Net::HTTP def self.multi_post_form(url, params) req = Post.new(url.path) req.multipart_params = params req.basic_auth url.user, url.password if url.user new(url.host, url.port).start {|http| http.request(req) } end end module Net class HTTP class Post def multipart_params=(param_hash={}) boundary_token = [Array.new(8) {rand(256)}].join self.content_type = "multipart/form-data; boundary=#{boundary_token}" boundary_marker = "--#{boundary_token}\r\n" self.body = param_hash.map { |param_name, param_value| boundary_marker + text_to_multipart(param_name, param_hash.delete(param_name).to_s) unless param_value.respond_to?(:read) || param_value.kind_of?(Hash) }.join('') self.body += param_hash.map { |param_name, param_value| boundary_marker + file_to_multipart(param_name, param_value) }.join('') self.body += "--#{boundary_token}--\r\n" end protected def file_to_multipart(key, file) if (file.kind_of? Hash) file_data = file[:data] file_name = file[:name] mime_type = file[:mime] || "application/octet-stream" else file_data = file.read file_name = File.basename(file.path) mime_type = "application/octet-stream" end part = %Q|Content-Disposition: form-data; name=\"#{key}\"; filename="#{file_name}"\r\n| part += "Content-Transfer-Encoding: binary\r\n" part += "Content-Type: #{mime_type}\r\n\r\n#{file_data}\r\n" end def text_to_multipart(key,value) "Content-Disposition: form-data; name=\"#{key}\"\r\n\r\n#{value}\r\n" end end end end class User require 'rubygems' require 'sqlite3' def self.db SQLite3::Database.new(File.join(ENV["HOME"], "tumblr.db")) end def self.create_table db.execute("CREATE TABLE users (email varchar, email_login varchar, password varchar)"); end def self.find(email) begin email_login, password = db.get_first_row("SELECT email_login, password FROM users WHERE email = ?", email) rescue SQLite3::SQLException create_table end if (email_login && password) return {:email => email_login, :password => password} end nil end def self.add(email, email_login, password) begin db.execute("DELETE FROM users WHERE email = ?", email) if (find(email)) rescue SQLite3::SQLException create_table end db.execute("INSERT INTO users (email, email_login, password) VALUES (?, ?, ?)", email, email_login, password) end end class Tumblr require 'net/http' def initialize(email, password) @email, @password = email, password end def params { 'email' => @email, 'password' => @password } end def post_regular(subject, body) p = params.merge({ 'type' => 'regular', 'title' => subject, 'body' => body }) res = Net::HTTP.post_form(URI.parse("http://www.tumblr.com/api/write"), p) end def post_image(caption, file_name, file_data, mime) p = params.merge({ 'type' => 'photo', 'caption' => caption, 'data' => {:name => file_name, :data => file_data, :mime => mime} }) res = Net::HTTP.multi_post_form(URI.parse("http://www.tumblr.com/api/write"), p) # res = Net::HTTP.multi_post_form(URI.parse("http://localhost:2000/"), p) puts res.inspect end end class Part require 'base64' attr_reader :content_type, :filename, :contents def initialize(text) @filename = "" header, body = text.split("\n\n") @content_type = header.match(/Content-Type:\s(.*);/i)[1] @filename = header.match(/name="?(.*)"?/i)[1] if header.match(/name="?(.*)"?/i) if (header.match(/Content-Transfer-Encoding: base64/)) @contents = Base64.decode64(body) else @contents = body end end end email = STDIN.read email = open('email_iphone.txt').read if email.empty? #File.open('email_iphone.txt', 'w') { |f| f.puts email } from = email.match(/^From:.*[^a-zA-Z0-9\.\-_]([a-zA-Z0-9\.\-_]+@[\w\.-]+)/)[1] subject = email.match(/^Subject: (.*)$/)[1] boundary = email.match(/boundary="?(.*)"?/)[1] if email.match(/boundary=/) File.open('log.txt', 'a') { |f| f.puts Time.now.to_s + " Subject: #{subject}"} post_body = "" file_name = "" file_data = "" file_mime = "" if boundary # multi-part email.sub!(/^.+?[^"]#{boundary}/m, '') email.split(/-*#{boundary}/).each do |part| next if part.empty? || part.match(/^\s*-+\s*$/) next unless part.match(/Content-Type:/i) p = Part.new(part) case p.content_type when 'text/plain' post_body = p.contents when /image/ file_data = p.contents file_name = p.filename file_mime = p.content_type end end else email.sub!(/^.+?\n\n/m, '') post_body = email end if (post_body.match(/email:/i) && post_body.match(/password:/i)) User.add(from, post_body.match(/email:\s*(.*)$/i)[1], post_body.match(/password:\s*(.*)$/i)[1]) else user = User.find(from) t = Tumblr.new(user[:email], user[:password]) unless file_name.empty? t.post_image(subject || post_body, file_name, file_data, file_mime) else t.post_regular(subject, post_body) end end
From the Design Piracy series on my blog: