orbeon / orbeon-forms

Orbeon Forms is an open source web forms solution. It includes an XForms engine, the Form Builder web-based form editor, and the Form Runner runtime.
http://www.orbeon.com/
GNU Lesser General Public License v2.1
517 stars 221 forks source link

Implement support for data: in xf:output mediatype="image/*" #1065

Closed avernet closed 9 years ago

avernet commented 11 years ago

Test case included in a comment below.

avernet commented 11 years ago

Simpler test case (right now, it doesn't work even trying to only get the base64 part):

<xh:html xmlns:xh="http://www.w3.org/1999/xhtml"
      xmlns:xf="http://www.w3.org/2002/xforms">
    <xh:head>
        <xf:model>
            <xf:instance>
                <i>data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==</i>
            </xf:instance>
        </xf:model>
    </xh:head>
    <xh:body>
        <xf:output mediatype="image/*" value="substring-after(., 'data:image/png;base64,')"/>
        <xh:img src="{.}"/>
    </xh:body>
</xh:html>
ebruchez commented 11 years ago

Also need to backport to 3.9.

ebruchez commented 11 years ago

The substring() idea doesn't work because by default, the type associated with xf:output is anyURI, not base64Binary.

One idea is to use both ref and value:

<xf:output
    ref="instance()/node-with-type"
    mediatype="image/*"
    value="substring-after(instance()/value, 'data:image/png;base64,')"/>

But this doesn't work right now.

avernet commented 11 years ago

Somehow, this is not working with this example: the xf:output generated an image of the right size, but transparent. Left with an xh:img, right with an xf:output.

screen shot 2013-08-03 at 4 31 16 pm

ebruchez commented 11 years ago

The issue with this example is that the URL contains + characters. Because the data part of the URL is first URL-decoded, the + becomes a space and so the data is corrupted.

How did you come up with a URL which contains + characters?

avernet commented 11 years ago

We get it from wPaint, through their API:

annotationImgData = @wpaintElC.wPaint('image')
OD.dispatchEvent
    targetId:  @container.id
    eventName: 'fr-update-annotation'
    properties: value: annotationImgData

This in turn seems to return canvas.toDataURL(). I re-tested this and it happens with both Firefox and Chrome, which is strange based on what I read on the base64 Wikipedia article:

Using standard Base64 in URL requires encoding of '+', '/' and '=' characters into special percent-encoded hexadecimal sequences ('+' = '%2B', '/' = '%2F' and '=' = '%3D'), which makes the string unnecessarily longer.

The HTML5 spec references the (very short) RFC 2397, which has an example with an <IMG SRC="…"> which contains a non-escaped +, so maybe Wikipedia is wrong, and + are not supposed to be escaped in data URLs, or at least are not in practice.

avernet commented 11 years ago

RFC 2397 says:

The appearance of ";base64" means that the data is encoded as base64. Without ";base64", the data (as a sequence of octets) is represented using ASCII encoding for octets inside the range of safe URL characters and using the standard %xx hex encoding of URLs for octets outside that range.

Maybe this implies that if you have ;base64, the data is encoded in base64-that's-it (unlike the case where there is no ;base64, where "the standard %xx hex encoding" must be used).

ebruchez commented 11 years ago

I think that for now, we'll simply consider that data is plain Base64 and not URL encoded.

avernet commented 9 years ago

This must have regressed at some point, which prevents the annotation control from working properly; reopening.

+1 from customer