function in_array( needle, haystack ) {
    for( var i = 0 ; i < haystack.length ; i ++ ) {
        if( haystack[i] == needle )
            return true;
    }
    return false;
}

/* http://alexei.417.ro/node/12 */
function sprintf () {
    var a, f = arguments[0], fi= '', i = 1, m = [''], o = '', p;
    while (f = f.substring (m[0].length)) {
        m = /^([^\%]*)(?:(\x25)((\x25)|(?:(\d+)\$)?(\+)?(0|'([^$]))?(-|\^)?(\d+)?(?:\.(\d+))?([bcdefosuxX])))?/.exec(f);
        if (a = m[12]) {
            if (arguments.length < (i = m[5] || i))
            throw("sprintf '" + m[0] + "' : No argument " + i);
            a = arguments[i++];
            s = (/[def]/.test(m[12]) && m[6] && a > 0) ? '+':'';
            switch (m[12]) {
                case 'b': a = a.toString(2); break;
                case 'c': a = String.fromCharCode(a); break;
                case 'd': a = parseInt(a); break;
                case 'e': a = m[11] ? a.toExponential(m[11]) : a.toExponential(); break;
                case 'f': a = m[11] ? parseFloat(a).toFixed(m[11]) : parseFloat(a); break;
                case 'o': a = a.toString(8); break;
                case 's': a = ((a = String(a)) && m[11] ? a.substring(0, m[11]) : a); break;
                case 'u': a = Math.abs(a); break;
                case 'x': a = a.toString(16); break;
                case 'X': a = a.toString(16).toUpperCase(); break;
            }
            if (m[10] && (m[10] > a.length)) {
                fir=fil=str_repeat(m[7] ? m[8] || '0' : ' ', m[10]-a.length);
                if (m[9] == '^') {
                fil = fil.substr(0, fil.length / 2);
                fir = fir.substr(fil.length);
                } else
                m[9] == '-' ? (fil = '') : (fir = '');
                a = fil + a + fir;
            }
        }
        o += m[1] + ((m[3] ? m[4] || (s + a) : m[2]) || '');
    }
    return o;
}
