Generate icons for checkboxes

Instead of using this square check boxes you can also set your own images using the three following methods of JCheckBox:

  • setIcon to set the default icon.
  • setSelectedIcon to set the icon displayed when the box is checked.
  • setDisabledIcon to set the icon used when the box is disabled.

Now I mostly need the same image as the default image for selected and disabled icon with either an outline when it’s selected or grayed out if disabled.
So that I don’t have to set those three icons manually each time, I’ve subclassed JCheckBox so that the setIcon sets all three icons:

public void setIcon(Icon defaultIcon) {
	super.setIcon(defaultIcon);
	// New icon should have the same size
	int height = defaultIcon.getIconHeight();
	int width = defaultIcon.getIconWidth();
	// Get an image with the icon
	BufferedImage image = new BufferedImage(width, height,
			BufferedImage.TYPE_INT_ARGB);
	Graphics2D g2 = image.createGraphics();
	// First paint the icon
	defaultIcon.paintIcon(this, g2, 0, 0);
	// Buffer for the new image
	BufferedImage selected = new BufferedImage(width, height,
			BufferedImage.TYPE_INT_ARGB);
	g2 = selected.createGraphics();
	// Draw the original icon
	g2.drawImage(image, null, 0, 0);
	// Create the stroke for the outline
	g2.setColor(UIManager.getColor("CheckBox.outlineColor"));
	int strokeSize = (int) (.15 * width);
	g2.setStroke(new BasicStroke(strokeSize, BasicStroke.CAP_ROUND,
			BasicStroke.JOIN_ROUND));
	// Then draw the outline
	g2.drawRoundRect(0, 0, width, height, height, height);
	// And create an ImageIcon to use as selected icon
	setSelectedIcon(new ImageIcon(selected));
	// For the disabled icon we just apply a gray filter
	ImageFilter filter = new GrayFilter(false, 0);
	// Apply the filter to the original image
	Image disabled = createImage(new FilteredImageSource(image.getSource(),
			filter));
	// And create an ImageIcon to use as disabled icon
	setDisabledIcon(new ImageIcon(disabled));
}

Now I just need to set one of them and the others are created automatically. The result looks like this:
checkboxes
Of course the outline shouldn’t be so thick and the icon already should provide space for the outline.

Java: Vertical Label in Swing

This is an article I’ve published over 8 years ago on jroller. I’ve now republished it on my current blog because I was asked to clarify the license terms (see next paragraph) and I found it better to do it here than to update a post on a blog I’m not maintaining anymore.

License clarification: You can use the code of any article on this blog as you wish. I’ve just published this code in the hope to be helpful and do not expect anything in return. So from my point of view you can consider it being released under the WTFPL license terms.

Today, let’s see how to implement a vertical label in Swing. This component should extend JLabel and provide the possibility to rotate 90° to the right or to the left.

Like normal JLabel, it should work whether it contains an icon, a text or both.

Here’s a screenshot of how it should look like:

vertical label

The label with a rotation to the left, no rotation and a rotation to the right.

So that the label painted according to the current look and feel, I didn’t want to paint it myself but to delegate it and rotate it.

In order to do this, I had to rotate and translate the graphics object. The remaining problem is that the UI delegate uses some methods of the label to get the size of the component and the insets. So we have to trick the UI delegate into thinking that the component is horizontal and not vertical.

  public Insets getInsets(Insets insets) {
        insets = super.getInsets(insets);
        if (painting) {
            if (rotation == ROTATE_LEFT) {
                int temp = insets.bottom;
                insets.bottom = insets.left;
                insets.left = insets.top;
                insets.top = insets.right;
                insets.right = temp;
            }
            else if (rotation == ROTATE_RIGHT) {
                int temp = insets.bottom;
                insets.bottom = insets.right;
                insets.right = insets.top;
                insets.top = insets.left;
                insets.left = temp;
            }
        }
        return insets;
    }
    public Insets getInsets() {
        Insets insets = super.getInsets();
        if (painting) {
            if (rotation == ROTATE_LEFT) {
                int temp = insets.bottom;
                insets.bottom = insets.left;
                insets.left = insets.top;
                insets.top = insets.right;
                insets.right = temp;
            }
            else if (rotation == ROTATE_RIGHT) {
                int temp = insets.bottom;
                insets.bottom = insets.right;
                insets.right = insets.top;
                insets.top = insets.left;
                insets.left = temp;
            }
        }
        return insets;
    }
    public int getWidth() {
        if ((painting) && (isRotated()))
            return super.getHeight();
        return super.getWidth();
    }
    public int getHeight() {
        if ((painting) && (isRotated()))
            return super.getWidth();
        return super.getHeight();
    }

The painting variable is set in the paintComponent method just before calling the method of the super class:

protected void paintComponent(Graphics g) {
	Graphics2D g2d = (Graphics2D) g;

	if (isRotated())
		g2d.rotate(Math.toRadians(90 * rotation));
	if (rotation == ROTATE_RIGHT)
		g2d.translate(0, -this.getWidth());
	else if (rotation == ROTATE_LEFT)
		g2d.translate(-this.getHeight(), 0);
	painting = true;

	super.paintComponent(g2d);

	painting = false;
	if (isRotated())
		g2d.rotate(-Math.toRadians(90 * rotation));
	if (rotation == ROTATE_RIGHT)
		g2d.translate(-this.getWidth(), 0);
	else if (rotation == ROTATE_LEFT)
		g2d.translate(0, -this.getHeight());
}

Now one remaining problem is that a normal label uses the icon and the text to compute it’s preferred, minimum and maximum size assuming it’s layed out horizontally. Now the layour managers use this methods to layout the components. So we need to return sizes based on a vertical layout. Since we do not want to compute the sizes ourselves, we have to let the super class compute it and switch height and width (when there’s a rotation):

public Dimension getPreferredSize() {
	Dimension d = super.getPreferredSize();
	if (isRotated()) {
		int width = d.width;
		d.width = d.height;
		d.height = width;
	}
	return d;
}

public Dimension getMinimumSize() {
	Dimension d = super.getMinimumSize();
	if (isRotated()) {
		int width = d.width;
		d.width = d.height;
		d.height = width;
	}
	return d;
}

public Dimension getMaximumSize() {
	Dimension d = super.getMaximumSize();
	if (isRotated()) {
		int width = d.width;
		d.width = d.height + 10;
		d.height = width + 10;
	}
	return d;
}

That’s it, now our component behaves exactly like a JLabel except that it can be rotated to the left or to the right. The whole source code here for your reference:

package org.jroller.henribenoit.swing;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;

public class VerticalLabel extends JLabel {
    public final static int ROTATE_RIGHT = 1;

    public final static int DONT_ROTATE = 0;

    public final static int ROTATE_LEFT = -1;

    private int rotation = DONT_ROTATE;

    private boolean painting = false;

    public VerticalLabel() {
        super();
    }

    public VerticalLabel(Icon image, int horizontalAlignment) {
        super(image, horizontalAlignment);
    }

    public VerticalLabel(Icon image) {
        super(image);
    }

    public VerticalLabel(String text, Icon icon, int horizontalAlignment) {
        super(text, icon, horizontalAlignment);
    }

    public VerticalLabel(String text, int horizontalAlignment) {
        super(text, horizontalAlignment);
    }

    public VerticalLabel(String text) {
        super(text);
    }

    public int getRotation() {
        return rotation;
    }

    public void setRotation(int rotation) {
        this.rotation = rotation;
    }

    public boolean isRotated() {
        return rotation != DONT_ROTATE;
    }

    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;

        if (isRotated())
            g2d.rotate(Math.toRadians(90 * rotation));
        if (rotation == ROTATE_RIGHT)
            g2d.translate(0, -this.getWidth());
        else if (rotation == ROTATE_LEFT)
            g2d.translate(-this.getHeight(), 0);
        painting = true;

        super.paintComponent(g2d);

        painting = false;
        if (isRotated())
            g2d.rotate(-Math.toRadians(90 * rotation));
        if (rotation == ROTATE_RIGHT)
            g2d.translate(-this.getWidth(), 0);
        else if (rotation == ROTATE_LEFT)
            g2d.translate(0, -this.getHeight());
    }

    public Insets getInsets(Insets insets) {
        insets = super.getInsets(insets);
        if (painting) {
            if (rotation == ROTATE_LEFT) {
                int temp = insets.bottom;
                insets.bottom = insets.left;
                insets.left = insets.top;
                insets.top = insets.right;
                insets.right = temp;
            }
            else if (rotation == ROTATE_RIGHT) {
                int temp = insets.bottom;
                insets.bottom = insets.right;
                insets.right = insets.top;
                insets.top = insets.left;
                insets.left = temp;
            }
        }
        return insets;
    }

    public Insets getInsets() {
        Insets insets = super.getInsets();
        if (painting) {
            if (rotation == ROTATE_LEFT) {
                int temp = insets.bottom;
                insets.bottom = insets.left;
                insets.left = insets.top;
                insets.top = insets.right;
                insets.right = temp;
            }
            else if (rotation == ROTATE_RIGHT) {
                int temp = insets.bottom;
                insets.bottom = insets.right;
                insets.right = insets.top;
                insets.top = insets.left;
                insets.left = temp;
            }
        }
        return insets;
    }

    public int getWidth() {
        if ((painting) && (isRotated()))
            return super.getHeight();
        return super.getWidth();
    }

    public int getHeight() {
        if ((painting) && (isRotated()))
            return super.getWidth();
        return super.getHeight();
    }

    public Dimension getPreferredSize() {
        Dimension d = super.getPreferredSize();
        if (isRotated()) {
            int width = d.width;
            d.width = d.height;
            d.height = width;
        }
        return d;
    }

    public Dimension getMinimumSize() {
        Dimension d = super.getMinimumSize();
        if (isRotated()) {
            int width = d.width;
            d.width = d.height;
            d.height = width;
        }
        return d;
    }

    public Dimension getMaximumSize() {
        Dimension d = super.getMaximumSize();
        if (isRotated()) {
            int width = d.width;
            d.width = d.height + 10;
            d.height = width + 10;
        }
        return d;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new FlowLayout());
        VerticalLabel label = new VerticalLabel("Testing something");
        VerticalLabel label2 = new VerticalLabel("Testing something");
        VerticalLabel label3 = new VerticalLabel("Testing something");
        label.setIcon(new ImageIcon("shortcut.png"));
        label2.setIcon(new ImageIcon("shortcut.png"));
        label3.setIcon(new ImageIcon("shortcut.png"));
        label.setRotation(VerticalLabel.ROTATE_LEFT);
        label2.setRotation(VerticalLabel.DONT_ROTATE);
        label3.setRotation(VerticalLabel.ROTATE_RIGHT);
        frame.getContentPane().add(label);
        frame.getContentPane().add(label2);
        frame.getContentPane().add(label3);
        frame.pack();
        frame.setVisible(true);
    }
}

 

Sybase ASE Cookbook Update

I’ve written this cookbook about 10 months ago. It basically contains all the information about Sybase ASE I’ve documented on my blog over the years. I use it when I need offline access to some tricks (since I’m not getting younger, it’s sometimes useful to have a kind of brain dump somewhere). I also compiled it and published it here in the hope that someone else might find it useful.

I’ve just updated the cookbook with a few new things. But it’s really a small update.

This cookbook is still available for free. And I am still no professional writer and still cannot afford paying someone for proof-read it. So if you notice any mistakes, explanations which cannot be understood or anything like this, please leave a comment here or contact me at henri.benoit@gmail.com. I can’t guarantee how fast I can fix mistakes but I’ll do my best to do it in a timely manner.

Benohead Sybase ASE Cookbook

Downloading files and directories via SFTP using SSH.Net

SSH.NET is a .NET library implementing the SSH2 client protocol. It is inspired by a port of the Java library JSch called Sharp.SSH. It allows you to execute SSH commands and also provides both SCP and SFTP functionality.

In this article, I’ll show you how to download a complete directory tree using SSH.NET.

First you’ll need to add a few usings:

using System;
using System.IO;
using Renci.SshNet;
using Renci.SshNet.Common;
using Renci.SshNet.Sftp;

SSH.NET can be added to your project using NuGet.

In order to work with SFTP, you’ll need to get an instance of SftpClient. You can either directly give details like host, port, username and password or you can provide a ConnectionInfo object. In this example we’ll use a KeyboardInteractiveConnectionInfo. This is required if the server expects an interactive keyboard authentication providing the password. The alternatives are PasswordConnectionInfo and PrivateKeyConnectionInfo.

First we’ll create the ConnectionInfo object:

var connectionInfo = new KeyboardInteractiveConnectionInfo(Host, Port, Username);

Host, Port and Username are constants I’ve defined before.

Then we need to define a delegate which will get the prompts returned by the server and will send the password when requested:

connectionInfo.AuthenticationPrompt += delegate(object sender, AuthenticationPromptEventArgs e)
{
	foreach (var prompt in e.Prompts)
	{
		if (prompt.Request.Equals("Password: ", StringComparison.InvariantCultureIgnoreCase))
		{
			prompt.Response = Password;
		}
	}
};

It waits for the prompt “Password: ” and sends the password I’ve defined in a constant called Password.

Then using this SFTP client, we’ll connect to the server and download the contents of the directory recursively:

using (var client = new SftpClient(connectionInfo))
{
	client.Connect();
	DownloadDirectory(client, Source, Destination);
}

Source is the directory you want to download on the remote server and destination is the local directory e.g.:

private const string Source = "/tmp";
private const string Destination = @"c:\temp";

Now we’ll define the DownloadDirectory method. It will get the directory listing and iterate through the entries. Files will be downloaded and for each directory in there, we’ll recursively call the DownloadDirectory method:

private static void DownloadDirectory(SftpClient client, string source, string destination)
{
	var files = client.ListDirectory(source);
	foreach (var file in files)
	{
		if (!file.IsDirectory && !file.IsSymbolicLink)
		{
			DownloadFile(client, file, destination);
		}
		else if (file.IsSymbolicLink)
		{
			Console.WriteLine("Ignoring symbolic link {0}", file.FullName);
		}
		else if (file.Name != "." && file.Name != "..")
		{
			var dir = Directory.CreateDirectory(Path.Combine(destination, file.Name));
			DownloadDirectory(client, file.FullName, dir.FullName);
		}
	}
}

I am ignoring symbolic links because trying to download them just fails and the SftpFile class provides no way to find what this link points to. “.” and “..” are also ignored.

Now let’s see how to download a single file:

private static void DownloadFile(SftpClient client, SftpFile file, string directory)
{
	Console.WriteLine("Downloading {0}", file.FullName);
	using (Stream fileStream = File.OpenWrite(Path.Combine(directory, file.Name)))
	{
		client.DownloadFile(file.FullName, fileStream);
	}
}

It’s pretty easy: you create a file stream to the destination file and use the DownloadFile method of the SFTP client to download the file.

That’s it ! Here the full code for your convenience:

using System;
using System.IO;
using Renci.SshNet;
using Renci.SshNet.Common;
using Renci.SshNet.Sftp;

namespace ConsoleApplication1
{
    public static class SftpTest
    {
        private const string Host = "192.168.xxx.xxx";
        private const int Port = 22;
        private const string Username = "root";
        private const string Password = "xxxxxxxx";
        private const string Source = "/tmp";
        private const string Destination = @"c:\temp";

        public static void Main()
        {
            var connectionInfo = new KeyboardInteractiveConnectionInfo(Host, Port, Username);

            connectionInfo.AuthenticationPrompt += delegate(object sender, AuthenticationPromptEventArgs e)
            {
                foreach (var prompt in e.Prompts)
                {
                    if (prompt.Request.Equals("Password: ", StringComparison.InvariantCultureIgnoreCase))
                    {
                        prompt.Response = Password;
                    }
                }
            };

            using (var client = new SftpClient(connectionInfo))
            {
                client.Connect();
                DownloadDirectory(client, Source, Destination);
            }
        }

        private static void DownloadDirectory(SftpClient client, string source, string destination)
        {
            var files = client.ListDirectory(source);
            foreach (var file in files)
            {
                if (!file.IsDirectory && !file.IsSymbolicLink)
                {
                    DownloadFile(client, file, destination);
                }
                else if (file.IsSymbolicLink)
                {
                    Console.WriteLine("Ignoring symbolic link {0}", file.FullName);
                }
                else if (file.Name != "." && file.Name != "..")
                {
                    var dir = Directory.CreateDirectory(Path.Combine(destination, file.Name));
                    DownloadDirectory(client, file.FullName, dir.FullName);
                }
            }
        }

        private static void DownloadFile(SftpClient client, SftpFile file, string directory)
        {
            Console.WriteLine("Downloading {0}", file.FullName);
            using (Stream fileStream = File.OpenWrite(Path.Combine(directory, file.Name)))
            {
                client.DownloadFile(file.FullName, fileStream);
            }
        }
    }
}

So except for the issue with the symbolic link, it works pretty good and is also quite fast.

 

The c# project is targeting “.NET Framework,Version=v4.0″, which is not installed on this machine.

Since I needed some space on my hard disk to install some software I went through the list of installed software and saw that Visual Studio 2010 was installed but I actually only use Visual Studio 2012 (or Visual Studio 2005 for some very old stuff which hasn’t been ported yet). So I thought it makes sense to uninstall Visual Studio 2010. And ended up wasting alot of time…

After uninstalling VS 2010, I started getting the following message in VS2012 whenever I opened a project targeted at the .NET framework v4.0:

The C# project xxx is targeting ‘.NETFramework,Version=v4.0″, which is not installed on this machine. to proceed, you must select an option below.

1.Change the target to .NET Framework 4.5…..

2.Download the targeting pack for “.NET Framework, Version = v4.0″…

3.Do not load the project

When you choose option 2 you are redirected to a web page where you actually cannot download the v4.0 .NET framework. Checking in the registry, I saw that the .NET framework was gone. I also found the installation package for the .NET framework v4.0. Unfortunately, it refuses to install since the v4.5 framework is already installed.

So my next great idea was to uninstall the v4.5 framework. Then I could install the v4.0 version. Of course, after that VS 2012 wouldn’t start anymore. So I installed the v4.5 framework again. During the installation, it told me that it’s an in-place update for the v4.0 framework. I immediately thought that it might cause trouble but didn’t have a choice anyway. After installing the v4.5 framework VS2012 worked again but as expected, I still got the same error message when opening projects targeting the v4.0 framework.

Running out of other options, I finally reinstalled VS2010. It took forever but in the end I was able to open all projects in VS2012.

So this is kind of a waste of space but if you cannot have your project target the v4.5 framework but need to target the v4.0 framework, you will need to have VS2010 installed additionally to VS2012 (even though you actually do not need VS2010).

If anybody has found a solution not requiring VS2010 to stay installed, please leave a comment. My hard disk space is running low and I’d love to be able to get rid of VS2010.

Windows 7: empty pages displayed in CHM file

When opening a CHM file downloaded from Internet on a Windows Vista or Windows 7 machine, the file may not render properly and just show empty pages. All you’ll see no matter which page you select is an error message saying that “Navigation to the webpage was canceled” e.g.:

Navigation to the webpage was canceled

The problem is that the file comes from another computer and is blocked. It’s strange because you actually get a security warning when opening the file and one would expect that if you open it anyway, everything should be fine. Here an example of such a security warning:

Open File - Security Warning

The solution is to unblock the file. In order to do it, do not open the file directly from the browser but save it to disk, then right click on the file, choose Properties and unblock the file:

CHM file properties - Unblock

Now, when you open the file, no security warning will be displayed and the contents will be displayed properly.

Note that you should only unblock files that you trust.

If you do not see an Unblock button, you have either already unblocked it and it doesn’t work anymore (not exactly sure when this happens) or you might have stored the file on a file system which doesn’t support the Unblock feature (not sure but it looks like it only works on NTFS).

You can also implicitly unblock the file by unchecking “Always ask before opening this file” in the security warning shown above.

So this whole behavior seems not to be very consistent but fixing it was pretty straight forward.

Update: It looks like on Windows 8, you can unblock files from a PowerShell using the following commandlet:

Unblock-File .\SshNet.Help.chm

 

CSS: Google Plus Like Buttons

I guess most web sites are now using CSS to create nice looking buttons without using background images. Google has done a nice job creating clean looking buttons. I’ll show in this article how you can easily create similar looking buttons.

First regarding why it makes sense to use only CSS to create buttons instead of using background images:

  • The browser does not need to load images. This makes the page loading process faster.
  • It makes it easier to create scalable buttons which look good no matter how long the label on the button.
  • You just need to adapt the CSS style in order to get different styles of buttons.

As far as I could see, Google seems to be using 4 types of buttons in Google Plus:

Add
Save
Add
Post comment

First we’ll style the first button as our default button (the one with the white background):

.google-plus-button {
    -moz-user-select: none;
    -ms-user-select: none;
    -webkit-user-select: none;
    background-color: #fff;
    border: 1px solid #d4d4d4;
    -webkit-border-radius: 2px;
    -moz-border-radius: 2px;
    border-radius: 2px;
    -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.05);
    -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.05);
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.05);
    color: #404040;
    cursor: default;
    display: inline-block;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 12px;
    font-weight: bold;
    height: 28px;
    line-height: 28px;
    margin-right: 0;
    min-width: 54px;
    outline: 0 none;
    padding: 0 8px;
    position: relative;
    text-align: center;
    white-space: nowrap;
    word-wrap: break-word;
}

The user-select: none properties are used to prevent text selection (the browser doesn’t know it’s a button).
Also the rounded corners will be square in Internet Explorer 8 and lower as well as in Opera Mini. And the box shadows will be missing in these browsers too.

Also note that I’m using the default cursor for the button because it’s the way it is in Google Plus. But if you’d rather have the pointer cursor used for links, just replace:

cursor: default;

by:

cursor: pointer;

You might have noticed that the labels on the buttons look a little bit different than on Google Plus, because they use the Roboto font. If you want to use it, you’ll need to get it from Google Fonts. But I personally use Arial which is close enough and has the advantage of already being available pretty much on every machine without having to reference an external resource which can have an impact on page load time. Anyway, in order to use the Roboto font, add the following code to the <head> tag of your website:

<link href='http://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>

And replace:

font-family: Arial, Helvetica, sans-serif;

By:

font-family: Roboto, Arial, ​sans-serif;

The next step is to add some styles so that it actually feels like a button:

.google-plus-button:hover {
    background-color: #fff;
    background-image: -moz-linear-gradient(center top , transparent, transparent);
    border: 1px solid #b8b8b8;
    -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
    -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
    color: #404040;
}
.google-plus-button:active {
    background: none repeat scroll 0 0 #e5e5e5;
    border-right: 1px solid transparent;
    -webkit-box-shadow: 0 2px 0 #ddd inset;
    -moz-box-shadow: 0 2px 0 #ddd inset;
    box-shadow: 0 2px 0 #ddd inset;
    color: #262626;
}

Now that we have our basic white button, we can style the other buttons which will get the red, green and blue classes:

.google-plus-button.green {
    background-color: #53a93f;
    border: 1px solid transparent;
    color: #fff;
}
.google-plus-button.green:hover {
    background-color: #65b045;
    border-color: transparent transparent #4c8534;
    -webkit-box-shadow: 0 -1px 0 #4c8534 inset;
    -moz-box-shadow: 0 -1px 0 #4c8534 inset;
    box-shadow: 0 -1px 0 #4c8534 inset;
}
.google-plus-button.green:active {
    background: none repeat scroll 0 0 #3e802f;
    border-color: #2f6124 transparent transparent;
    -webkit-box-shadow: 0 1px 0 #2f6124 inset;
    -moz-box-shadow: 0 1px 0 #2f6124 inset;
    box-shadow: 0 1px 0 #2f6124 inset;
}

.google-plus-button.red {
    background-color: #d73d32;
    border: 1px solid transparent;
    color: #fff;
}
.google-plus-button.red:hover {
    background-color: #e74b37;
    border-color: transparent transparent #bd3d2a;
    -webkit-box-shadow: 0 -1px 0 #bd3d2a inset;
    -moz-box-shadow: 0 -1px 0 #bd3d2a inset;
    box-shadow: 0 -1px 0 #bd3d2a inset;
}
.google-plus-button.red:active {
    background-color: #be3e2e;
    border-color: #9a3323 transparent transparent;
    -webkit-box-shadow: 0 1px 0 #9a3323 inset;
    -moz-box-shadow: 0 1px 0 #9a3323 inset;
    box-shadow: 0 1px 0 #9a3323 inset;
}

.google-plus-button.blue {
    background-color: #427fed;
    border: 1px solid transparent;
    color: #fff;
}
.google-plus-button.blue:hover {
    background-color: #4285f4;
    border-color: transparent transparent #2f69c2;
    -webkit-box-shadow: 0 -1px 0 #2f69c2 inset;
    -moz-box-shadow: 0 -1px 0 #2f69c2 inset;
    box-shadow: 0 -1px 0 #2f69c2 inset;
}
.google-plus-button.blue:active {
    background: none repeat scroll 0 0 #2c56b1;
    border-color: #21448d transparent transparent;
    -webkit-box-shadow: 0 1px 0 #21448d inset;
    -moz-box-shadow: 0 1px 0 #21448d inset;
    box-shadow: 0 1px 0 #21448d inset;
}

And here’s how you can use the buttons (the following code creates the four buttons at the top of the page):

<div class="google-plus-button">Add</div>
<div class="google-plus-button blue">Save</div>
<div class="google-plus-button red">Add</div>
<div class="google-plus-button green">Post comment</div>

These buttons use the usual Google colors. But you can of course define colors which will better fit to the styles of your website but still provide the clean and polished look of the Google Plus buttons e.g.:

Google Plus Buttons other colors

Feel free to leave a comment if you spot a problem, have a suggestion how to improve them or just like them.

 

HTML5: Displaying the battery level

Note that this currently only works with Firefox. Support for Chrome and Internet Explorer is not yet available and it’s not yet known when it will be available.

The new Battery Status API allows you from a web page to access information about the battery status of the device rendering it. It is not only useful in order to show the current status but to implement battery status dependent logic e.g. increasing polling interval using Ajax or disabling animations in order to preserve the battery, or auto-saving in case the device goes out of power, prevent the user from performing long running operation which might not be able to finish because of the low remaining battery level.

First we’ll create the HTML and CSS in order to get an empty battery display looking like this:

The HTML code couldn’t be simpler. We just need a battery div:

<div id="battery"></div>

Now we need to display a border around the div and a smaller rectangle after it:

.battery:after {
    background-color: #fff;
    border: 2px solid #000;
    content: "";
    display: block;
    height: 16px;
    position: absolute;
    right: -6px;
    top: 6px;
    width: 6px;
}
.battery {
    background-color: #fff;
    border: 2px solid #000;
    height: 32px;
    margin-left: auto;
    margin-right: auto;
    position: relative;
    width: 100px;
}

Then we need to display a battery level within the battery display:

<div id="battery"><div id="battery-level"></div></div>

And we just need to add some CSS:

.battery .battery-level {
    background-color: #666;
    height: 100%;
}

By setting the width of .battery-level in pixels (or in percent which is the same since the element is 100 pixels wide) to the battery level in percents, we’ll get the right display:

Of course, one would expect our battery level display to show the level in a different color depending whether the battery is almost empty or not. So let’s introduce three CSS classes which will show the level in green, yellow or red:

Using the following CSS code:

.battery .battery-level.high {
    background-color: #66CD00;
}
.battery .battery-level.medium {
    background-color: #FCD116;
}
.battery .battery-level.low {
    background-color: #FF3333;
}

Before we move to the HTML5 part, let’s also display the battery level as text, by setting it as text on the battery-level element and by adding the following css rule:

.battery .battery-level {
    text-align: center;
}

It then looks like this:

10%
75%
95%

Now we’re almost done… All we need is what’s actually the main topic of this post: to get the battery level data using HTML5. For this we need to use the new Battery Status API.

The Battery Status API provides access the battery information through navigator.battery which implement the BatteryManager interface. This interface provides the following information:

  • whether the battery is currently charging
  • the charging time
  • the discharging time
  • the battery level

Additionally, it also provides events you can listen to:

  • onchargingchange
  • onchargingtimechange
  • ondischargingtimechange
  • onlevelchange

We will not use the events for now and just show the battery level when the page was loaded:

The JavaScript code to work with this API is pretty straight forward:

var battery = navigator.battery;
var level    = battery.level * 100;
var batteryLevel = jQuery('.battery .battery-level');
batteryLevel.css('width', level + '%');
batteryLevel.text(level + '%');
if (battery.charging) {
    batteryLevel.addClass('charging');
} else if (level > 50) {  
    batteryLevel.addClass('high');  
} else if (level >= 25 ) {  
    batteryLevel.addClass('medium');  
} else {  
    batteryLevel.addClass('low');  
}

If you want to update the battery level display as the battery charges and discharges:

Here’s the JavaScript code:

function updateBatteryDisplay(battery) {
	var level = battery.level * 100;
	var batteryLevel = jQuery('.battery .battery-level');
	batteryLevel.css('width', level + '%');
	batteryLevel.text(level + '%');
	if (battery.charging) {
	    batteryLevel.addClass('charging');
	    batteryLevel.removeClass('high');  
	    batteryLevel.removeClass('medium');  
	    batteryLevel.removeClass('low');  
	} else if (level > 50) {  
	    batteryLevel.addClass('high');  
	    batteryLevel.removeClass('charging');
	    batteryLevel.removeClass('medium');  
	    batteryLevel.removeClass('low');  
	} else if (level >= 25 ) {  
	    batteryLevel.addClass('medium');  
	    batteryLevel.removeClass('charging');
	    batteryLevel.removeClass('high');  
	    batteryLevel.removeClass('low');  
	} else {  
	    batteryLevel.addClass('low');  
	    batteryLevel.removeClass('charging');
	    batteryLevel.removeClass('high');  
	    batteryLevel.removeClass('medium');  
	}
}

var battery = navigator.battery;
updateBatteryDisplay(battery);
battery.onchargingchange = function () {
    updateBatteryDisplay(battery);
};
battery.onlevelchange = function () {
    updateBatteryDisplay(battery);
};

So the Battery Status API is a very powerful and useful API which is very easy to use. Now let’s hope it will soon be available in all major browsers !

ASP.NET: Slow first loading time

You might have experienced the problem that when you first load a large ASP.NET application (e.g. a CMS), it takes quite some time to load. If you then reload the page or even restart the browser and load the page again, it’s quite fast. There seems to be a few possible cause for this. So this post will not give you an extensive answer as to what all could go wrong but focus on application pool recycling.

What is an Application Pool?

Application Pools are used by IIS to isolate web applications. It allows you to use different settings in different applications. This is especially important when your different applications use different security settings. Applications in different application pools run in different windows processes (w3wp.exe) and thus also provide some kind of segregation by preventing an application from interfering with other applications. So an error in one application won’t cause other applications to crash or behave unexpectedly.

What is Application Pool Recycling?

Application pool recycling basically means that when a given event occurs, the resources related to an application pool will be recovered. It is mainly useful to prevent long running application from crashing or hanging e.g. because of memory leaks. When the recycling happens, a new worker process is started which will receive new web requests and the old one is shut down (once it’s done processing current requests), so there is no downtime while recycling.

Why does recycling cause the first load to last longer ?

Many applications need to first compile scripts or DLLs on the fly. Others need to load a large amount of data and pre-process it. This is basically what’s causing the delay on the first load. Afterwards once everything is compiled and data pre-processed, everything is fast.

Whenever an application pool is recycled and the worker processes are shutdown, next time the application is called, a new worker process needs to be started and these compilation and pre-processing activities need to be performed again.

When does recycling happen?

There are basically two different ways to recycle application pools:

  1. Recycling based on configuration
  2. On-demand recycling

On-demand recycling can be done:

  • in the IIS manager
  • from the command line using appcmd
  • using Windows Management Instrumentation (WMI) i.e. the ApplicationPool.Recycle method

Automatic application pool recycling can be configured to recycle:

  • when reaching a memory threshold (virtual memory or used memory)
  • when reaching a certain number of requests
  • at a scheduled time
  • after a scheduled time

Additionally, recycling will happen, when the configuration of an application is changed or when an unhealthy ISAPI condition is reported.

How to configure when automatic application pool recycling is done?

This can be configured in the Application Pools configuration panel of the IIS manager (Go to Start -> Administrative Tools -> Internet Information Services (IIS) Manager):

Application pool configuration

Select an application pool on the left-hand side and click on Recycling on the right.

The default configuration is to recycle an application pool after 29 hours (1740 minutes):

Application Pool Recycling Settings

If there are long periods of time during which your site/application has few hits, it might be a good idea to increase this default value. Actually, except if you know that you have a memory leak somewhere and do not manage to fix it, there is no big benefit in recycling your application pools at fixed intervals. If your application is running on a server where other applications are running, you may want to used the memory based maximums. Otherwise just removing the time interval based configuration may be a good solution. If nothing else it configured, you application pool will be recycled anyway once all available memory is used.

Idle Time-out

Also note that even though strictly speaking, it’s not an automatic application pool recycling, you can configure the application pool so that worker processes are shutdown after a specified amount on time being idle i.e. not receiving new requests or processing existing requests. The default value is 20 minutes. Actually I guess in most cases it makes no sense. It’s only useful if you have so limited resources that you need to get rid of unused application pools as fast as possible. So in most cases, I’d recommend setting the idle time-out to zero:

Application pool idle time-out

How do I know when recycling has occurred?

There are two places where you can configure under which conditions an event log entry is generated when an application pool is recycled.

The first one is when you press “Next” in the dialog shown above. You will then see the following:

Recycling application pool recycling events to log

The checkbox under “Configurable recycling events” are disable in this screenshot because I haven’t configured any  trigger for an automatic application pool recycling. But if you defined e.g. a number of requests, some checkboxes will be enabled.

Another place where you can set it is the Advanced Settings dialog. Just select your application pool and press “Advanced Settings”. The following dialog will be displayed:

Application pool advanced settings

The recycling settings are the bottom and contain a section called “Generate Recycle Event Log Entry”. You can then set the appropriate entries to true to get the required event log entries.

Also remember that starting from Windows 2008, you can have an email sent when an event is triggered.

Fixing the Shellshock GNU bash shell vulnerability

What’s shellshock?

Shellshock (also known as Bashdoor) is a vulnerability in GNU bash shell. It allows an attacker access to run remote commands on your system. It seems to affect the Bash versions 1.13 to 4.3. In the past few days, botnets have used compromised computers for distributed denial-of-service (DDOS) attacks and vulnerability scanning. Bash is installed as the default command line interface on many Unix-based systems. It is used to interpret commands and is itself a command which can be executed. As such it has both a list of environment variable and a list of internal functions. When launching a new bash interpreter, a new list of environment variables and functions can be exported to the new process. This vulnerability causes Bash to execute commands stored in environment variables in a special way. This happens when a newly started instance of Bash scans its environment variables for values in a special format, which should be converted to internal functions. In the affected versions, Bash creates fragments of code on-the-fly and executes them without checking whether the fragments are only function definitions. Using this vulnerability, the attacker can execute any arbitrary command.

How to check whether you are affected?

In order to check whether your system is affected you can execute the following from a shell:

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

If the ouput contains “vulnerable”, you are affected. Otherwise, it means the patch for Bash has already been installed (but keep in mind that there different ways to exploit this vulnerability and even if this check is negative, it’d be safe to update to newer versions of Bash as they are released).

Your server is not only vulnerable when spawning a Bash instance from the command line but also when Apache is used in combination with mod_cgi and spawns either a Bash shell or anything else (e.g. a Perl script) which executes commands and passes environment variables.

A few examples are:

  • A Perl script using the built-in functions exec or system to invoke a new shell process
  • A PHP script using the built-in functions exec or system to invoke a new shell process
  • A Python script using os.system or os.popenx (depending on how it is called)

Note that an attack on CGI scripts will only work if Bash is used as default shell.

Just to show you how easy it is to use this vulnerability against a server running Apache, mod_cgi and some CGI scripts spawning a shell:

curl "https://mysiteipaddress.com/index.cgi" --insecure -H "User-Agent: () { :; }; echo 'Hello Server' > /tmp/shellshock.log"

This will return some HTML code and will create a file /tmp/shellshock.log on the affected server.

How to fix it?

In most systems, it’s as easy as installing the latest Bash update. On Debian, Ubuntu and other systems using apt-get:

apt-get update && apt-get upgrade

On Red Hat, Fedory, CentOS and other systems using yum:

yum -y update bash

On Arch Linux:

pacman -Syu

On SLES:

zypper ref -s
zypper up bash

SUSE Linux Enterprise Server

Note that updatse for SLES are only available in LTSS versions and for SLES 11 SP3. If you are running an older non-LTSS version of SLES, you’ll have to install Bash from source as described below. Here the list of SLES versions for which an update is available:

  • SUSE Linux Enterprise Server 10 SP3 LTSS
  • SUSE Linux Enterprise Server 11 SP2 LTSS
  • SUSE Linux Enterprise Server 11 SP1 LTSS
  • SUSE Linux Enterprise Server 10 SP4 LTSS
  • SUSE Linux Enterprise Server 11 SP3

Red Hat Enterprise Linux

RHEL updates are available for the following versions:

  • Red Hat Enterprise Linux 4 Extended Lifecycle Support
  • Red Hat Enterprise Linux 5
  • Red Hat Enterprise Linux 5.6 Long Life
  • Red Hat Enterprise Linux 5.9 Extended Update Support
  • Red Hat Enterprise Linux 6
  • Red Hat Enterprise Linux 6.2 Advanced Update Support
  • Red Hat Enterprise Linux 6.4 Extended Update Support
  • Red Hat Enterprise Linux 7

 Mac OS X

Apple has released updates for Mac OS X Lion, Mountain Lion and Mavericks. Make sure that you install these updates even if Apple has been arguing that most Mac OS X users are not exposed unless they have configured advanced UNIX services. Since most Max OS X users do not have a web server running, the risk of having this vulnerability exploited is not as high as for Unix-based web servers accessible from the internet but you do not want to risk anything especially when the fix is as easy as updating your software (which should be done on a regular basis anyway).

How to install from source?

Latest Bash version (4.3)

If no update is available for your system (e.g. because you’re on an older version), you’ll have to download Bash 4.3, apply all patches, compile it and install it. If you have a direct access from your machine to the internet, do the following:

cd /tmp
mkdir bash
cd bash
wget https://ftp.gnu.org/gnu/bash/bash-4.3.tar.gz
for i in $(seq -f "%03g" 1 27); do wget https://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-$i; done
tar zxvf bash-4.3.tar.gz 
cd bash-4.3
for i in $(seq -f "%03g" 1 27);do patch -p0 < ../bash43-$i; done
./configure && make && make install

If there are more than 27 patches for Bash 4.3 when you read this replace both occurences of 27 by the appropriate number.

If you do not have direct access to the internet from the machine, you’ll have to download Bash 4.3 and all updates and then copy them through (S)FTP to /tmp/bash:

tar zxvf bash-4.3.tar.gz 
cd bash-4.3
for i in $(seq -f "%03g" 1 27);do patch -p0 < ../bash43-$i; done
./configure && make && make install

Note: If the files are renamed to bash43-0xx.txt when downloading, you’ll have to remove the .txt extension. And change 27 to the current number of patches for Bash 4.3.

Also note that bash will be installed in /usr/local/bin/bash. you will then need to make sure that the old bash is removed and replaced by a symlink to the new one:

cd /bin; rm bash; ln -s /usr/local/bin/bash

(thanks Gerhard for the hint)

Older Bash version (e.g. 3.2)

If you’re using an older version of Bash (e.g. because you’re running SLES 11 SP1), you might want to only update Bash to the latest update within the same version.

First create the working directory /tmp/bash using: mkdir /tmp/bash

Download https://ftp.gnu.org/gnu/bash/bash-3.2.48.tar.gz instead of the 4.3 package. This package already includes the updates until update 48. Additionally download updates 49 to 54 from https://ftp.gnu.org/gnu/bash/bash-3.2-patches/.

Note: If the files are renamed to bash32-0xx.txt when downloading, you’ll have to remove the .txt extension.

Upload all downloaded files to /tmp/bash. Go to /tmp/bash using: cd /tmp/bash and execute the following:

tar zxvf bash-3.2.48.tar.gz 
cd bash-3.2.48/
for i in $(seq -f "%03g" 49 54);do patch -p0 < ../bash32-$i; done
./configure && make && make install

Change 54 to the current number of patches for Bash 3.2.

Also note that this uses the patch command. If it is not installed, you’ll have to install it or you’ll have to perform all steps except the last one on a machine where patch is installed and then copy the resulting folder to the machine where it should be installed before executing the last command. Before executing this last command you might need to add execution permissions to the configure file:

chmod +x configure

If you get the following error message during the install step:

/home/install -m 0755 bash /usr/local/bin/bash
make: execvp: /home/install: Permission denied
make: *** [install] Error 127

You will have to execute the following:

install -m 0755 bash /usr/local/bin/bash

Note that bash will be installed in /usr/local/bin/bash. you will then need to make sure that the old bash is removed and replaced by a symlink to the new one:

cd /bin; rm bash; ln -s /usr/local/bin/bash

(thanks Gerhard for the hint)

 LD_LIBRARY_PATH

I’ve noticed that with the new version of Bash there may be some issues when setting LD_LIBRARY_PATH  before starting some software. Actually you should not be using LD_LIBRARY_PATH on a production system but rather rely on ldconfig. In order to do this, you should add all directories containing shared libraries to /etc/ld.so.conf and execute the following:

ldconfig -v

This way you make sure that even with an updated version of Bash your software will find the shared libraries without issues.