Is it possible to embed a base64 image with CFMailParam? - coldfusion

I'm working on an app that creates customized images based on user inputs using canvas and I was wondering if it was possible to allow users to email themselves a copy of the final product in base64 or if I would have to convert it to .jpg or .png and then embed it as that.
Thanks.

I'd suggest converting the Base64 to an image, writing to disk, and using cfmailparam to attach/inline it as well as automatically remove it from disk.
I have had nothing but issues trying to directly inline/attach base64 images to emails using cfmail. I have had partial success converting the base64 to an image object (using ImageReadBase64()) and then using the image object as the value of the cfmailparam content attribute and ommitting the file attribute, however the image comes through with inverted colors oddly enough.
On to some example code...
<cfsavecontent variable="mailContent">
...
<img src="cid:signature">
...
</cfsavecontent>
<cfset sigImage = ImageReadBase64(SIGNATURE_IMAGE_BASE64)>
<cfimage source="#sigImage#" destination="tmpSigImage.png" action="write" overwrite="true">
<cfmail ...>
#mailContent#
<cfmailparam
file="#ExpandPath('./tmpSigImage.png')#"
contentid="signature"
disposition="inline"
remove="yes"
/>
</cfmail>

Related

How to change the user image using cfldap?

I'm able to get all the values that I want from cfldap.
But when I try to update the user image I don't know how to send the correct value for the binary image attribute.
I tried getting the image variable from the cffile upload
<cffile action="UPLOAD" filefield="file" destination="c:\inetpub\wwwroot\test" nameconflict="OVERWRITE" result="image" />
Also tried using cfimage with a static image -
<cfimage action="read" source="c:\inetpub\wwwroot\test\image.png" name="anotherImage">
Or even with
<cffile action="READBINARY" file="c:\inetpub\wwwroot\test\image.png" variable="BinaryImageContent">
But in any case, when I call
<cfldap action="modify"
DN="#results.dn#"
attributes="thumbnailPhoto=#obj.image#"
modifytype="replace"
server="myserver"
username="mydomain\myuser"
password="mypass">
The #results.dn# is the DN from the user that I get before (Everything ok on that)
I created the #obj.image# to be able to try all types of variables
Also tried these params:
<cfset obj.test1 = BinaryImageContent />
<cfdump var="#imageGetBlob(anotherImage)#" />
<cfdump var="#toString(obj.test1)#" />
By the way, the error that I get its
One or more of the required attributes may be missing or incorrect or
you do not have permissions to execute this operation on the server.
The problem is that I'm using the domain administrator account to update that
(THIS ERROR IS SOLVED - The network guys hadn't given me this permission... now I have it).
Now what I'm using is the following:
<cffile action="UPLOAD" filefield="file" destination="c:\inetpub\wwwroot\test" nameconflict="OVERWRITE" result="imagem" />
<cfset filename = "C:\inetpub\wwwroot\test\#imagem.serverFile#">
<cffile action="readbinary" file="#filename#" variable="img">
<cfset imgStr = BinaryEncode(img, "hex")>
<cfset imgStr2 = REReplace(imgStr, "..", "\\\0", "ALL")>
<cfldap
action="modify"
DN="#results.dn#"
attributes="thumbnailPhoto=#imgStr2#"
modifytype="replace"
server="myserver"
username="mydomain\myuser"
password="mypass"
>
but I get this binary code
Whats strange, is that before I had a binary code like -1-41 and now, nothing similar...
and when I try to show the pic
And this is one correct image....
EDIT: The original code sample below shows how it could work if ColdFusion wouldn't have a bug (or "very unfortunate design decision") in CFLDAP.
CFLDAP encodes the parameter values you pass to it before sending them to the server. This is nice because you don't have to worry about value encoding. But... it is also not helpful because it means you can't send encoded values yourself anymore, since CF invariably encodes them again.
Bottom line: As far as LDAP is concerned, encoding a file into a hex-string is correct, but CFLDAP mangles that string before sending it to the server. Combined with the fact that CFLDAP does not accept raw binary data this means that you can't use it to update binary attributes.
The comments contain a suggestion for a 3rd-party command line tool that can easily substitute CFLDAP for this task.
You need to send an encoded string to the server as the attribute value. The encoding scheme for binary data in LDAP queries has the form of attribute=\01\02\03\ab\af\cd.
Read your image into a byte array, encode that array into a hex string and prefix every encoded byte with a backslash.
<cffile action="readbinary" file="#filename#" variable="img">
<cfset imgStr = BinaryEncode(img, "hex")>
<cfset imgStr = REReplace(imgStr, "..", "\\\0", "ALL")>
<cfldap
action="modify"
DN="#results.dn#"
attributes="thumbnailPhoto=#imgStr#"
modifytype="replace"
server="myserver"
username="mydomain\myuser"
password="mypass"
>
Also don't forget what the documentation has to say about modifyType.

CFFILE - Uploading a file using a component

I have a form that I would like to submit to a component for processing (CRUD behaviors), the problem is it seems passing multipart/form-data to a component somehow looses the file location. When it gets to the part of the component that should be uploading the file I get the infamous form field did not contain a file error.
I am not 100% sure why this happening but if I submit the form directly to a .cfm page that performs the cffile action everything works as expected, but if the .cfm page does something like:
<cfobject name="process_form" component="processor" />
<cfset result = process_form.upload( form ) />
and the component "processor" tries to do the upload, I get the form field did not contain a file.
My processor looks like:
<cfcomponent name="processor">
<cffunction name="upload" returntype="string">
<cfargument name="form_data" type="struct" />
<cffile action="upload" filefield="#arguments.form_data.file_1#" ...>
[ ... ]
</cffunction>
</cfcomponent>
One thing to note, is if I try use the variable arguments.form_data.file_1 without the # signs around it, I get the error:
The form field arguments.form_data.file_1 did not contain a file.
If I put the # signs around the variable I get:
The form field C:\JRun4\servers\cfusion\SERVER-INF\temp\cfusion-war-tmp\neotmp7350969777287007477.tmp did not contain a file.
Any idea on how to fix this issue? I would rather have all my processing actions inside a component, but right now I can't seem to make that work.
Thanks!
Will
You shouldn't need to use the full variable name when using a cffile tag--you just need the form field name, so something like:
<cffile action="upload" filefield="file_1" ...>
should suffice. The FORM struct field holds the location of the temporary file, but the cffile tag doesn't need that (I'd image that id directly accesses the FORM struct on the backend based on the fieldname you've provided).

How do you write a image to browser as a binary stream in coldfusion?

I have a service on a Coldfusion 9 server that creates image banners on the fly for us. A separate machine has to save these files with something like:
wget http://myserver.com/services/local/bannerCreator/250x250-v3.cfm?prodID=3&percentSaving=19
The problem is that I can't think of how to get coldfusion to write out binary data without using a temporary file. At the minute the image is just displayed as an image tag like this:
<cfimage action = "writeToBrowser" source="#banner#" width="#banner.width#" height="#banner.height#" />
Any ideas? Or should I just use a temporary file?
I can't test because you're not giving any example code for how your images are generated, but have you tried something along this line?
<cfcontent reset="true" variable="#imageData#" type="image/jpg" />
Update: So I went ahead and created my own image; I'll assume you're doing something similar. This works perfectly for me:
<cfset img = imageNew("",200,200,"rgb","red") />
<cfcontent variable="#toBinary(toBase64(img))#" type="image/png" reset="true" />
This works without writing to file, and without using a virtual file system ("ramdisk")
If you have the binary bytes of an file/image, you can replace the output buffer with it's contents like so:
<cfscript>
// eg. this is how you get a file as a binary stream
// var fileBytes = fileReadBinary( '/path/to/your/file.jpg' );
// get the http response
var response = getPageContext().getFusionContext().getResponse();
// set the appropriate mime type
response.setHeader( 'Content-Type', 'image/jpg' );
// replace the output stream contents with the binary
response.getOutputStream().writeThrough( fileBytes );
// leave immediately to ensure no whitespace is added
abort;
</cfscript>
Pretty much what <cfcontent> does when you use reset="true"
The advantage of this method over <cfcontent> is that we can write it inside our cfscript based cfcs.
I found the solution above
<cfcontent variable="#toBinary(toBase64(img))#" type="image/png" reset="true" />
to not quite work for me.
Setting type="image/png" is just setting the mime type of the response. I don't think it's necessarily encoding the image as PNG. As such, generating a transparent png (image type "argb") was giving me odd colours, when compared to the <cfimage action = "writeToBrowser"...> method.
I figured that somehow I needed to explicitly encode the image data as PNG and output the binary data directly.
With some digging around in the underlying java, I came up with this, which so far seems to work for me.
This example draws a transparent png with a black circle.
<!--- create the image and draw it --->
<cfset img = ImageNew("", 23, 23, "argb")>
<cfset ImageSetDrawingColor(img, "black")>
<cfset ImageDrawOval(img, 0, 0, 21, 21, true)>
<!--- get the response object --->
<cfset response = getPageContext().getFusionContext().getResponse()>
<!--- set the response mime type --->
<cfset response.setHeader('Content-Type', 'image/png')>
<!--- get the underlying image data --->
<cfset bImage = ImageGetBufferedImage(img)>
<!--- get the magical object to do the png encoding --->
<cfset ImageIO = createObject("java", "javax.imageio.ImageIO")>
<!--- encode the image data as png and write it directly to the response stream --->
<cfset ImageIO.write(bImage, "png", response.getResponse().getOutputStream())>
I hope that helps someone!
Take out the height and width attributes and add the format attribute:
<cfimage action = "writeToBrowser" source="#banner#" format="png" />
wget should honor the redirection to the physical file CF creates in the CFFileServlet folder but if it doesn't there is a flag you can set to make it --max-redirect=10.
And as you suggest, a temporary file would work too. Just write the file and use cfheader and cfcontent to write it out. Just make sure to make the temp file name more unique.
<cfimage action="write" destination="tempfile.png" source="#banner#" format="png" />
<cfheader name="content-disposition" value="attachment; filename=banner.png" />
<cfcontent file="tempfile.png" deletefile="true" type="image/png" />
I do a similar thing, and you need to combine using tags and cfscript. There are image functions that are required. There are a lot of image functions available, once you have an image in memory as a variable. You can get the image into memory using CFFILE or CFHTTP or a number of other ways.
In my case, I read an image file into memory using CFIMAGE tag, then manipulate it with CFSCRIPT image functions by adding text to the bottom, then outputting the resulting image as a .png (or a .jpg if you prefer) to the browser. The only file stored on the server is the original image file. In your case instead of reading in an image you'd call it using a cfhttp tag as you already do. Here's my code:
<!---Get the image for processing ...--->
<cfimage action="read" source="#application.approotABS#\webcam\webcam.jpg" name="CamImage" />
<!--- prepare the text for overlay --->
<cfscript>
attr=structNew();
attr.font = "Arial";
attr.size = 15;
ImageSetDrawingColor(CamImage, "white");
ImageDrawText(CamImage, 'LIVE FROM STUDIO 1', 18,(ImageGetHeight(CamImage)-54), attr);
ImageDrawText(CamImage, '#ShowOnNow.showname#', 18,(ImageGetHeight(CamImage)-36), attr);
ImageDrawText(CamImage, datestring,18,(ImageGetHeight(CamImage)-18), attr);
</cfscript>
<!--- further down the page, output the manipulated image: ---->
<div class="webcam">
<cfimage action="writeToBrowser" source="#Camimage#" >
</div>
You can see it in action at http://hawkesburyradio.com.au/index.cfm?pid=111538
(I am using CF9 with Windows Server )

Converting Unicode Characters from Twitter JSON API feed using ColdFusion

I'm trying to use the Twitter API to pull down statuses from the Lists API using ColdFusion and am parsing everything I need just fine using the JSON format and a JSON component.
The problem I've come across is trying to convert the Unicode characters so they display correctly on screen.
here is the sample data that comes from the JSON feed
F\u00e0bregas
Is there some regex I could use to convert this?
Currently I have it writing out the raw data from the JSON feed
#node.user.name#
Which is fine, but it contains the \u00e0 which I need to convert so it displays as Fàbregas with the correct accent over the 'a'.
First up I think this is more of an character encoding issue than a regex issue.
How are you getting the Twitter data? If it's using <cfhttp> you could try setting the charset attribute to UTF-8. This will ensure that the data from Twitter arrives in UTF-8.
Then you should explicitly set the character encoding on the page you are trying to output the data on (the FORM and URL encoding while you are at it). For example:
<!--- URL and FORM encoding to UTF-8 --->
<cfset setEncoding("URL", "UTF-8") />
<cfset setEncoding("FORM", "UTF-8") />
<cfcontent type="text/html; charset=UTF-8" />
<cfoutput>#node.user.name#</cfoutput>
You'll find some more info here. Hope that helps!
There has to be a better way but until then I think this works
<cfset y = 'F\u00e0bregas'/>
<cfset x = evaluate(de(rereplace(y,'\\u([a-fA-f0-9]{4})','##chr(inputbasen(''\1'',16))##','all')))/>

How to generate PDF from .cfm page in Mac

I am using <cfdocument> tag of coldfusion 7. Using CFEclipse and working on MacOS.
I have written the following code:
<cfdocument format="pdf">
SitePoint.com - Introduction to ColdFusion 7
PDF Generation
This is an example of PDF generation using ColdFusion 7.
</cfdocument>
But instead of asking me to save this file in .pdf format, its trying to open it in .cfm format.
How can I save it in .pdf format? Thanks!
Unless you tell it otherwise, the webserver returns the results of a CFM call as text. You need to use CFContent with CFHeader to alert the browser that the results it will be recieving are of a different type. Something like:
<cfheader name="Content-Disposition" value="inline; filename=document.pdf">
<cfcontent type="application/x-pdf">
<cfdocument>...</cfdocument>
I may have the MIME type wrong there. I'm doing this from memory. Check the docs for more help.
If you are on CF8 or higher then use the saveAsName attribute:
<cfdocument saveAsName=""
Either that or the method suggested by Ben above should work
You might also need to import the style sheet as well. So you can get the desired formatting. It needs to be imported after cfdocument.
<cfdocument
format="pdf"
filename = "canwriteurfile.pdf"
overwrite = "yes"
marginBottom = ".2"
marginLeft = ".4"
marginRight = ".4"
marginTop = ".2">
<style type="text/css">#import "pdf.css";</style>
BLAHHH BLAHHH PDF FORMATTING STUFF
</cfdocument>
Try:
<cfdocument format="PDF" name="myPDF">
<html>
<body>
SitePoint.com - Introduction to ColdFusion 7
PDF Generation
This is an example of PDF generation using ColdFusion 7.
</body>
</html>
</cfdocument>
<cfpdf action = "write" destination = "pdf_path" source = "myPDF" overwrite = "yes"/>
<cflocation url="pdf_path"/>
Whis this you save the PDF on disk