if (!document.comDamonNS) {
    document.comDamonNS = new Array();
}
    
/*
 * various stuff I may have snarfed and forgot from where..., some I am to blame for.
 */

function tohex(c) {
    if ('0' <= c && c <= '9') return  0 + c.charCodeAt(0) - '0'.charCodeAt(0);
    if ('a' <= c && c <= 'f') return 10 + c.charCodeAt(0) - 'a'.charCodeAt(0);
    if ('A' <= c && c <= 'F') return 10 + c.charCodeAt(0) - 'A'.charCodeAt(0);
    alert('funny hex character: ' + c);
    return 0;
}
      
/*
 * Convert a hex string to an array of little-endian words
 */

function hex2binl(str) {
  var bin    = Array();
  var bphc   = 4;	 // bits per hex char
  var l2bphc = 2;
  var l2bpw  = 5;	// log 2 bits per word (2^5 == 32)
  
  for (var bit = 0; bit < bphc * str.length ; bit += bphc) {
      bin[bit >> l2bpw] |= tohex(str.charAt(bit >> l2bphc)) << (((((bit%32) >> l2bphc) ^ 1) << l2bphc)); // swap nibbles
  }
  
  return bin;
}

function hexlify(str) {
    var hexstr = '';
    var c;
    
    for (var i = 0; i < str.length; ++i) {
	c = str.charCodeAt(i);
	if (c <= '9') {
	    hexstr += '0';
	}
	hexstr += c.toString(16);
    }
    return hexstr;
}

function unhexlify(hexstr) {
    var str = '';
    var c;
    
    for (var i = 0; i < hexstr.length; i += 2) {
	c  = tohex(hexstr.charAt(i)) << 4;
	c += tohex(hexstr.charAt(i+1));

	str += String.fromCharCode(c);
    }
    return str;
}
    
/*
 * TEA encryption.  http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm
 */

function encode64(u_32, l_32, k, c) {
    var sum = 0;
    var delta = 0x9e3779b9;
 
    var y = new Number(u_32 ^ c[0]);
    var z = new Number(l_32 ^ c[1]);
 
    for (var i=0; i<32; ++i) {
	y    = 0xffffffff & (y + ((z << 4 ^ z >>> 5) + z ^ sum + k[sum & 3]));
	sum  = 0xffffffff & (sum + delta);
	z    = 0xffffffff & (z + ((y << 4 ^ y >>> 5) + y ^ sum + k[sum >> 11 & 3]));
    }
 
    return new Array(y, z)
}
 
 
function decode64(u_32, l_32, k, c) {
    var sum   = 0xc6ef3720;
    var delta = 0x9e3779b9;
 
    var y = new Number(u_32);	
    var z = new Number(l_32);
 
    for (var i=0; i<32; ++i) {
	z   = 0xffffffff & (z - ((y << 4 ^ y >>> 5) + y ^ sum + k[sum >> 11 & 3]));
	sum = 0xffffffff & (sum - delta);
	y   = 0xffffffff & (y - ((z << 4 ^ z >>> 5) + z ^ sum + k[sum & 3]));
 
    }
    return new Array(y ^ c[0], z ^ c[1])
}
 
function encode_str(key, str) {
    var estr = '';
    var crap = 0;
    var hdr  = '';

    //
    // initial character encodes length of prefix
    //
    if ((1 + str.length) % 16) {
        crap += 16 - ((1 + str.length) % 16);
    }

    hdr  = String.fromCharCode((Math.floor(Math.random() * 256) & 0xf0) + (crap & 0x0f));
    while (hdr.length != 1) {
	hdr = String.fromCharCode(Math.floor(Math.random() * 256) & 0xf0);
    }

    for (var i = 0; i < crap; ++i) {
        hdr += String.fromCharCode(Math.floor(Math.random() * 256) & 0x7f);
    }

    str = hdr + str;

    if (str.length % 16) {
	alert('foo');
    }

    str  = hexlify(str)
    estr = ''

    var c = new Array(0, 0)

    for (var i = 0; i < str.length; i += 16) {
	var p0 = Number('0x' + str.slice(i, i+8));
	var p1 = Number('0x' + str.slice(i+8, i+16));
	var zot = encode64(p0, p1, key, c);

	// alert(format('%s: [%x, %x] -> [%x, %x]', str, p0, p1, zot[0], zot[1]));

	c[0] = p0;
	c[1] = p1;
	
	for (var k = 0; k < 2; ++k) {
	    for (var l = 0; l < 4; ++l) {
		estr += String.fromCharCode((zot[k] >> (24 - l * 8)) & 0xff);
	    }
	}
    }

    return hexlify(estr)
}

function decode_str(key, estr) {
    var str = '';
    var state = 0;
    var skip;
	
    if (estr.length % 16) {
	alert(format('%s: %d', estr, estr.length));
	return false;
    }
    
    var c = new Array(0, 0)

    for (var i = 0; i < estr.length; i += 16) {
	var p0 = Number('0x' + estr.slice(i, i+8));
	var p1 = Number('0x' + estr.slice(i+8, i+16));
	var zot = decode64(p0, p1, key, c);

	c[0] = p0;
	c[1] = p1;
	
	for (var k = 0; k < 2; ++k) {
	    for (var l = 0; l < 4; ++l) {
		if (state == 0) {
		    skip  = 1 + ((zot[0] >> 24) & 0x0f);
		    ++state;
		}
		if (state == 1) {
		    if (--skip == 0) {
			++state;
		    }
		} else {
		    str += String.fromCharCode((zot[k] >> (24 - l * 8)) & 0xff);
		}
	    }
	}
    }

    return str
}

function decode(obj) {
    var NS = document.comDamonNS;
    var estr;

    if (obj.value) {
	estr = obj.value;
    } else if (obj.textContent) {
	estr = obj.textContent;
	var idx;
	while ((idx = estr.indexOf('\n')) >= 0) {
	    estr = estr.replace('\n', '');
	}
    } else {
	alert(obj);
	var db = window.open('', 'debug', 'height=800, width=600, resize=yes').document;
	dbg = function() {
	    db.write('<pre>' + vformat(arguments) + '</pre>\n');
	}

	obj_dump('obj', obj, 2, dbg);
	db.close();
    }
    
    var start = estr.indexOf('enc:');
    if (start != -1) {
      estr = estr.substring(4 + start, estr.length);
    }

    str = decode_str(NS.key, estr)

    if (obj.value) {
	obj.value = str;
    } else if (obj.textContent) {
	obj.textContent = str;
	//escape(str);
	//alert(str);
    }
    return true;
}

function encdec(obj) {
    if (obj) {
	if (false) {
	    var db = window.open('', 'debug', 'height=800, width=600, resize=yes').document;
	    dbg = function() {
		db.write('<pre>' + vformat(arguments) + '</pre>\n');
	    }

	    obj_dump('obj', obj, 2, dbg);
	    db.close();
	}
	if (obj.className == 'enc') {
	    if (decode(obj)) {
		obj.className = 'dec';
	    }
	}
    }
}

function cleartext() {
    var nodes = document.getElementsByTagName('*');
    
    for (var i = 0; i < nodes.length; ++i) {
	var elem = nodes[i];
	if (!elem.className) {
	    continue;
	}

	if (elem.className.indexOf('enc') >= 0) {
	    if (decode(elem)) {
		elem.className = elem.className.replace('enc', 'dec');
	    }
	}
    }
}

    
function pass_decode(str) {
    var NS = document.comDamonNS;

    if (!str || str.length != 32) {
	return '';
    }
    var key = hex2binl(NS.sig);
    var zot = hex2binl(str);
    var a   = decode64(zot[0], zot[1], key, new Array(0,0));
    var b   = decode64(zot[2], zot[3], key, new Array(0,0));
    
    return binl2hex(new Array(a[0], a[1], b[0], b[1]));
}

function pass_encode(str) {
    var NS = document.comDamonNS;

    if (!str || str.length != 32) {
	return '';
    }
    var key = hex2binl(NS.sig);
    var zot = hex2binl(str);
    var a   = encode64(zot[0], zot[1], key, new Array(0,0));
    var b   = encode64(zot[2], zot[3], key, new Array(0,0));
    
    return binl2hex(new Array(a[0], a[1], b[0], b[1]));
}

function checkKey() {
    var NS = document.comDamonNS;
    var passwd;
    var p;

    if (parent && parent.comDamonSession) {
	passwd = pass_decode(parent.comDamonSession);
    } else {
	passwd = 'wtf?';
    }

    while (navigator) {
	if (passwd.length == 32) {
	    if (passwd != binl2str(str2binl(passwd))) {
		alert(format('Warning: %s != %s', passwd, binl2str(str2binl(passwd))));
	    }

	    NS.key = hex2binl(passwd);

	    if (passwd != binl2hex(hex2binl(passwd))) {
		alert(format('Warning: %s != %s', passwd, binl2hex(hex2binl(passwd))));
	    }

	    var p0 = Number('0xf1cc36be');
	    var p1 = Number('0xfbffc4b1');
	    var zot = decode64(p0, p1, NS.key, new Array(0,0));

	    if (zot[0] == (NS.key[0] ^ NS.key[1]) && zot[1] == (NS.key[2] ^ NS.key[3])) {
		parent.comDamonSession = pass_encode(passwd);
		return true;
	    }
	}
	p = prompt("please provide password:");
	passwd = hex_md5(p);
    }
}

function obj_dump(prefix, o, max, dbg) {
    var NS = document.comDamonNS;

    if (NS.dump_seen) {
	if (typeof(o) == 'object' && NS.dump_seen[o]) {
	    return;
	}
    } else {
	NS.dump_seen = new Array();
	NS.dump_seen[NS.dump_seen] = true;
    }
	
    try {
	if (o) {
	    for (i in o) {
		try {
		    if (o[i]) {
			if (typeof(o[i]) == 'string') {
			    dbg('%s.%s: %s', prefix, i, escape(o[i]));
			} else if (typeof(o[i]) == 'function') {
			    dbg('%s.%s: function', prefix, i);
			} else if (typeof(o[i]) == 'object') {
			    dbg('%s.%s: object', prefix, i);
			    NS.dump_seen[o] = true;
			    
			    if (max > 0) {
				obj_dump(prefix + '.' + i, o[i], max-1, dbg);
			    }
			} else {
			    dbg('%s.%s: %s', prefix, i, o[i]);
			}
		    }
		} catch(e) {
		    var zot ='**gok';
		
		    try { zot = i; } catch (e) { ; }
		    dbg('>>> %s: %s', e, zot);
		}
	    }
	}
    } catch (e) {
	prompt(format('wtf?: %s', e));
    }
}

function mail_munger(obj) {
    var ns  = document.comDamonNS;
    var a   = document.createElement('a');
    var enc = obj.className;

    var start = enc.indexOf('enc:');
    if (start != -1) {
	enc = enc.substring(4 + start, enc.length);
    }
    var dec = decode_str(new Array(1957, 1, 15, 0), enc);

    if (false) {
	var db = window.open('', 'debug', 'height=800, width=600, resize=yes').document;
	dbg = function() {
	    db.write('<pre>' + vformat(arguments) + '</pre>');
	}
	obj_dump('obj', obj, 2, dbg);
	db.close();
    }
    
    a.setAttribute('href', 'mailto:' + dec);
    a.appendChild(document.createTextNode(dec));

    var nodes = obj.childNodes
    for (var i = 0; i < nodes.length; ++i) {
	var elem = nodes[i];

	if (elem && elem.setAttribute) {
	    elem.setAttribute('style', 'display: none')
	}
    }
    
    obj.appendChild(a);

    return true;
}

function munge() {
    var nodes = document.getElementsByTagName('span');
    
    for (var i = 0; i < nodes.length; ++i) {
	var elem = nodes[i];
	if (elem.id != 'munge') {
	    continue;
	}
	if (!elem.className) {
	    continue;
	}

	if (elem.className.indexOf('enc:') >= 0) {
	    if (mail_munger(elem)) {
		elem.className = elem.className.replace('enc:', 'dec:');
	    }
	}
    }
}
