Calculating partial Hausdorff Distance

 
struct Point
{
	Point(int_t _x, int_t _y) : x(_x), y (_y)
	{
 
	}
 
	int_t x;
	int_t y;
};
 
 
typedef std::list<Point*> points_t;
 
double euclideanDistance(const Point& lhs,const Point& rhs)
{
	 double p1 = std::pow((float)(rhs.x - lhs.x), 2);
	 double p2 =  std::pow((float)(rhs.y - lhs.y), 2);
	 double vd =  std::sqrt(p1 + p2);
 
	 return vd;
}
 
 
double hausdorffPHD(points_t seta, points_t setb)
{
    double maxDistance = 0;
 
    points_t::iterator afront = seta.begin();
    points_t::iterator aback  = seta.end();
 
    std::vector<double> ranking;
 
    for(int_t i=0; afront != aback ; ++afront, ++i)
    {
    	Point* a = *afront;
        double minDistance = std::numeric_limits<double>::max();
 
        points_t::iterator bfront = setb.begin();
        points_t::iterator bback  = setb.end();
 
    	for(; bfront != bback ; ++bfront)
	    {
    		Point* b = *bfront;
    		double ed = euclideanDistance(*a, *b);
 
            if (ed < minDistance)
                minDistance = ed;
	    }
 
    	ranking.push_back(minDistance);
    }
 
    std::sort(ranking.begin(), ranking.end());
 
    double fraction = .7;
    int k = (int) (seta.size() * fraction);
    return ranking[k];
}
 
 
double hausdorff(points_t seta, points_t setb)
{
    double habPHD = hausdorffPHD( seta, setb);
    double hbaPHD = hausdorffPHD( setb, seta);
    double distancePHD = std::max(habPHD, hbaPHD);
    printf("hd = %0.4f\t %0.4f\t %0.4f\t \n", distancePHD, habPHD, hbaPHD);
    return distancePHD;
}
 
 
int_t main(int_t argc, char_t** args)
{
 
	points_t seta;
	points_t setb;
 
	seta.push_back(new Point(1,2));
	seta.push_back(new Point(2, 4));
 
	setb.push_back(new Point(2, 4));
	setb.push_back(new Point(3, 4));
 
	double val = hausdorff(seta, setb);
}

Compiling Webkit on Windows using Visual Studio 2012

Just some notes on compiling WebKit on windows with visual studio.

Issues :

C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xrefwrap(431): error C2064: term does not evaluate to a function taking 1 arguments (..\..\win\WebCoreSupport\WebFrameLoaderClient.cpp)
25>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(239) : see reference to function template instantiation '_Ret std::_Callable_obj<_Ty>::_ApplyX<_Rx,WebCore::PolicyAction>(_V0_t &&)' being compiled
25>          with
25>          [
25>              _Ret=void,
25>              _Ty=int,
25>              _Rx=void,
25>              _V0_t=WebCore::PolicyAction
25>          ]
25>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(239) : see reference to function template instantiation '_Ret std::_Callable_obj<_Ty>::_ApplyX<_Rx,WebCore::PolicyAction>(_V0_t &&)' being compiled
25>          with
25>          [
25>              _Ret=void,
25>              _Ty=int,
25>              _Rx=void,
25>              _V0_t=WebCore::PolicyAction
25>          ]
25>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(239) : while compiling class template member function 'void std::_Func_impl<_Callable,_Alloc,_Rx,_V0_t>::_Do_call(_V0_t &&)'
25>          with
25>          [
25>              _Callable=_MyWrapper,
25>              _Alloc=std::allocator>,
25>              _Rx=void,
25>              _V0_t=WebCore::PolicyAction
25>          ]
25>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(515) : see reference to class template instantiation 'std::_Func_impl<_Callable,_Alloc,_Rx,_V0_t>' being compiled
25>          with
25>          [
25>              _Callable=_MyWrapper,
25>              _Alloc=std::allocator>,
25>              _Rx=void,
25>              _V0_t=WebCore::PolicyAction
25>          ]
25>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(515) : see reference to function template instantiation 'void std::_Func_class<_Ret,_V0_t>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
25>          with
25>          [
25>              _Ret=void,
25>              _V0_t=WebCore::PolicyAction,
25>              _Ty=int,
25>              _Alloc=std::allocator>,
25>              _Fty=int
25>          ]
25>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(515) : see reference to function template instantiation 'void std::_Func_class<_Ret,_V0_t>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
25>          with
25>          [
25>              _Ret=void,
25>              _V0_t=WebCore::PolicyAction,
25>              _Ty=int,
25>              _Alloc=std::allocator>,
25>              _Fty=int
25>          ]
25>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(515) : see reference to function template instantiation 'void std::_Func_class<_Ret,_V0_t>::_Reset_alloc<_Ty,std::allocator>>(_Fty &&,_Alloc)' being compiled
25>          with
25>          [
25>              _Ret=void,
25>              _V0_t=WebCore::PolicyAction,
25>              _Ty=int,
25>              _Fty=int,
25>              _Alloc=std::allocator>
25>          ]
25>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(515) : see reference to function template instantiation 'void std::_Func_class<_Ret,_V0_t>::_Reset_alloc<_Ty,std::allocator>>(_Fty &&,_Alloc)' being compiled
25>          with
25>          [
25>              _Ret=void,
25>              _V0_t=WebCore::PolicyAction,
25>              _Ty=int,
25>              _Fty=int,
25>              _Alloc=std::allocator>
25>          ]
25>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(675) : see reference to function template instantiation 'void std::_Func_class<_Ret,_V0_t>::_Reset<_Ty>(_Fty &&)' being compiled
25>          with
25>          [
25>              _Ret=void,
25>              _V0_t=WebCore::PolicyAction,
25>              _Ty=int,
25>              _Fty=int
25>          ]
25>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(675) : see reference to function template instantiation 'void std::_Func_class<_Ret,_V0_t>::_Reset<_Ty>(_Fty &&)' being compiled
25>          with
25>          [
25>              _Ret=void,
25>              _V0_t=WebCore::PolicyAction,
25>              _Ty=int,
25>              _Fty=int
25>          ]
25>          ..\..\win\WebCoreSupport\WebFrameLoaderClient.cpp(97) : see reference to function template instantiation 'std::function<_Fty>::function(_Fx &&)' being compiled
25>          with
25>          [
25>              _Fty=void (WebCore::PolicyAction),
25>              _Fx=int
25>          ]
25>          ..\..\win\WebCoreSupport\WebFrameLoaderClient.cpp(97) : see reference to function template instantiation 'std::function<_Fty>::function(_Fx &&)' being compiled
25>          with
25>          [
25>              _Fty=void (WebCore::PolicyAction),
25>              _Fx=int
25>          ]

Patch
WebFrameLoaderClient.cpp
Line 97
- : m_policyFunction(0)
+ : m_policyFunction(nullptr)

Issue:

25>WebKitGUID.lib(WebKit_i.obj) : error LNK2005: _IID_IDOMDocumentType already defined in uuid.lib(i_mshtml.obj)
25>WebKitGUID.lib(WebKit_i.obj) : error LNK2005: _IID_IDOMProcessingInstruction already defined in uuid.lib(i_mshtml.obj)
25>WebKitGUID.lib(WebKit_i.obj) : error LNK2005: _IID_IDOMEvent already defined in uuid.lib(i_mshtml.obj)
25>WebKitGUID.lib(WebKit_i.obj) : error LNK2005: _IID_IDOMUIEvent already defined in uuid.lib(i_mshtml.obj)
25>WebKitGUID.lib(WebKit_i.obj) : error LNK2005: _IID_IDOMKeyboardEvent already defined in uuid.lib(i_mshtml.obj)
25>WebKitGUID.lib(WebKit_i.obj) : error LNK2005: _IID_IDOMMouseEvent already defined in uuid.lib(i_mshtml.obj)
25>WebKitGUID.lib(WebKit_i.obj) : error LNK2005: _IID_IDOMMutationEvent already defined in uuid.lib(i_mshtml.obj)
25>WebKitGUID.lib(WebKit_i.obj) : error LNK2005: _IID_IDOMWheelEvent already defined in uuid.lib(i_mshtml.obj)

Added linker option to WebKitGUID /FORCE:MULTIPLE
Now we get warning instead of errors;

13>WebKitGUID.lib(WebKit_i.obj) : warning LNK4006: _IID_IDOMDocumentType already defined in uuid.lib(i_mshtml.obj); second definition ignored
13>WebKitGUID.lib(WebKit_i.obj) : warning LNK4006: _IID_IDOMProcessingInstruction already defined in uuid.lib(i_mshtml.obj); second definition ignored
13>WebKitGUID.lib(WebKit_i.obj) : warning LNK4006: _IID_IDOMEvent already defined in uuid.lib(i_mshtml.obj); second definition ignored
13>WebKitGUID.lib(WebKit_i.obj) : warning LNK4006: _IID_IDOMUIEvent already defined in uuid.lib(i_mshtml.obj); second definition ignored
13>WebKitGUID.lib(WebKit_i.obj) : warning LNK4006: _IID_IDOMKeyboardEvent already defined in uuid.lib(i_mshtml.obj); second definition ignored
13>WebKitGUID.lib(WebKit_i.obj) : warning LNK4006: _IID_IDOMMouseEvent already defined in uuid.lib(i_mshtml.obj); second definition ignored
13>WebKitGUID.lib(WebKit_i.obj) : warning LNK4006: _IID_IDOMMutationEvent already defined in uuid.lib(i_mshtml.obj); second definition ignored
13>WebKitGUID.lib(WebKit_i.obj) : warning LNK4006: _IID_IDOMWheelEvent already defined in uuid.lib(i_mshtml.obj); second definition ignored
13>C:\cygwin\home\gbugaj\WebKit\WebKitBuild\Debug_WinCairo\bin32\WebKit.dll : warning LNK4088: image being generated due to /FORCE option; image may not run

Building Dependencies

Cairo

Issue

gbugaj@LTRMS7GB /cygdrive/c/cygwin/home/gbugaj/cairo
$ make -f Makefile.win32  CFG=release

make[1]: Entering directory '/cygdrive/c/cygwin/home/gbugaj/cairo/src'

cairo-deflate-stream.c
e:\source\c-libraries\zlib-1.2.3-lib\include\zconf.h(289) : fatal error C1083: Cannot open include file: 'unistd.h': No such file or directory
../build/Makefile.win32.common:55: recipe for target 'release/cairo-deflate-stream.obj' failed
make[1]: *** [release/cairo-deflate-stream.obj] Error 2
make[1]: Leaving directory '/cygdrive/c/cygwin/home/gbugaj/cairo/src'
Makefile.win32:12: recipe for target 'cairo' failed
make: *** [cairo] Error 2

Fix is to add empty ‘unistd.h’ to zlib include directory

Calculate centroid of 2D non crossing polygon

Calculate centroid of 2D non crossing polygon,
To accommodate that points are correct using Gift wrapping algorithm(Finding Convex Hull)

Test case

 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
 
import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
 
import org.junit.Test;
 
public class MathUtilTest
{
 
    @Test
    public void computeCentroidWithHull()
    {
        Point p1 = new Point(1, 1);
        Point p2 = new Point(2, 2);
        Point p3 = new Point(3, 1);
        Point p4 = new Point(1, 0);
        Point p5 = new Point(0, 1);
        Point p6 = new Point(5, 5);
 
        Point centroid2d = MathUtil.centroid2D(Arrays.asList(p1, p2, p3, p4, p5, p6));
        assertEquals(new Point(2, 1), centroid2d);
    }
 
    @Test
    public void computeCentroid()
    {
        Point p1 = new Point(1, 1);
        Point p2 = new Point(2, 2);
        Point p3 = new Point(3, 1);
 
        Point centroid2d = MathUtil.centroid2D(Arrays.asList(p1, p2, p3));
        assertEquals(new Point2D(2, 1), centroid2d);
    }
}

Implementation

    /**
     * Calculate centroid of 2D non crossing polygon, To accommodate that points
     * are correct using Gift wrapping algorithm(Finding Convex Hull)
     * 
     * @ref http://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon
     * @param vertices
     * @return
     */
    public static Point centroid2D(final List<Point> vertices)
    {
        if (vertices == null)
            return new Point(0, 0);
 
        List<Point> hull = null;
        if (vertices.size() < 2)
            hull = new ArrayList<Point>(vertices);
        else
            hull = findConvexHull(vertices);
 
        // Now we can calculate the centroid of polygon using standard mean
        final int len = hull.size();
        final double xy[] = new double[] { 0, 0 };
        for (int i = 0; i < len; ++i)
        {
            final Point p = hull.get(i);
            xy[0] += p.getX();
            xy[1] += p.getY();
        }
 
        final int x = (int) (xy[0] / len);
        final int y = (int) (xy[1] / len);
 
        return new Point(x, y);
    }

Find Convex hull of given points using Gift wrapping algorithm

Find Convex hull of given points using Gift wrapping algorithm


This is implementation of Grift wrapping algorithm for finding convex hull.

 
  private static final Integer ZERO = new Integer(0);
 
 
/**
     * Find Convex hull of given points
     * 
     * @ref http://en.wikipedia.org/wiki/Gift_wrapping_algorithm
     * @param vertices
     * @return
     */
    private static List<Point> findConvexHull(final List<Point> vertices)
    {
        if (vertices == null)
            return Collections.emptyList();
 
        if (vertices.size() < 3)
            return vertices;
 
        final List<Point> points = new ArrayList<Point>(vertices);
        final List<Point> hull = new ArrayList<Point>();
        Point pointOnHull = getExtremePoint(points, true);
        Point endpoint = null;
        do
        {
            hull.add(pointOnHull);
            endpoint = points.get(0);
 
            for (final Point r : points)
            {
                // Distance is used to find the outermost point -
                final int turn = findTurn(pointOnHull, endpoint, r);
                if (endpoint.equals(pointOnHull) || turn == -1 || turn == 0
                    && dist(pointOnHull, r) > dist(endpoint, pointOnHull))
                {
                    endpoint = r;
                }
            }
            pointOnHull = endpoint;
        } while (!endpoint.equals(hull.get(0))); // we are back at the start
 
        return hull;
    }
 
 
    private static double dist(final Point p, final Point q)
    {
        final double dx = (q.x - p.x);
        final double dy = (q.y - p.y);
        return dx * dx + dy * dy;
    }
 
 
   /**
     * Returns -1, 0, 1 if p,q,r forms a right, straight, or left turn. 
     * 1 = left, -1 = right, 0 = none
     * 
     * @ref http://www-ma2.upc.es/geoc/mat1q1112/OrientationTests.pdf
     * @param p
     * @param q
     * @param r
     * @return 1 = left, -1 = right, 0 = none
     */
    private static int findTurn(final Point p, final Point q, final Point r)
    {
        final int x1 = (q.x - p.x) * (r.y - p.y);
        final int x2 = (r.x - p.x) * (q.y - p.y);
        final int anotherInteger = x1 - x2;
        return ZERO.compareTo(anotherInteger);
    }

Convert Leptonica PIX data into Java BufferedImage

This snippet allows us to convert Leptonica PIX data into Java BufferedImage, in my case the pix->data could be compressed using zlib so I am decompressing before recreating image.
We are assuming here that this is bi-tonal image(1 bpp)

File used in example :

Image represented by the data:
binary

Sample Usage

   byte[] zlibData = FileUtil.read("pix-compressed.txt");
   BufferedImage image = LeptonicaUtil.convert(zlibData, width, height, 1);
   ImageIO.write(image, "png", new File("C:/temp/test.png"));

Code

 
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
 
/**
 * Utility for help us work with leptonica pix data
 * @author gbugaj
 *
 */
public class LeptonicaUtil
{
 
    public static BufferedImage convert(byte[] indata, int width, int height, int depth)
    {
        try
        {
            // Decompress the bytes
 
            byte[] pixdata = zlibDecompress(indata);
 
            // 4 (4 Bytes per Int)
            int wpl = (width * depth + 31) / 32;
            int byteCount = 4 * wpl * height;
            int rowSize = 4 * wpl;
            assert (byteCount == pixdata.length);
 
            BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
            WritableRaster raster = img.getRaster();
            byte[] rasterdata = new byte[width * height];
            int rasterindex = 0;
 
            for (int h = 0; h < height; ++h)
            {
                int start = h * rowSize;
                byte[] row = new byte[rowSize];
                System.arraycopy(pixdata, start, row, 0, rowSize);
                // Convert row bytes into linedata using 4 bytes to represent a
                // 32 bit int
                IntBuffer intBuffer = ByteBuffer.wrap(row).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer();
                int[] linedata = new int[intBuffer.remaining()];
                intBuffer.get(linedata);
                for (int w = 0; w < width; ++w)
                {
                    int word = w >> 5;
                    // need this to get proper byte ordering
                    int index = (31 - (w & 31));
                    byte val = (byte) (((linedata[word] >> index) & 1) ^ 1);
                    rasterdata[rasterindex] = val;
                    ++rasterindex;
                }
            }
 
            raster.setDataElements(0, 0, width, height, rasterdata);
            return img;
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (DataFormatException e)
        {
            e.printStackTrace();
        }
        return null;
    }
 
    public static byte[] zlibDecompress(byte[] data) throws IOException, DataFormatException
    {
 
        /**
         * 78 01 - No Compression/low 78 9C - Default Compression 78 DA - Best
         * Compression
         */
 
        if (data.length < 2)
            return data;
 
        // Check magic headers
        if (!((data[0] & 0xff) == 0x78 && ((data[1] & 0xff) == 0x01 || (data[1] & 0xff) == 0x9C || (data[1] & 0xff) == 0xDA)))
        {
            return data;
        }
 
        Inflater inflater = new Inflater();
        inflater.setInput(data);
 
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
        byte[] buffer = new byte[1024];
        int count = -1;
        while (!inflater.finished() && count != 0)
        {
            count = inflater.inflate(buffer);
            outputStream.write(buffer, 0, count);
        }
 
        inflater.end();
        outputStream.close();
        return outputStream.toByteArray();
    }
}

Convert Leptonica PIX data to Java BufferedImage

This snippet allows us to convert Leptonica PIX data into Java BufferedImage, in my case the pix->data could be compressed using zlib so I am decompressing before recreating image.
We are assuming here that this is bi-tonal image(1 bpp)

Sample Usage

   BufferedImage image = LeptonicaUtil.convert(zlibData, width, height, 1);
   ImageIO.write(image, "png", new File("C:/temp/test.png"));

Code

 
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
 
/**
 * Utility for help us work with leptonica pix data
 * @author gbugaj
 *
 */
public class LeptonicaUtil
{
 
    public static BufferedImage convert(byte[] indata, int width, int height, int depth)
    {
        try
        {
            // Decompress the bytes
 
            byte[] pixdata = zlibDecompress(indata);
 
            // 4 (4 Bytes per Int)
            int wpl = (width * depth + 31) / 32;
            int byteCount = 4 * wpl * height;
            int rowSize = 4 * wpl;
            assert (byteCount == pixdata.length);
 
            BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
            WritableRaster raster = img.getRaster();
            byte[] rasterdata = new byte[width * height];
            int rasterindex = 0;
 
            for (int h = 0; h < height; ++h)
            {
                int start = h * rowSize;
                byte[] row = new byte[rowSize];
                System.arraycopy(pixdata, start, row, 0, rowSize);
                // Convert row bytes into linedata using 4 bytes to represent a
                // 32 bit int
                IntBuffer intBuffer = ByteBuffer.wrap(row).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer();
                int[] linedata = new int[intBuffer.remaining()];
                intBuffer.get(linedata);
                for (int w = 0; w < width; ++w)
                {
                    int word = w >> 5;
                    // need this to get proper byte ordering
                    int index = (31 - (w & 31));
                    byte val = (byte) (((linedata[word] >> index) & 1) ^ 1);
                    rasterdata[rasterindex] = val;
                    ++rasterindex;
                }
            }
 
            raster.setDataElements(0, 0, width, height, rasterdata);
            return img;
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (DataFormatException e)
        {
            e.printStackTrace();
        }
        return null;
    }
 
    public static byte[] zlibDecompress(byte[] data) throws IOException, DataFormatException
    {
 
        /**
         * 78 01 - No Compression/low 78 9C - Default Compression 78 DA - Best
         * Compression
         */
 
        if (data.length < 2)
            return data;
 
        // Check magic headers
        if (!((data[0] & 0xff) == 0x78 && ((data[1] & 0xff) == 0x01 || (data[1] & 0xff) == 0x9C || (data[1] & 0xff) == 0xDA)))
        {
            return data;
        }
 
        Inflater inflater = new Inflater();
        inflater.setInput(data);
 
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
        byte[] buffer = new byte[1024];
        int count = -1;
        while (!inflater.finished() && count != 0)
        {
            count = inflater.inflate(buffer);
            outputStream.write(buffer, 0, count);
        }
 
        inflater.end();
        outputStream.close();
        return outputStream.toByteArray();
    }
}

Encrypting application configuration files – Java AES

There other day I needed to encrypt certain properties in our XML configuration files. But there were few challanges that needed to be addressed

  • Use existing Java installation
  • !!! How will Master Encryption Key be derives and stored !!!

First restriction is very important as it limits us to what algorithmic and key sizes can be used, adding Java Cryptography Extension was not a option.

This limited us to using AES with key size 128, using 256 would give us an exception.

java.security.InvalidKeyException:Illegal key size or default parameters

Second important question raised was “How will the master password be derived and possibly stored ?”, there are a number of approaches to this and each have its advantages, but the constraint here is that there should be no user interaction involved.

Few of the approaches considered

Passing password as a environment variable
This requires users to modify the startup parameters and the password is plain text
Prompting user to provider password when they start the application
This is good method(KeePass use it) but it requires user interaction, which was not acceptable in my case
Generating unique machine key
This method is not the best but it does work well, as long as the attacker don’t know how the key was generated.

Approach chosen by me was to use the machine generated key/id, I have chooses the MAC address as the machine key, I know it can be easily spoofed but if the attacker is that dedicated then I am screwed anyway.

Machine key generation algorithm is is straight forward. First we will try to obtain the MAC Address from the network interface, if that fails we we try to use the machine name obtained from the RuntimeMXBean, this is very depended on what JVM we are using as there is no guarantee what getName() method will return, if this fails we will fall back to using
System.getenv("COMPUTERNAME"), if all this fails we simply throw an exception.

Encrypted Message Format

CRYPT:Ss3iHK6kHLswAh7AyoHdo1dbbTJt0UpLxVNRZ9W+bks=

Encrypted messages can be broken down into three parts

Identifier : CRYPT used to indicate that this property have been encrypted

Initial Vector + Data : Ss3iHK6kHLswAh7AyoHdo1dbbTJt0UpLxVNRZ9W+bks=

Because we know the IV size(128 bits) we can prepend that to the begging of our encrypted message, so when we are decrypting the message we know that first 128bits will be the IV.


Example Usage

  AESEncryptDecryptUtil util = new AESEncryptDecryptUtil();
        String encrypedMessage = util
            .encrypt("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin scelerisque sodales augue, ac tristique nibh euismod nec. ");
        boolean status = util.isEncrypted(encrypedMessage);
 
        System.out.println("Encrypted : " + encrypedMessage);
        System.out.println("Message encrypted : " + status);
        System.out.println("Decrypted : " + util.decrypt(encrypedMessage));

Encrypting Properties

   public String getUserName()
    {
        try
        {
            AESEncryptDecryptUtil util = new AESEncryptDecryptUtil();
            if (util.isEncrypted(userName))
            {
                return util.decrypt(userName);
            }
        }
        catch (EncryptDecryptException e)
        {
            e.printStackTrace();
        }
        return userName;
    }

Output

Encrypted : CRYPT:keGhiojDBpgsUkdepcT6aFvzR0Jpsmi4no3TwP3OzFbAmjvvBxkSQHMyQ8uM81PTCTEWebe3HrE5
o/+jLgdmQB+CDxBMUvUrFRvFFAGsrCcS+cWgYTi+T5/LTUFonXBOc5r++GQbV2htxy9YislL2JPT
vMQAGrgMjOFTDBZvuJdeUIC6uKWjtndJidxigxHB
Message encrypted : true
Decrypted : Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin scelerisque sodales augue, ac tristique nibh euismod nec.

Code Listing

 
import java.io.UnsupportedEncodingException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.security.AlgorithmParameters;
import java.security.InvalidKeyException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.KeySpec;
 
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
 
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
 
/**
 * AES Encryption/Decryption Utility that uses MAC address as the Master
 * Encryption Key Initial Vector need to be stored together with the encrypted
 * string so that we can use it to decrypt the message. This is the format that
 * will be produced from the encryption, both encrypted message and initial
 * vector are base 64 encoded, in UTF-8 char set
 * <code>CRYPT:initialVector+encryptedMessage</code>
 * 
 * @author gbugaj
 */
public class AESEncryptDecryptUtil
{
 
    private static final int ITERATIONS = 65536;
 
    private static final String STRING_ENCODING = "UTF-8";
 
    private static final String CRYPT_PREFIX = "CRYPT";
 
    /**
     * If we user Key size of 256 we will get java.security.InvalidKeyException:
     * Illegal key size or default parameters , Unless we configure Java
     * Cryptography Extension 128
     */
    private static final int KEY_SIZE = 128;
 
    private static final byte[] SALT = { (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0 };
 
    private SecretKeySpec secret;
 
    private Cipher cipher;
 
    private BASE64Encoder base64Encoder;
 
    private BASE64Decoder base64Decoder;
 
    private AESEncryptDecryptUtil() throws EncryptDecryptException
    {
        try
        {
            /* Derive the key, given password and salt. */
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            KeySpec spec;
 
            spec = new PBEKeySpec(getHardwareKey(), SALT, ITERATIONS, KEY_SIZE);
            SecretKey tmp = factory.generateSecret(spec);
            secret = new SecretKeySpec(tmp.getEncoded(), "AES");
 
            // CBC = Cipher Block chaining
            // PKCS5Padding Indicates that the keys are padded
            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
 
            // For production use commons base64 encoder
            base64Decoder = new BASE64Decoder();
            base64Encoder = new BASE64Encoder();
        }
        catch (Exception e)
        {
            throw new EncryptDecryptException("Unable to initialize", e);
        }
 
    }
 
    /**
     * Get hardware key to be used for encryption, we rely on MAC address as the
     * key, with fallback to JVM name then windows machine name
     * 
     * @return key as char[]
     * @throws EncryptDecryptException
     */
    private char[] getHardwareKey() throws EncryptDecryptException
    {
 
        // Exceptions from this are ignored as we move to next available method
        try
        {
            InetAddress address = InetAddress.getLocalHost();
            NetworkInterface nic = NetworkInterface.getByInetAddress(address);
            if (nic != null)
            {
                byte[] mac = nic.getHardwareAddress();
                if (mac != null && mac.length > 0)
                {
                    return new String(mac, STRING_ENCODING).toCharArray();
                }
            }
        }
        catch (UnknownHostException e)
        {
            e.printStackTrace();
        }
        catch (SocketException e)
        {
            e.printStackTrace();
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }
 
        // Could not obtain MAC Address so we are falling back on the computer
        // name then on the JVM Name
        RuntimeMXBean rmx = ManagementFactory.getRuntimeMXBean();
        String jvmName = rmx.getName();
        String[] parts = jvmName.split("@");
        if (parts.length > 0)
        {
            String name = parts[1];
            if (name != null && !name.isEmpty())
            {
                return name.toCharArray();
            }
        }
 
        String name = System.getenv("COMPUTERNAME");
        if (name != null && !name.isEmpty())
        {
            return name.toCharArray();
        }
        throw new EncryptDecryptException("Unable to obtain Secure Key");
    }
 
    /**
     * Encrypt given input string
     * 
     * @param input
     * @return
     * @throws EncryptDecryptException
     */
    public String encrypt(String input) throws EncryptDecryptException
    {
        try
        {
            byte[] inputBytes = input.getBytes(STRING_ENCODING);
            cipher.init(Cipher.ENCRYPT_MODE, secret);
            AlgorithmParameters params = cipher.getParameters();
            byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
            byte[] ciphertext = cipher.doFinal(inputBytes);
            byte[] out = new byte[iv.length + ciphertext.length];
            System.arraycopy(iv, 0, out, 0, iv.length);
            System.arraycopy(ciphertext, 0, out, iv.length, ciphertext.length);
            return CRYPT_PREFIX + ":" + base64Encoder.encode(out);
        }
 
        catch (IllegalBlockSizeException e)
        {
            throw new EncryptDecryptException("Unable to encrypt", e);
        }
        catch (BadPaddingException e)
        {
            throw new EncryptDecryptException("Unable to encrypt", e);
        }
        catch (InvalidKeyException e)
        {
            throw new EncryptDecryptException("Unable to encrypt", e);
        }
        catch (InvalidParameterSpecException e)
        {
            throw new EncryptDecryptException("Unable to encrypt", e);
        }
        catch (UnsupportedEncodingException e)
        {
            throw new EncryptDecryptException("Unable to encrypt", e);
        }
    }
 
    /**
     * Decrypt input string
     * 
     * @param input
     * @return decrypted string
     * @throws EncryptDecryptException
     */
    @SuppressWarnings("restriction")
    public String decrypt(String input) throws EncryptDecryptException
 
    {
        if (!input.startsWith(CRYPT_PREFIX))
        {
            throw new EncryptDecryptException("Unable to decrypt, input string does not start with 'CRYPT'");
        }
 
        try
        {
            byte[] data = base64Decoder.decodeBuffer(input.substring(6, input.length()));
            int keylen = KEY_SIZE / 8;
            byte[] iv = new byte[keylen];
            System.arraycopy(data, 0, iv, 0, keylen);
            cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
            return new String(cipher.doFinal(data, keylen, data.length - keylen), STRING_ENCODING);
        }
        catch (Exception e)
        {
            throw new EncryptDecryptException("Unable to decrypt ", e);
        }
    }
 
    /**
     * Helper Exception to wrap arround Encryption/Decryption exceptions
     */
    @SuppressWarnings("serial")
    private static class EncryptDecryptException extends Exception
    {
        public EncryptDecryptException()
        {
            super();
        }
 
        public EncryptDecryptException(String msg)
        {
            super(msg);
        }
 
        public EncryptDecryptException(String msg, Throwable t)
        {
            super(msg, t);
        }
 
        public EncryptDecryptException(Throwable t)
        {
            super(t);
        }
    }
 
    /**
     * Check if given string is already encrypted
     * 
     * @param input
     * @return
     */
    private boolean isEncrypted(String input)
    {
        if (input == null || input.isEmpty())
        {
            return false;
        }
        return input.startsWith(CRYPT_PREFIX);
    }
 
    public static void main(String[] args) throws EncryptDecryptException
    {
        AESEncryptDecryptUtil util = new AESEncryptDecryptUtil();
        String encrypedMessage = util
            .encrypt("TEST");
        boolean status = util.isEncrypted(encrypedMessage);
 
        System.out.println("Encrypted : " + encrypedMessage);
        System.out.println("Message encrypted : " + status);
        System.out.println("Decrypted : " + util.decrypt(encrypedMessage));
    }
 
}

Leptonica barcode generation

Leptonica provides us with easy way to read barcodes but it does not offer a way to create them(as far as I know). Here is a leptonica function that will allow us to generate CODABAR barcode, in the feature I am planning on adding more type and more options but for now this was all I needed.


Sample Usage

l_int32 res = 300;
l_int32 bar_width = .02 * res;
l_int32 bar_height = .35 * res;
 
// Barcode is bitonal
PIX* barcode= pixCreateBarcodeCodebar("C3853110009C", bar_width, bar_height, 10, 10, 2, 2);
if (barcode == NULL)
{
	printf("\n******** ERROR ***********");
	return;
}
pixWritePng("c:/temp/barcode.png", barcode, 0);

Implementation

/**
 * Barcode Generator
 * @author : greg
 */
#ifndef CREATEBARCODE_H_
#define CREATEBARCODE_H_
 
#include <ctype.h>
 
#if !defined(LEPTONICA_ALLHEADERS_H)
#   include <leptonica/allheaders.h>
#endif
 
#if !defined(LEPTONICA_READBARCODE_H)
#	include <leptonica/readbarcode.h>
#endif
 
/* ----------------------------------------------------------------- *
 * Codabar symbology                         *
 * Data  B  S  B  S  B  S  B   Value
 * 0     0  0  0  0  0  1  1     0
 * 1     0  0  0  0  1  1  0     1
 * 2     0  0  0  1  0  0  1     2
 * @ref http://www.barcodesymbols.com/codabar.htm
 * @ref leptonica/readbarcode.h
 * ----------------------------------------------------------------- */
static const char *CodabarCodes[] =
{ "1111122", "1111221", "1112112", "2211111", "1121121", /* 0: 0 - 4      */
"2111121", "1211112", "1211211", "1221111", "2112111", /* 5: 5 - 9      */
"1112211", "1122111", "2111212", "2121112", "2121211", /* 10: -,$,:,/,. */
"1121212", "1122121", "1212112", "1112122", "1112221" /* 15: +,A,B,C,D */
};
 
int mapCodebarToIndex(const char c)
{
	switch (toupper(c))
	{
	case '0':
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
		return atoi(&c);
	case '-':
		return 10;
	case '$':
		return 11;
	case ':':
		return 12;
	case '/':
		return 13;
	case '.':
		return 14;
	case '+':
		return 15;
	case 'A':
		return 16;
	case 'B':
		return 17;
	case 'C':
	case '*':
		return 18;
	case 'E':
	case 'D':
		return 19;
 
	}
	return 0;
}
 
/**
 * Crate 8 bpp Codebar barcode
 */
PIX* pixCreateBarcodeCodebar(const char* code, l_int32 bar_width, l_int32 bar_height, l_int32 margin_left,
		l_int32 margin_right, l_int32 margin_top, l_int32 margin_bottom)
{
	PROCNAME("pixCreateBarcodeCodebar");
 
	printf("\n Rendering : %s", code);
	//The width ratio between narrow and wide can be chosen between 1:2.25 and 1:3
	l_float32 ratio = 2;
	l_int32 width_wide = bar_width * ratio;
	l_int32 narrow_space = bar_width;
	// Calculate size
	l_int32 size = 0;
	for (int i = 0; code[i] != '\0'; ++i, ++size)
	{
		// NOOP
	}
	// allocate big enough image
	PIX* pix = pixCreate(size * width_wide * 7, bar_height, 1);
	pixSetResolution(pix, 300, 300);
 
	l_int32 xpos = margin_left;
	for (int i = 0; i < size; ++i)
	{
		const char* encoding = CodabarCodes[mapCodebarToIndex(code[i])];
		for (l_uint16 j = 0; j < 7; j++)
		{
			l_int32 renderwidth = bar_width;
			if (encoding[j] == '2')
			{
				renderwidth = width_wide;
			}
			if ((j % 2 == 0))
			{
				for (l_int32 k = 0; k < renderwidth; ++k)
				{
//					pixRenderLineArb(pix, xpos+k, 0, xpos+k, height, 1, 0, 0, 0);
					pixRenderLine(pix, xpos + k, margin_top, xpos + k, bar_height - margin_bottom, 1, L_SET_PIXELS);
				}
			}
			xpos += renderwidth;
		}
 
		// Each character is separated by narrow space
		if (i < size - 1)
			xpos += narrow_space;
	}
 
	// Clip
	BOX* bounds = boxCreate(0, 0, xpos + margin_right, bar_height);
	pix = pixClipRectangle(pix, bounds, NULL);
	boxDestroy(&bounds);
	return pix;
}
 
#endif /* CREATEBARCODE_H_ */

I think I will make this my first GIT project and share it with all, trying to move away from google code.

Population Count using popcnt instruction (counting number of on bits)

Using popcnt instruction found on newer processors to get population count which is number of set bits.

Reference : SSE4



Here are couple example inputs with expected output.

 0xA =  1010 -- > 2
 0x3F2 =  1111110010 -- > 7	
#include <iostream>
#include <stdio.h>
 
using namespace std;
 
int main() {
	// 0xA =  1010 -- > 2
	// 0x3F2 =  1111110010 -- > 7
 
	unsigned long code = 0x3F2UL;
	int bitcount = 0;
 
	__asm__( "movl %1, %%eax; "  //code into eax
			"popcnt  %%eax,  %%eax;"//  call popcnt instruction
			"movl %%eax, %0;"// ebx into bitcount
			:"=r"(bitcount)// output
			:"r"(code)// input
			:"%eax","%ebx","%ecx","%edx"// clobbered register
	);
 
	printf("%d", bitcount);
	return 0;
}

java.lang.ClassNotFoundException: org.springframework.web.context.support.StandardServletEnvironment

While upgrading from Spring 3.0.5 to 3.1.1.RELEASE I started getting following exception.

java.lang.ClassNotFoundException: org.springframework.web.context.support.StandardServletEnvironment
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
	at org.springframework.web.servlet.HttpServletBean.<init>(HttpServletBean.java:90)
	at org.springframework.web.servlet.FrameworkServlet.<init>(FrameworkServlet.java:211)
	at org.springframework.web.servlet.DispatcherServlet.<init>(DispatcherServlet.java:323)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
	at java.lang.Class.newInstance0(Class.java:355)
	at java.lang.Class.newInstance(Class.java:308)

After some research I came to conclusion that the file have been factored out into ‘spring-web’ subproject.

So to solve this all we need to do is include ‘spring-web’ dependency

            <dependency>
 
         	<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
			<exclusions>
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

Hope this might help someone save some time.