/****************************************************************************** * @file iban_analyzer.c * @brief Normalisation, validation et extraction locale d'IBAN. ******************************************************************************/ #include "core/iban_analyzer.h" #include char *iban_analyzer_normalize_canonical(const char *text) { if(text==NULL||strlen(text)>(1024U * 1024U))return NULL; GString *r=g_string_new(NULL); for(const unsigned char *p=(const unsigned char *)text;*p;p++) { if(*p==' '||*p=='\t'||*p=='\r'||*p=='\n'||*p=='-')continue; if(!g_ascii_isalnum(*p)){g_string_free(r,TRUE);return NULL;} g_string_append_c(r,g_ascii_toupper(*p)); } if(r->len==0){g_string_free(r,TRUE);return NULL;}return g_string_free(r,FALSE); } char *iban_analyzer_normalize(const char *text) { GString *result = NULL; if (text == NULL) return NULL; result = g_string_new(NULL); for (const char *cursor = text; *cursor != '\0'; cursor++) if (g_ascii_isalnum(*cursor)) g_string_append_c(result, g_ascii_toupper(*cursor)); if (result->len == 0) { g_string_free(result, TRUE); return NULL; } return g_string_free(result, FALSE); } gboolean iban_analyzer_validate(const char *iban) { char *normalized = iban_analyzer_normalize(iban); guint remainder = 0; gsize length = 0; if (normalized == NULL) return FALSE; length = strlen(normalized); if (length < 15 || length > 34 || !g_ascii_isalpha(normalized[0]) || !g_ascii_isalpha(normalized[1]) || !g_ascii_isdigit(normalized[2]) || !g_ascii_isdigit(normalized[3])) { g_free(normalized); return FALSE; } for (gsize offset = 0; offset < length; offset++) { char character = normalized[(offset + 4) % length]; if (g_ascii_isdigit(character)) remainder = (remainder * 10 + (guint)(character - '0')) % 97; else if (g_ascii_isalpha(character)) { guint value = (guint)(character - 'A') + 10; remainder = (remainder * 10 + value / 10) % 97; remainder = (remainder * 10 + value % 10) % 97; } else { g_free(normalized); return FALSE; } } g_free(normalized); return remainder == 1; } IbanAnalyzerResult iban_analyzer_validate_canonical_result(const char *iban) { char *normalized=iban_analyzer_normalize_canonical(iban); static const struct { const char *country; gsize length; } lengths[]={ {"BE",16},{"DE",22},{"ES",24},{"FR",27},{"GB",22}, {"IT",27},{"LU",20},{"NL",18},{"PT",25}}; if(normalized==NULL||strlen(normalized)<15||strlen(normalized)>34|| !g_ascii_isalpha(normalized[0])||!g_ascii_isalpha(normalized[1])|| !g_ascii_isdigit(normalized[2])||!g_ascii_isdigit(normalized[3])) { g_free(normalized);return IBAN_ANALYZER_RESULT_INVALID; } for(guint i=0;ilen; index++) if (g_strcmp0(candidate, g_ptr_array_index(results, index)) == 0) duplicate = TRUE; if (candidate != NULL && iban_analyzer_validate(candidate) && !duplicate) g_ptr_array_add(results, candidate); else g_free(candidate); g_free(raw); g_match_info_next(matches, NULL); } g_match_info_free(matches); g_regex_unref(regex); return results; }