/*

SYNOPSIS:


***
Part of this library (the encode/decode-functions) is built on GNU/GPL-licensed code from ostermiller.org

Here the functions have been put into a class

*/

function ObscureEmailsEncoder() {

	this.urlDecode = function (str) {
	    str=str.replace(new RegExp('\\+','g'),' ');
	    return unescape(str);
	};
	
	this.urlEncode = function (str) {
	    str=escape(str);
	    str=str.replace(new RegExp('\\+','g'),'%2B');
	    return str.replace(new RegExp('%20','g'),'+');
	};
	
	this.END_OF_INPUT = -1;
	
	this.base64Chars = new Array(
	    'A','B','C','D','E','F','G','H',
	    'I','J','K','L','M','N','O','P',
	    'Q','R','S','T','U','V','W','X',
	    'Y','Z','a','b','c','d','e','f',
	    'g','h','i','j','k','l','m','n',
	    'o','p','q','r','s','t','u','v',
	    'w','x','y','z','0','1','2','3',
	    '4','5','6','7','8','9','+','/'
	);
	
	this.reverseBase64Chars = new Array();
	
	
	for (var i=0; i < this.base64Chars.length; i++){
	    this.reverseBase64Chars[this.base64Chars[i]] = i;
	}
	
	
	this.base64Str = "";
	this.base64Count = 0;
	
	this.setBase64Str = function (str) {
	    this.base64Str = str;
	    this.base64Count = 0;
	};
	
	this.readBase64 = function(){    
	    if (!this.base64Str) return this.END_OF_INPUT;
	    if (this.base64Count >= this.base64Str.length) return this.END_OF_INPUT;
	    var c = this.base64Str.charCodeAt(this.base64Count) & 0xff;
	    this.base64Count++;
	    return c;
	};
	
	this.encodeBase64 = function(str) {
	    this.setBase64Str(str);
	    var result = '';
	    var inBuffer = new Array(3);
	    var lineCount = 0;
	    var done = false;
	    while (!done && (inBuffer[0] = this.readBase64()) != this.END_OF_INPUT){
	        inBuffer[1] = this.readBase64();
	        inBuffer[2] = this.readBase64();
	        result += (this.base64Chars[ inBuffer[0] >> 2 ]);
	        if (inBuffer[1] != this.END_OF_INPUT){
	            result += (this.base64Chars [(( inBuffer[0] << 4 ) & 0x30) | (inBuffer[1] >> 4) ]);
	            if (inBuffer[2] != this.END_OF_INPUT){
	                result += (this.base64Chars [((inBuffer[1] << 2) & 0x3c) | (inBuffer[2] >> 6) ]);
	                result += (this.base64Chars [inBuffer[2] & 0x3F]);
	            } else {
	                result += (this.base64Chars [((inBuffer[1] << 2) & 0x3c)]);
	                result += ('=');
	                done = true;
	            }
	        } else {
	            result += (this.base64Chars [(( inBuffer[0] << 4 ) & 0x30)]);
	            result += ('=');
	            result += ('=');
	            done = true;
	        }
	        lineCount += 4;
	        if (lineCount >= 76){
	            result += ('\n');
	            lineCount = 0;
	        }
	    }
	    return result;
	};
	
	this.readReverseBase64 = function () {   
	    if (!this.base64Str) return this.END_OF_INPUT;
	    while (true){      
	        if (this.base64Count >= this.base64Str.length) return this.END_OF_INPUT;
	        var nextCharacter = this.base64Str.charAt(this.base64Count);
	        this.base64Count++;
	        if (this.reverseBase64Chars[nextCharacter]){
	            return this.reverseBase64Chars[nextCharacter];
	        }
	        if (nextCharacter == 'A') return 0;
	    }
	    return this.END_OF_INPUT;
	};
	
	this.ntos = function(n) {
	    n=n.toString(16);
	    if (n.length == 1) n="0"+n;
	    n="%"+n;
	    return unescape(n);
	};
	
	this.decodeBase64 = function (str) {
	    this.setBase64Str(str);
	    var result = "";
	    var inBuffer = new Array(4);
	    var done = false;
	    while (!done && (inBuffer[0] = this.readReverseBase64()) != this.END_OF_INPUT
	        && (inBuffer[1] = this.readReverseBase64()) != this.END_OF_INPUT){
	        inBuffer[2] = this.readReverseBase64();
	        inBuffer[3] = this.readReverseBase64();
	        result += this.ntos((((inBuffer[0] << 2) & 0xff)| inBuffer[1] >> 4));
	        if (inBuffer[2] != this.END_OF_INPUT) {
	            result +=  this.ntos((((inBuffer[1] << 4) & 0xff)| inBuffer[2] >> 2));
	            if (inBuffer[3] != this.END_OF_INPUT) {
	                result +=  this.ntos((((inBuffer[2] << 6)  & 0xff) | inBuffer[3]));
	            } else {
	                done = true;
	            }
	        } else {
	            done = true;
	        }
	    }
	    return result;
	};
	
	this.digitArray = new Array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f');
	
	this.toHex = function(n) {
	    var result = ''
	    var start = true;
	    for (var i=32; i>0;){
	        i-=4;
	        var digit = (n>>i) & 0xf;
	        if (!start || digit != 0){
	            start = false;
	            result += this.digitArray[digit];
	        }
	    }
	    return (result==''?'0':result);
	};
	
	this.pad = function (str, len, pad) {
	    var result = str;
	    for (var i=str.length; i<len; i++){
	        result = pad + result;
	    }
	    return result;
	};
	
	this.encodeHex = function (str) {
	    var result = "";
	    for (var i=0; i<str.length; i++){
	        result += this.pad(this.toHex(str.charCodeAt(i)&0xff),2,'0');
	    }
	    return result;
	};
	
	this.decodeHex = function (str) {
	    str = str.replace(new RegExp("s/[^0-9a-zA-Z]//g"));
	    var result = "";
	    var nextchar = "";
	    for (var i=0; i<str.length; i++){
	        nextchar += str.charAt(i);
	        if (nextchar.length == 2){
	            result += this.ntos(eval('0x'+nextchar));
	            nextchar = "";
	        }
	    }
	    return result;
	};
}


// Class to do decoding
var ObscureEmails = {
	
	_encoder: new ObscureEmailsEncoder(),
	
	// Decode the emails which have been obscured
	decode: function() {
		// Decode emails in a-tags
		var anchors = document.getElementsByTagName("a");
		
		for (var i=0; i < anchors.length; i++) {
			if (anchors[i].href.substr(0, 7) == "mailto:") {
				anchors[i].href = "mailto:" + ObscureEmails._decodeEmail(anchors[i].href.substr(7));
			}
		}
		
		// Decode email in free text
		var span = document.getElementsByTagName("span");
		
		for (var i=0; i < span.length; i++) {
			if (span[i].className == "camus-obscure-email") {
				span[i].innerHTML = ObscureEmails._decodeEmail(span[i].innerHTML);
			}
		}
		
	},
	
	// Decode single mail
	_decodeEmail: function(email) {
		return ObscureEmails._encoder.decodeBase64(ObscureEmails._encoder.decodeBase64(email));
	}
	
}