// This source code is now part of the PHPLint project, see:
// http://cvs.icosaedro.it:8080/viewvc/public/phplint/stdlib/it/icosaedro/web
// Test code also available under the test/ directory of that project.
/**
* Class for Italian Codice Fiscale normalization, formatting and checking.
* @author Umberto Salsi <salsi@icosaedro.it>
* @version $Date: 2020/01/23 10:35:20 $
*/
class CodiceFiscale
{
/**
* Normalizes a CF by removing white spaces and converting to upper-case.
* @param string cf Raw CF, possibly with spaces.
* @return string Normalized CF.
*/
static normalize(cf)
{
return cf.replace(/\s/g, "").toUpperCase();
}
/**
* Returns the formatted CF. Currently does nothing but normalization.
* @param string cf Raw CF, possibly with spaces.
* @return string Formatted CF.
*/
static format(cf)
{
return this.normalize(cf);
}
/**
* Validates a regular CF.
* @param string cf Normalized, 16 characters CF.
* @return string Null if valid, or string describing why this CF must be
* rejected.
*/
static PRIVATE_validate_regular(cf)
{
if( ! /^[0-9A-Z]{16}$/.test(cf) )
return "Invalid characters.";
var s = 0;
var even_map = "BAFHJNPRTVCESULDGIMOQKWZYX";
for(var i = 0; i < 15; i++){
var c = cf[i];
var n = 0;
if( "0" <= c && c <= "9" )
n = c.charCodeAt(0) - "0".charCodeAt(0);
else
n = c.charCodeAt(0) - "A".charCodeAt(0);
if( (i & 1) === 0 )
n = even_map.charCodeAt(n) - "A".charCodeAt(0);
s += n;
}
if( s%26 + "A".charCodeAt(0) !== cf.charCodeAt(15) )
return "Invalid checksum.";
return null;
}
/**
* Validates a temporary CF.
* @param string cf Normalized, 11 characters CF.
* @return string Null if valid, or string describing why this CF must be
* rejected.
*/
static PRIVATE_validate_temporary(cf)
{
if( ! /^[0-9]{11}$/.test(cf) )
return "Invalid characters.";
var s = 0;
for(var i = 0; i < 11; i++ ){
var n = cf.charCodeAt(i) - "0".charCodeAt(0);
if( (i & 1) === 1 ){
n *= 2;
if( n > 9 )
n -= 9;
}
s += n;
}
if( s % 10 !== 0 )
return "Invalid checksum.";
return null;
}
/**
* Verifies the basic syntax, length and control code of the given CF.
* @param string cf Raw CF, possibly with spaces.
* @return string Null if valid, or string describing why this CF must be
* rejected.
*/
static validate(cf)
{
cf = this.normalize(cf);
if( cf.length === 0 )
return "Empty.";
else if( cf.length === 16 )
return this.PRIVATE_validate_regular(cf);
else if( cf.length === 11 )
return this.PRIVATE_validate_temporary(cf);
else
return "Invalid length.";
}
}