markevans / dragonfly

A Ruby gem for on-the-fly processing - suitable for image uploading in Rails, Sinatra and much more!
http://markevans.github.io/dragonfly
MIT License
2.12k stars 244 forks source link

Base64 encoding should not have linefeed characters #447

Open Odaeus opened 8 years ago

Odaeus commented 8 years ago

I was trying to use the #b64_data method to encode an image into base64 for insertion directly into an HTML IMG element attribute. I noticed it was failing because the data contains linefeed ("\n") characters to wrap the text.

I think the fix is to modify the Content#b64_data method to use Base64.strict_encode64 as the Ruby docs say that doesn't add linefeeds. I hope to submit a PR for this but wanted to create an issue in case others have the same problem.

markevans commented 8 years ago

Which browser are you using out of interest? I tested in Safari and Chrome (but not IE) and they seemed to work ok for me with "\n" characters

Odaeus commented 8 years ago

Ah sorry, I oversimplified! I'm actually passing the data to Javascript code (Polymer's iron-image web component to be exact). It doesn't display and it also confuses the Chrome Development Console, which identifies it as B64 encoded image but gives up after the newline. I imagine browser attribute parsing is more tolerant to this.

I also checked the data URL scheme RFC, which is silent on the issue (not really in the remit), however the (Base-N encodings RFC)[https://www.ietf.org/rfc/rfc4648.txt] specifically prohibits the insertion of newlines in this context:

Implementations MUST NOT add line feeds to base-encoded data unless the specification referring to this document explicitly directs base encoders to add line feeds after a specific number of characters.

That section in the standard basically appears to be a complaint about MIME-style encoding being overly prevalent. As evidenced by Ruby's own Base64 encoding being wrong by default!

markevans commented 8 years ago

Ok - it seems almost as though it isn't well specified whether newlines are ok are not (the statement from RFC 4648 seems to me to delegate responsibility to the "other" spec referring to it), but taking them out with strict encode can't hurt.

Odaeus commented 8 years ago

Sorry for taking so long to get back to you.

So I think Polymer's iron-image component breaks because it sets the image by doing el.style.backgroundImage = "url('" + src + "')". Which fails when the base64 has newlines. So yes it does work with strict base64.

The error I referred to in Chrome also appears to be due to URL detection and how the dev console handles strings. Creating a new image element and assigning it to src normalises the string for example, so reading it back out means the Console's URL detection works. This is a very minor problem.