public
Last active

  • Download Gist
app/models/image.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
attr_accessor :attachment64
 
before_validation :save_attachment64
 
has_attached_file :attachment, :storage => :s3, :s3_credentials => "#{RAILS_ROOT}/config/aws.yml",
:path => "messages_images/:id/:style/:filename",
:styles => { :original => ['1000x600>'],
:normal => ['500x500>'],
:stack => ['137x133>']
},
:default_style => :normal
 
private
def save_attachment64
File.open("tmp/reply.png", "wb") { |f| f.write(Datafy::decode_data_uri(attachment64)[0]) }
self.attachment = File.open("tmp/reply.png", "r")
end
form.html.haml
Haml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
:javascript
$(function() {
var canvas = document.getElementById('imageView');
$('#new_message').submit(function() {
$('#message_images_attributes_0_attachment64').val(canvas.toDataURL());
});
$('.erase').click(function() {
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
})
});
 
- form_for @message do |f|
.send= image_submit_tag 'send.png'
.erase= image_tag 'erase.png'
 
#container
<canvas id="imageView" width="536" height="984">
</canvas>
- f.fields_for "images", Image.new do |i|
= i.hidden_field :attachment64
lib/datafy.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
#!/usr/bin/env ruby -w
 
=begin
 
Creates a data: URI as described by RFC 2397
[http://www.ietf.org/rfc/rfc2397.txt]
 
by: Eric Hodel <drbrain@segment7.net>
 
$ echo 'Here is some text to datafy.' | ./datafy.rb -m text/plain
data:text/plain,Here%20is%20some%20text%20to%20datafy.%0A
 
$ echo 'Here is some text to datafy.' | ./datafy.rb -m application/octet-stream
data:application/octet-stream;base64,SGVyZSBpcyBzb21lIHRleHQgdG8gZGF0YWZ5Lgo=
 
Datafy will also fetch and encode from an HTTP URL: ./datafy.rb -u http://...
It will recursively encode stylsheets, img src=, link href=, and normalize
URLs.
 
=end
 
require 'base64'
require 'uri'
require 'net/http'
require 'cgi'
 
module Datafy
 
A_HREF_RE = /a([^>]+)href="([^"]+)"/im
LINK_HREF_RE = /link([^>]+)href="([^"]+)"/im
IMG_SRC_RE = /img([^>]+)src="([^"]+)"/im
 
CSS_URL_RE = /url\("?([^?"]+)"+\)/im
 
def Datafy::make_data_uri(content, content_type)
outuri = 'data:' + content_type
 
unless content_type =~ /^text/i # base64 encode if not text
outuri += ';base64'
content = encode64(content).gsub("\n", '')
else
content = CGI::escape(content)
end
 
outuri += ",#{content}"
end
 
def Datafy::decode_data_uri(uri)
uri = URI.parse(uri) unless uri.kind_of? URI
 
raise ArgumentError.new("Incorrect URI scheme, expected data:, got #{uri.scheme}") unless
uri.scheme == 'data'
 
# extract the media type and data
uri.opaque =~ /^([^,]+)?,(.*)$/
 
mediatype = $1
data = $2
 
# if the media is base64 encoded, set the flag and strip it
if base64 = $1 =~ /^(.+);base64$/
mediatype = $1
end
 
# decode
if base64
data = Base64.decode64(data)
else
data = CGI::unescape(data)
end
 
return data, mediatype
end
 
def Datafy::page_to_data_uri(uri)
uri = URI.parse(uri) unless uri.kind_of? URI
 
$stderr.puts "working on #{uri}" if $DEBUG
 
page = fetch_page(uri)
body = page.body
content_type = page['content-type'].downcase
 
$stderr.puts "has content type #{content_type}" if $DEBUG
 
encode_page(body, content_type, uri)
end
 
private
 
def Datafy::encode_page(body, content_type, base_uri)
case content_type
when 'text/html'
$stderr.puts "filtering 'A's" if $DEBUG
 
body = body.gsub(A_HREF_RE) {
href_uri = cleanup_uri(base_uri, $2)
%Q!a#{$1}href="#{href_uri}"!
}
 
$stderr.puts "filtering 'IMG's" if $DEBUG
 
body = body.gsub(IMG_SRC_RE) {
img_uri = cleanup_uri(base_uri, $2)
%Q!img#{$1}src="#{page_to_data_uri(img_uri)}"!
}
$stderr.puts "filtering 'LINK's" if $DEBUG
 
body = body.gsub(LINK_HREF_RE) {
href_uri = cleanup_uri(base_uri, $2)
%Q!link#{$1}href="#{page_to_data_uri(href_uri)}"!
}
 
when 'text/css'
$stderr.puts "filtering CSS urls" if $DEBUG
body = body.gsub(CSS_URL_RE) {
url_contents = ''
uri = cleanup_uri(base_uri, $1)
if uri.scheme != 'data'
url_contents = page_to_data_uri(uri)
else
url_contents = uri.opaque
end
%Q!url("#{url_contents}")!
}
 
end
 
return make_data_uri(body, content_type)
end
 
def Datafy::cleanup_uri(base, link)
$stderr.puts "cleaning #{link} using base #{base}" if $DEBUG
link = URI.parse(link) unless link.kind_of? URI
 
return link if link.scheme == 'mailto'
 
# make sure its absolute
if link.relative? && link.path[0].chr != '/'
path_ary = base.path.split('/')
link.path = path_ary[0...path_ary.length-1].join('/') + '/' +
link.path
end
 
# make sure all the components are there
link.scheme = base.scheme unless link.scheme
link.host = base.host unless link.host
link.port = base.port unless link.port
 
link
end
 
def Datafy::fetch_page(uri)
response = nil
begin
Net::HTTP.start( uri.host, uri.port ) {|http|
uri.normalize!
response, = http.get(uri.path)
}
rescue Net::ProtoRetriableError => err
uri = URI.parse(err.response['location'])
retry if uri.host
rescue Net::ProtoFatalError => err
raise RuntimeError.new("404 encountered at #{uri} fetching page")
end
 
return response
end
end
 
if __FILE__ == $0 # don't polute the namespace with help
 
require 'getoptlong'
 
def help(exitcode = 0)
$stderr.puts "datafy.rb, an RFC2397 data: uri utility"
$stderr.puts "by Eric Hodel <drbrain@segment7.net>"
$stderr.puts
$stderr.puts "usage: #{$0} [-m=mimetype] [filename]"
$stderr.puts
$stderr.puts "options:"
$stderr.puts " -m=mimetype the mime type of the file to be encoded"
$stderr.puts
$stderr.puts "#{$0} can be called with a filename and will attempt to"
$stderr.puts "determine the file using file(1) if it exists on your system"
$stderr.puts "otherwise the mime type must be specified. #{$0} can also"
$stderr.puts "read a file from stdin, the mime type must be specified in"
$stderr.puts "this mode."
 
exit(exitcode)
end
 
url = ''
content_type = ''
 
opts = GetoptLong.new(
["-m", GetoptLong::REQUIRED_ARGUMENT],
['-u', GetoptLong::REQUIRED_ARGUMENT],
["-h", GetoptLong::NO_ARGUMENT]
)
 
opts.each { |opt, arg|
case opt
when "-h" then help()
when "-m" then content_type = arg.downcase
when '-u' then url = arg
end
}
 
if url.empty?
filename = ARGV[0]
 
content = ''
if filename
content = File.open(filename) { |fp| fp.read }
begin
if content_type.empty?
content_type = /^#{filename}: ([^,]+).*$/.match(`file -i #{filename}`)[1].downcase
end
rescue
content_type = nil
end
else
content = $stdin.read
end
 
if content_type.nil? or content_type.empty?
$stderr.puts 'Cannot determine MIME type of file, please use -m'
$stderr.puts
help(1)
end
 
puts Datafy.make_data_uri(content, content_type)
else
begin
page, = Datafy.decode_data_uri(Datafy.page_to_data_uri(url))
puts page
rescue => err
$stderr.puts "#{err.class.name} encoding #{url}:\n#{err}"
end
end
 
end # __FILE__ == $0

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.