When you work with images in web applications it is very important to provide high level of safety. The single server contains multiple web applications, and if one of them will hangs, all the rest ones may stop working too. If some applications will occupy all resources, other ones will not functionate. This topic describes how to increase safety and reduce risk of deny of service. We advise to follow the rules below.
Do not forget to dispose the objects as early as possible. Just call the Dispose() method of the Bitmap as soon the bitmap is no longer needed.
Dim bitmap As New Aurigma.GraphicsMill.Bitmap 'Process... bitmap.Load(path) '... bitmap.Dispose()
Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap(); //Process... bitmap.Load(path); //... bitmap.Dispose();
To guaranty that the resources are released even in exceptional situations when a error occurs, put the Dispose() call in the try/finally block:
Dim bitmap As New Aurigma.GraphicsMill.Bitmap Try 'Process... bitmap.Load(path) '... Finally bitmap.Dispose() End Try
Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap() try { //Process... bitmap.Load(path); //... } finally { bitmap.Dispose(); }
If your code is written with C#, you can use the using statement which guaranties that the object will be disposed after the block of code specified in this statement will complete. Here is an example:
using (Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap()) { //Process... bitmap.Load(path); //... }
You can limit the time of operations executed by Graphics Mill for .NET (loading, saving, applying effects, etc) via the property Timeout of the Bitmap class. This property specifies how much time (in milliseconds) the operation can be running. If the operation timeout expires, it is automatically aborted.
Let's examine the following code:
<%@ Page language="VB" AutoEventWireup="true"%> <script runat="server" language="VB"> Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Dim bitmap As New Aurigma.GraphicsMill.Bitmap 'Load image from file bitmap.Load(Server.MapPath("SourceImages/Mountain.jpg")) 'Resize image to huge size (6000x4000). Note, this code will make the 'server overloaded for a long time. In the next code sample will be 'demonstrated how to specify timeout to avoid hanging bitmap.Transforms.Resize(6000, 4000) Response.ContentType="image/jpeg" bitmap.Save(Response.OutputStream, _ New Aurigma.GraphicsMill.Codecs.JpegEncoderOptions(70, False)) Response.End bitmap.Dispose End Sub </script>
<%@ Page language="C#" AutoEventWireup="true" %> <script runat="server" language="C#"> private void Page_Load(object sender, System.EventArgs e) { Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap(); //Load image from file bitmap.Load(Server.MapPath("SourceImages/Mountain.jpg")); //Resize image to huge size (6000x4000). Note, this code will make the //server overloaded for a long time. In the next code sample will be //demonstrated how to specify timeout to avoid hanging bitmap.Transforms.Resize(6000, 4000); Response.ContentType="image/jpeg"; bitmap.Save(Response.OutputStream, new Aurigma.GraphicsMill.Codecs.JpegEncoderOptions(70, false)); Response.End(); bitmap.Dispose(); } </script>
It is obviously that resizing to such huge (2000x3000) image may take about half minute (depending on computer capacity and amount of free resources). For web servers such a delay may be disastrous. The way out is to use Timeout property. If Graphics Mill for .NET works too long, it will allow to stop and prevent application freezing. So we recommend using this property everywhere where it is possible. The recommended value is in range 5-60 seconds (5000-60000 milliseconds). Specifying small timeouts will cause too often aborting of operations. Note, you should specify timeout before running any operations with the bitmap.
Here is modified code:
<%@ Page language="VB" AutoEventWireup="true"%> <script runat="server" language="VB"> Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Dim bitmap As New Aurigma.GraphicsMill.Bitmap 'Set timeout to 5 seconds bitmap.Timeout = 5000 'Load image from file bitmap.Load(Server.MapPath("SourceImages/Mountain.jpg")) 'Resize image to huge size (6000x4000). Note, this code will make the 'server overloaded for a long time. In the next code sample will be 'demonstrated how to specify timeout to avoid hanging bitmap.Transforms.Resize(6000, 4000) Response.ContentType="image/jpeg" bitmap.Save(Response.OutputStream, _ New Aurigma.GraphicsMill.Codecs.JpegEncoderOptions(70, False)) Response.End bitmap.Dispose End Sub </script>
<%@ Page language="C#" AutoEventWireup="true" %> <script runat="server" language="C#"> private void Page_Load(object sender, System.EventArgs e) { Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap(); //Set timeout to 5 seconds bitmap.Timeout = 5000; //Load image from file bitmap.Load(Server.MapPath("SourceImages/Mountain.jpg")); //Resize image to huge size (6000x4000). Note, this code will make the //server overloaded for a long time. In the next code sample will be //demonstrated how to specify timeout to avoid hanging bitmap.Transforms.Resize(6000, 4000); Response.ContentType="image/jpeg"; bitmap.Save(Response.OutputStream, new Aurigma.GraphicsMill.Codecs.JpegEncoderOptions(70, false)); Response.End(); bitmap.Dispose(); } </script>
Always check all the data which comes either as a result of the user interaction or as URL parameters (which you need to retrieve to Graphics Mill for .NET). It will help to reduce the risk of the malicious attacks.
Let's assume we have created simple script thumbnail.aspx which reads images and creates thumbnails:
<%@ Page language="VB" AutoEventWireup="true" %> <script runat="server" language="VB"> Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Dim bitmap As New Aurigma.GraphicsMill.Bitmap 'Load image from file specified in url bitmap.Load(Server.MapPath(Request.QueryString("path"))) 'Resize image to width and height passed in URL. Note, it is unsafe 'as a hacker can pass enormous value and make the server hang. 'Always check parameters passed through the URL! bitmap.Transforms.Resize(Int32.Parse(Request.QueryString("width")), _ Int32.Parse(Request.QueryString("height"))) Response.ContentType="image/jpeg" bitmap.Save(Response.OutputStream, _ New Aurigma.GraphicsMill.Codecs.JpegEncoderOptions(70, False)) Response.End bitmap.Dispose End Sub </script>
<%@ Page language="C#" AutoEventWireup="true"%> <script runat="server" language="C#"> private void Page_Load(object sender, System.EventArgs e) { Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap(); //Load image from file specified in url bitmap.Load(Server.MapPath(Request.QueryString["path"])); //Resize image to width and height passed in URL. Note, it is unsafe //as a hacker can pass enormous value and make the server hang. //Always check parameters passed through the URL! bitmap.Transforms.Resize(Int32.Parse(Request.QueryString["width"]), Int32.Parse(Request.QueryString["height"])); Response.ContentType="image/jpeg"; bitmap.Save(Response.OutputStream, new Aurigma.GraphicsMill.Codecs.JpegEncoderOptions(70, false)); Response.End(); bitmap.Dispose(); } </script>
Writing this code we expect that correct values are always retrieved. When the URL string is thumbnail.aspx?width=100&height=100&path=source.jpg, a thumbnail is created and displayed correctly. But let's now suppose that some malefactor decides to hang our server. In this case they will just specify thumbnail.aspx?width=10000&height=10000&path=source.jpg and then will run it several times. It will take a lot of resources on the server and cause a sudden downfall of the server performance. Besides of it, user can also change path parameter to see files which are stored in closed for browsing folder in the following way: thumbnail.aspx?width=100&height=100&path=../protected/source.jpg.
That's why to avoid such malicious actions you should not pass such data in URL string or at least validate it (for example check whether thumbnail width and height is in reasonable range, e.g. less than 320x200, or specified path does not have ".." substring). Another way out is to encrypt parameters in the URL string (pass something like this: thumbnail.aspx?dfksg34hkdkerefsg5ndfg1affdsf4jd). However the encrypting is a subject of a separate topic.
Avoid to generate images on-the-fly. Server computing resources are noticeable more expensive than hard disk space, that's why it is better to save once created results where it is possible. The typical example is online galleries of images. It is very popular to generate thumbnails for such an images automatically. But it is obviously that creating thumbnails everytime user visits a page consumes too much server resources. The more reasonable is to create thumbnails only once, and save them to hard disk and everytime visitor browse the page again, load thumbnails from disk instead of creating them on-the-fly.