/* * SPDX-FileCopyrightText: 2023 jordi fita mas * * SPDX-License-Identifier: PostgreSQL */ #include "es.h" #include #include #include #include static char compute_dni_check_digit(const char *start, const char *end) { unsigned long int n = 0; const char *p = start; for(; p != end; p++) { n = n * 10 + *p - 48; } return "TRWAGMYFPDXBNJZSQVHLCKE"[n % 23]; } static bool valid_short_dni(const char *dni) { return dni[8] == compute_dni_check_digit(dni + 1, dni + 8); } static bool valid_dni(const char *dni) { return dni[8] == compute_dni_check_digit(dni, dni + 8); } static bool valid_nie(char *nie) { bool valid = false; nie[0] -= 'X' - 48; valid = nie[8] == compute_dni_check_digit(nie, nie + 8); nie[0] += 'X' - 48; return valid; } static bool valid_cif(const char *cif) { int odds = 0; int evens = 0; int n = 0; int checksum; for (n = 1; n < 8; n++) { if (n % 2 == 0) { evens += cif[n] - 48; } else { int d = (cif[n] - 48) * 2; int a = d / 10; int b = d % 10; odds += a + b; } } checksum = 10 - (odds + evens) % 10; return cif[8] == checksum + 48 || cif[8] == "JABCDEFGHI"[checksum]; } char * check_es_vat(const char *str, size_t len) { const char *p = str; const char *end = p + len; char buf[10] = { 0 }; int n = 0; if (len < 9 ) { return NULL; } for (; p != end && n < 10; p++) { char c = *p; if (c == ' ' || c == '-') continue; if (n > 0 && n < 8) { if (!isdigit(c)) { return NULL; } buf[n] = c; } else { buf[n] = toupper(c); } n++; } if (n == 10) { return NULL; } buf[9] = 0; switch (buf[0]) { case 'K': case 'L': case 'M': if (!valid_short_dni(buf)) { return NULL; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (!valid_dni(buf)) { return NULL; } break; case 'X': case 'Y': case 'Z': if (!valid_nie(buf)) { return NULL; } break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'J': case 'N': case 'P': case 'Q': case 'R': case 'S': case 'U': case 'V': case 'W': if (!valid_cif(buf)) { return NULL; } break; default: return NULL; } return pstrdup(buf); }