Home / Indice sezione
 www.icosaedro.it 

 Controllo del codice fiscale e della partita IVA

cf-php.txt

<?php

// 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.


namespace it\icosaedro\web;

/*. require_module 'core'; require_module 'ctype'; require_module 'pcre'; .*/

/**
 * Italian Codice Fiscale normalization, formatting and validation routines.
 * A <u>regular CF</u> is composed by 16 among letters and digits; the last
 * character is always a letter representing the control code.
 * A <u>temporary CF</u> could also be assigned; a temporary CF is composed of
 * 11 digits, the last digit being the control code.
 * Examples: MRORSS00A00A000U, 12345678903.
 * @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.
	 * Useful to clean-up user's input and to save the result in the DB.
	 * @param string $cf Raw CF, possibly with spaces.
	 * @return string Normalized CF.
	 */
	static function normalize($cf)
	{
		$cf = (string) str_replace(" ", "", $cf);
		$cf = (string) str_replace("\t", "", $cf);
		$cf = (string) str_replace("\r", "", $cf);
		$cf = (string) str_replace("\n", "", $cf);
		$cf = strtoupper($cf);
		return $cf;
	}
	
	/**
	 * Returns the formatted CF. Currently does nothing but normalization.
	 * @param string $cf Raw CF, possibly with spaces.
	 * @return string Formatted CF.
	 */
	static function format($cf)
	{
		return self::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.
	 */
	private static function validate_regular($cf)
	{
		if( preg_match("/^[0-9A-Z]{16}\$/sD", $cf) !== 1 )
			return "Invalid characters.";
		$s = 0;
		$even_map = "BAFHJNPRTVCESULDGIMOQKWZYX";
		for( $i = 0; $i < 15; $i++ ){
			$c = $cf[$i];
			if( ctype_digit($c) )
				$n = ord($c) - ord('0');
			else
				$n = ord($c) - ord('A');
			if( ($i & 1) == 0 )
				$n = ord($even_map[$n]) - ord('A');
			$s += $n;
		}
		if( $s%26 + ord("A") !== ord($cf[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.
	 */
	private static function validate_temporary($cf)
	{
		if( preg_match("/^[0-9]{11}\$/sD", $cf) !== 1 )
			return "Invalid characters.";
		$s = 0;
		for( $i = 0; $i < 11; $i++ ){
			$n = ord($cf[$i]) - ord('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 function validate($cf)
	{
		$cf = self::normalize($cf);
		if( strlen($cf) == 0 )
			return "Empty.";
		else if( strlen($cf) == 16 )
			return self::validate_regular($cf);
		else if( strlen($cf) == 11 )
			return self::validate_temporary($cf);
		else
			return "Invalid length.";
	}
	
}

Vedi il codice come puro testo.

Umberto Salsi
Commenti
Contatto
Mappa
Home / Indice sezione
An abstract of the latest comments from the visitors of this page follows. Please, use the Comments link above to read all the messages or to add your contribute.

2019-01-31 by alberto fauro
Migliorie alla regex
il pattern ^[0-9A-Z]{16}$ può essere migliorato usando ^[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST]{1}[0-9LMNPQRSTUV]{2}[A-Z]{1}[0-9LMNPQRSTUV]{3}[A-Z]{1}$ che tiene conto delle sostituzioni valide delle cifre con lettere nel caso di omocodie [more...]