NUM_DIGITOS_CPF = 11;
NUM_DIGITOS_CNPJ = 14;
NUM_DGT_CNPJ_BASE = 8;

String.prototype.lpad = function(pSize, pCharPad) {
	var str = this;
	var dif = pSize - str.length;
	var ch = String(pCharPad).charAt(0);
	for (; dif > 0; dif--)
		str = ch + str;
	return (str);
};

String.prototype.trim = function() {
	return this.replace(/^\s*/, "").replace(/\s*$/, "");
};

function unformatNumber(pNum) {
	return String(pNum).replace(/\D/g, "").replace(/^0+/, "");
}

function formatCpfCnpj(pCpfCnpj, pUseSepar, pIsCnpj) {
	if (pIsCnpj == null)
		pIsCnpj = false;
	if (pUseSepar == null)
		pUseSepar = true;
	var maxDigitos = pIsCnpj ? NUM_DIGITOS_CNPJ : NUM_DIGITOS_CPF;
	var numero = unformatNumber(pCpfCnpj);

	numero = numero.lpad(maxDigitos, '0');

	if (!pUseSepar)
		return numero;

	if (pIsCnpj) {
		reCnpj = /(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})$/;
		numero = numero.replace(reCnpj, "$1.$2.$3/$4-$5");
	} else {
		reCpf = /(\d{3})(\d{3})(\d{3})(\d{2})$/;
		numero = numero.replace(reCpf, "$1.$2.$3-$4");
	}
	return numero;
}

function dvCpfCnpj(pEfetivo, pIsCnpj) {
	if (pIsCnpj == null)
		pIsCnpj = false;
	var i, j, k, soma, dv;
	var cicloPeso = pIsCnpj ? NUM_DGT_CNPJ_BASE : NUM_DIGITOS_CPF;
	var maxDigitos = pIsCnpj ? NUM_DIGITOS_CNPJ : NUM_DIGITOS_CPF;
	var calculado = formatCpfCnpj(pEfetivo + "00", false, pIsCnpj);
	calculado = calculado.substring(0, maxDigitos - 2);
	var result = "";

	for (j = 1; j <= 2; j++) {
		k = 2;
		soma = 0;
		for (i = calculado.length - 1; i >= 0; i--) {
			soma += (calculado.charAt(i) - '0') * k;
			k = (k - 1) % cicloPeso + 2;
		}
		dv = 11 - soma % 11;
		if (dv > 9)
			dv = 0;
		calculado += dv;
		result += dv;
	}

	return result;
}

function isCpf(pCpf) {
	var numero = formatCpfCnpj(pCpf, false, false);
	if (numero.length > NUM_DIGITOS_CPF)
		return false;

	var base = numero.substring(0, numero.length - 2);
	var digitos = dvCpfCnpj(base, false);
	var algUnico, i;

	// Valida dígitos verificadores
	if (numero != "" + base + digitos)
		return false;

	/*
	 * Não serão considerados válidos os seguintes CPF: 000.000.000-00, 111.111.111-11, 222.222.222-22, 333.333.333-33, 444.444.444-44, 555.555.555-55, 666.666.666-66, 777.777.777-77, 888.888.888-88, 999.999.999-99.
	 */
	algUnico = true;
	for (i = 1; algUnico && i < NUM_DIGITOS_CPF; i++) {
		algUnico = (numero.charAt(i - 1) == numero.charAt(i));
	}
	return (!algUnico);
} // isCpf

function isCnpj(pCnpj) {
	var numero = formatCpfCnpj(pCnpj, false, true);
	if (numero.length > NUM_DIGITOS_CNPJ)
		return false;

	var base = numero.substring(0, NUM_DGT_CNPJ_BASE);
	var ordem = numero.substring(NUM_DGT_CNPJ_BASE, 12);
	var digitos = dvCpfCnpj(base + ordem, true);
	var algUnico;

	// Valida dígitos verificadores
	if (numero != "" + base + ordem + digitos)
		return false;

	/*
	 * Não serão considerados válidos os CNPJ com os seguintes números BÁSICOS: 11.111.111, 22.222.222, 33.333.333, 44.444.444, 55.555.555, 66.666.666, 77.777.777, 88.888.888, 99.999.999.
	 */
	algUnico = numero.charAt(0) != '0';
	for (var i = 1; algUnico && i < NUM_DGT_CNPJ_BASE; i++) {
		algUnico = (numero.charAt(i - 1) == numero.charAt(i));
	}
	if (algUnico)
		return false;

	/*
	 * Não será considerado válido CNPJ com número de ORDEM igual a 0000. Não será considerado válido CNPJ com número de ORDEM maior do que 0300 e com as três primeiras posições do número BÁSICO com 000 (zeros). Esta crítica não será feita quando o no BÁSICO do CNPJ for igual a 00.000.000.
	 */
	if (ordem == "0000")
		return false;
	return (base == "00000000" || parseInt(ordem, 10) <= 300 || base.substring(0, 3) != "000");
}

function isCpfCnpj(pCpfCnpj) {
	var numero = pCpfCnpj.replace(/\D/g, "");
	if (numero.length > NUM_DIGITOS_CPF)
		return isCnpj(pCpfCnpj);
	else
		return isCpf(pCpfCnpj);
}

