Is it possible to avoid "The operation is insecure" when using Canvas? - javascript

I have a HTML canvas (using KineticJS, however canvas aficionados should still chime in) that loads an image from another domain, places it onto the canvas and overlays some other information to product a final image. When I try to use canvas.toDataURL () to output the file, I receive the message "The operation is insecure.", obviously due to cross-domain restrictions.
I was wondering if anyone knows of any methods to work around this error (preferably cross-browser compatible). I was thinking a solution would be to copy the canvas to another canvas, kind of like a screenshot, but I can't find any method of doing so in the way that would avoid the error as I think it copies all canvas properties along with it.
Does anyone have any ideas?

If the images are coming from a domain you don't control, then you're stuck with CORS limitations.
If you have access to configuring your own server, you can enable cross-origin sharing by setting this heading (read more about server security when doing this):
Access-Control-Allow-Origin: <origin> | *
Alternatively, if you host your images on a CORS enabled site like www.dropbox.com you can fetch images without the security errors like this:
var image1=new Image();
image1.onload=function(){
context.drawImage(image1,0,0);
}
image1.crossOrigin="anonymous";
image1.src="https://dl.dropboxusercontent.com/u/99999999/yourCORSenabledPic.jpg";

Related

Intermittent failure to load images - ERR_CONTENT_LENGTH_MISMATCH

The problem
My website fails to load random images at random times.
Intermittent failure to load image with the following error in console:
"GET example.com/image.jpg net::ERR_CONTENT_LENGTH_MISMATCH"
Image either doesn't load at all and gives the broken image icon with alt tag, or it loads halfway and the rest is corrupted (e.g. colors all screwed up or half the image will be greyed out).
Setup
Litespeed server, PHP/mySQL website, with HTML, CSS, Javascript, and JQuery.
Important Notes
Problem occurs on all major web browsers - intermittently and with various images.
I am forcing UTF-8 encoding and HTTPS on all pages via htaccess.
Hosting provider states that all permissions are set correctly.
In my access log, when an image fails to load, it gives a '200 OK' response for the image and lists the bytes transferred as '0' (zero).
It is almost always images that fail to load but maybe 5% of the time it will be a CSS file or Javascript file.
Problem occurred immediately after moving servers from Apache to Litespeed and has been persistent over several weeks.
Gzip and caching enabled.
This error is definite mismatch between the data that is advertised in the HTTP Headers and the data transferred over the wire.
It could come from the following:
Server : If a server has a bug with certain modules that changes the content but don't update the content-length in the header or just doesn't work properly.
Proxy : Any proxy between you and your server could be modifying the request and not update the content-length header.
This could also happens if setting wrong content-type.
As far as I know, I haven't see those problem in IIS/apache/tomcat but mostly with custom written code. (Writing image yourself on the response stream)
It could be even caused by your ad blocker.
Try to disable it or adding an exception for the domain from which the images come from.
Suggest accessing the image as a discrete url using cURL, eg
php testCurlimg >image.log 2>&1 to see exactly what is being returned by the server. Then you can move upon level to test the webpage
php testCurlpg >page.log 2>&1 to see the context for mixed data
I just ran into this same ERR_CONTENT_LENGTH_MISMATCH error. I optimized the image and that fixed it. I did the image optimization using ImageOptim but I'm guessing that any image optimization tool would work.
Had this problem today retrieving images from Apache 2.4 when using a proxy I wrote in php to provide a JWT auth gateway for accessing a couchdb backend. The proxy uses php fsockopen and the fread() buffer was set relatively low (30 bytes) because I had seen this value used in other peoples work and I never thought to change it. In all my failing JPG (JFIF) images I found the discrepancy in the original versus the image served was a series of crlf that matched the size of the fread buffer. Increased the byte length for the buffer and the problem no longer exists.
In short, if your fread buffer streaming the image is completely full of carriage returns and line feeds, the data gets truncated. This possibly also relates to the post from Collin Krawll as to why image optimization resolved that problem.

How to change an Images Cross Origin attribute using loadFromJSON?

I am using FabricJS' loadFromJSON method to load a bunch of objects (text and images) to a canvas.
The images are coming from Google Cloud Storage. The bucket they are stored in has the correct CORS settings, for allow all for "Access-Control-Allow-Origin".
The images will load in OK, but when trying to save a thumbnail, using the toDataURL() method, I get:
Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
I'm unsure why, because the images CORS settings are correct.
I know some people suggest creating a new image and setting the attribute that way, but that doesn't fit in with using the very quick and easy loadFromJSON method.
Any ideas on why the CORS settings are being ignored and anyway around this issue?

how to secure img src path when user clicks on view source using javascript?

How to secure the src path of the image when clicks on inspect element so that user should not get to know about the actual src path..please help me with the solution and it should be done with javascript only no other tags should be used.
You can convert image into base 64 data URIs for embedding images.
Use: http://websemantics.co.uk/online_tools/image_to_data_uri_convertor/
Code sample:
.sprite {
background-image:url(data:image/png;base64,iVBORw0KGgoAAAA... etc );
}
This is commonly done server-side, where you have an endpoint that serves the image file to you as bytes...
You can store the images in a private location on the server where IIS/<your favourite web server> doesn't have direct access to it, but only a web app, running on it, with the required privilege is authorized to do so.
Alternatively people also "store" the images in the database itself and load it directly from there.
In either case, the response which has to be sent back has to be a stream of bytes with the correct mime type.
Edit:
Here are a couple of links to get you started if you are into ASP.NET:
http://www.codeproject.com/Articles/34084/Generic-Image-Handler-Using-IHttpHandler
http://aspalliance.com/1322_Displaying_Images_in_ASPNET_Using_HttpHandlers.5 <- this sample actually does it from a database.
Don't let the choice of front-end framework (asp.net, php, django, etc) hinder you. Search for similar techniques in your framework of choice.
Edit:
Another way if you think html5 canvas is shown here: http://www.html5canvastutorials.com/tutorials/html5-canvas-images/
However you run into the same problem. Someone can view the image url if they can see the page source. You'll have to revert to the above approach eventually.

Force image caching with javascript

I am trying to clone an image which is generated randomly.
Although I am using the exact same url a different image is load. (tested in chrome and firefox)
I can't change the image server so I am looking for a pure javascript/jQuery solution.
How do you force the browser to reuse the first image?
Firefox:
Chrome:
Try it yourself (maybe you have to reload it several times to see it)
Code:
http://jsfiddle.net/TRUbK/
$("<img/>").attr('src', img_src)
$("<div/>").css('background', background)
$("#source").clone()
Demo:
http://jsfiddle.net/TRUbK/embedded/result/
You can't change the image server if it isn't yours, but you can trivially write something on your own server to handle it for you.
First write something in your server-side language of choice (PHP, ASP.NET, whatever) that:
Hits http://a.random-image.net/handler.aspx?username=chaosdragon&randomizername=goat&random=292.3402&fromrandomrandomizer=yes and downloads it. You generate a key in one of two way. Either get a hash of the whole thing (MD5 should be fine, it's not a security-related use so worries that it's too weak these days don't apply). Or get the size of the image - the latter could have a few duplicates, but is faster to produce.
If the image isn't already stored, save it in a location using that key as part of its filename, and the content-type as another part (in case there's a mixture of JPEGs and PNGs)
Respond with an XML or JSON response with the URI for the next stage.
In your client side-code, you hit that URI through XmlHttpRequest to obtain the URI to use with your images. If you want a new random one, hit that first URI again, if you want the same image for two or more places, use the same result.
That URI hits something like http://yourserver/storedRandImage?id=XXX where XXX is the key (hash or size as decided above). The handler for that looks up the stored copies of the images, and sends the file down the response stream, with the correct content-type.
This is all really easy technically, but the possible issue is a legal one, since you're storing copies of the images on another server, you may no longer be within the terms of your agreement with the service sending the random images.
You can try saving the base64 representation of the image.
Load the image in an hidden div/canvas, then convert it in base64. (I'm not sure if a canvas can be hidden, nor if it is possible to convery the img using html4 tag)
Now you can store the "stringified" image in a cookie, and use it unlimited times...
The headers being sent from your random image generator script include a Cache-Control: max-age=0 declaration which is in essence telling the browser not to cache the image.
You need to modify your image generator script/server to send proper caching headers if you want the result to be cached.
You also need to make sure that the URL stays the same (I didn't look at that aspect since there were tons of parameter being passed).
There seems to be two workarounds:
If you go with the Canvas method, see if you can get the image to load onto the Canvas itself so that you can manipulate the image data directly instead of making a 2nd http request for the image. You can feed the image data directly onto a 2nd Canvas.
If you're going to build a proxy, you can have the proxy remove the No-Cache directive so that subsequent requests by your browser use the cache (no guarantees here - depends on browser/user settings).
First off, you can "force" anything on the web. If you need to force things, then web development is the wrong medium for you.
What you could try, is to use a canvas element to copy the image. See https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Using_images for examples.
Tell it to stop getting a random image, seems to work the way you want when I add this third replace call:
// Get the canvas element.
var background = ($("#test").css('background-image')),
img_src = background.replace(/^.+\('?"?/, '').replace(/'?"?\).*$/, '').replace(/&fromrandomrandomizer=yes/,'')
try:
var myImg = new Image();
myImg.src = img_src;
and then append "myImg" to where you want:
$(document).append(myImg);
I did this with your fiddler scripts and got the same image every time
#test {
background:url(http://a.random-image.net.nyud.net/handler.aspx?username=chaosdragon&randomizername=goat&random=292.3402&fromrandomrandomizer=yes);
width: 150px;
height: 150px;
}
note the .nyud.net after the domain name.

How can I get images drawn with drawImage to be included when using toDataURL?

I'm working on a page where you will be able to draw images on a canvas. You have 6 options of images, and when you are done I want people to able to save their creation.
I'm using drawImage to draw the images on the canvas, but when I use the following code:
var canvas = document.getElementById("canvas");
window.open(canvas.toDataURL("image/png"));
It doesn't show the drawn images on the DataUrl images.
How can I make sure that the images that are drawn on the canvas are also visible in the image given by toDataURL?
What are the URLs of your page and the images you are drawing?
If your images are not coming from the same origin as the page, you will not be able to use toDataURL or any other methods to read the contents of the canvas; this is an intentional security feature. Check your JavaScript error console and you may see something like "DOM ERROR" or "SECURITY EXCEPTION".
What do I mean? I mean that if your page is at some URL (e.g., test.com, localhost:8080, file:///home/foo/) and the images you are drawing are located at URLs with different origins (google.com is a different origin from test.com, localhost:3000 is a different origin from localhost:8080, some browsers treat file:/// urls as if they are always from a different origin) then the browser will mark your canvas as unreadable once you draw the image to it.
Why is it this way? Pages can display images from other origins, but many other forms of cross-origin access are denied unless explicitly granted-- XMLHttpRequests, for example.
file URLs are treated differently as well because they are potentially more abusable. If you are using local files for the page and images, serve them with a trivial web server instead.
The first bullet in this section applies.

Categories