var YAHOO_ULT_LIBCODE = 2;
var CTRL_C            = '\x03';
var CTRL_D            = '\x04';
var YAHOO_LRD_BEACON  = 'http://us.lrd.yahoo.com/t/b.gif';

var YAHOO_BASE64_STR  =  "ABCDEFGHIJKLMNOP" +
                         "QRSTUVWXYZabcdef" +
                         "ghijklmnopqrstuv" +
                         "wxyz0123456789._-";



/* generate a ylc url */
function yahoo_linktrack_click(u, p) {
    if (u && p) {} else { return u; }

    // hardcode _r to 2 for this library
    p['_r'] = YAHOO_ULT_LIBCODE;

    var ks = []; 
    var i = 0;
    for (var k in p) { 
        var v = p[k];
        if (typeof(v) == 'undefined') { v = p[k] = ''; }
        // keys must be at least 1 char long
        if (k.length < 1 ) { return u; }           
        // and not longer than 8
        if (k.length > 8) { return u; }
        // keys can't have spaces
        if (k.indexOf(' ') != -1) { return u; }   
        // or ctrl chars
        if (yahoo_has_ctrl_char(k) || yahoo_has_ctrl_char(v)) { return u; }  

        ks[i++] = k; 
    }
    ks = ks.sort(); 

    var f = [];
    for (var i = 0; i < ks.length; i++) {
        f[i] = ks[i] + CTRL_C + p[ks[i]];
    }
    f = f.join(CTRL_D);

    if (f.length < 1 || f.length > 1024) { return u; }

    f = ';_ylc=' + yahoo_encode64(f);

    var i = u.indexOf('/*'); 
    if (i == -1) { i = u.indexOf('/?'); }
    if (i == -1) { i = u.indexOf('?'); }

    if (i == -1) { 
        return u + f;
    } else {
        return u.substr(0, i) + f + u.substr(i);
    }
}

/* register an event on the lrd server by refreshing an img src */
function yahoo_linktrack_beacon(i, p) {
    if (i && p) {
        var url = yahoo_linktrack_click(YAHOO_LRD_BEACON, p);
        url += '?.rand=' + Math.random();
        i.src = url;
    }
}

function yahoo_has_ctrl_char(s) {
    for (i = 0; i < s.length; i++) {
        if( s.charCodeAt(i) < 0x20 ) {
            return true;
        }
    }
    return false;
}

function yahoo_encode64(input) {
    var output = "";
    var chr1, chr2, chr3 = "";
    var enc1, enc2, enc3, enc4 = "";
    var i = 0;

    do {
        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);

        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;

        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }

        output = output + 
        YAHOO_BASE64_STR.charAt(enc1) + 
        YAHOO_BASE64_STR.charAt(enc2) + 
        YAHOO_BASE64_STR.charAt(enc3) + 
        YAHOO_BASE64_STR.charAt(enc4);
        chr1 = chr2 = chr3 = "";
        enc1 = enc2 = enc3 = enc4 = "";
    } while (i < input.length);

    return output;
}
