Compare commits

..

No commits in common. "1df8abb7d2e23e66c69928ffe03262f8247607b1" and "b6884d6398caae3217520e0511f73406be7bf825" have entirely different histories.

12 changed files with 436 additions and 452 deletions

View File

@ -15,7 +15,11 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Install PostgreSQL development tools - name: Install PostgreSQL development tools
run: sudo apt install postgresql-server-dev-13 run: sudo apt install postgresql-server-dev-13
- name: Make # - name: configure
# run: ./configure
- name: make
run: make run: make
# - name: Install # - name: make check
# run: sudo make install # run: make check
# - name: make distcheck
# run: make distcheck

View File

@ -1,34 +1,23 @@
![C/C++ CI](https://github.com/yorickdewid/PostgreSQL-IBAN/workflows/C/C++%20CI/badge.svg) # PostgreSQL-IBAN
# PostgreSQL IBAN
PostgreSQL IBAN extension that can verify International Bank Account Numbers. PostgreSQL IBAN extension that can verify International Bank Account Numbers.
This ensures that only valid bank account numbers are stored. This ensures that only valid bank account numbers are stored.
### Example ### Example
```sql ```sql
CREATE TABLE test_iban ( CREATE TABLE test_iban (
name text, id serial NOT NULL,
account iban name character varying(32),
account iban,
CONSTRAINT test_iban_pkey PRIMARY KEY (id)
) )
--
-- Insert data -- Insert data
-- INSERT INTO test_iban (name, account) VALUES ('John', 'NL91ABNA0417164300'); -- Dutch IBAN format
INSERT INTO test_iban (name, account) VALUES ('Doe', 'DE89370400440532013000'); -- German IBAN format
-- Dutch IBAN format -- Invalid bank account
INSERT INTO test_iban (name, account) VALUES ('John', 'NL91ABNA0417164300');
-- German IBAN format
INSERT INTO test_iban (name, account) VALUES ('Doe', 'DE89370400440532013000');
-- Invalid data
INSERT INTO test_iban (name, account) VALUES ('Dean', 'AZ22NABZ00000000137010001944'); INSERT INTO test_iban (name, account) VALUES ('Dean', 'AZ22NABZ00000000137010001944');
--
-- Show output
--
SELECT * FROM test_iban;
``` ```
Manually test input Manually test input
@ -42,19 +31,3 @@ the `::iban` datatype can be cast to an text to perform string operations
```sql ```sql
SELECT 'KZ86125KZT5004100100'::iban::text; SELECT 'KZ86125KZT5004100100'::iban::text;
``` ```
## Build
Make sure PostgreSQL development tools are installed (check `pg_config`)
```bash
git clone https://github.com/yorickdewid/PostgreSQL-IBAN
cd PostgreSQL-IBAN
make install
```
Login to the database and load the extension
```sql
CREATE EXTENSION iban;
```

5
debian/changelog vendored
View File

@ -1,5 +0,0 @@
postgresql-iban (1.0.0~git15.g0e533af-1) bookworm; urgency=medium
* Add Debian packaging
-- jordi fita mas <jordi@tandem.blog> Mon, 19 Jun 2023 08:54:47 +0000

22
debian/control vendored
View File

@ -1,22 +0,0 @@
Source: postgresql-iban
Section: database
Priority: optional
Maintainer: jordi fita mas <jordi@tandem.blog>
Build-Depends:
debhelper-compat (= 13),
postgresql-all (>= 217~),
Standards-Version: 4.6.0
Vcs-Browser: https://github.com/yorickdewid/PostgreSQL-IBAN
Vcs-Git: https://github.com/yorickdewid/PostgreSQL-IBAN.git
Homepage: https://github.com/yorickdewid/PostgreSQL-IBAN
Rules-Requires-Root: no
Package: postgresql-15-iban
Architecture: any
Depends:
${shlibs:Depends},
${misc:Depends},
${postgresql:Depends}
description: IBAN type for PostgreSQL
PostgreSQL IBAN extension that can verify International Bank Account Numbers.
This ensures that only valid bank account numbers are stored.

22
debian/control.in vendored
View File

@ -1,22 +0,0 @@
Source: postgresql-iban
Section: database
Priority: optional
Maintainer: jordi fita mas <jordi@tandem.blog>
Build-Depends:
debhelper-compat (= 13),
postgresql-all (>= 217~),
Standards-Version: 4.6.0
Vcs-Browser: https://github.com/yorickdewid/PostgreSQL-IBAN
Vcs-Git: https://github.com/yorickdewid/PostgreSQL-IBAN.git
Homepage: https://github.com/yorickdewid/PostgreSQL-IBAN
Rules-Requires-Root: no
Package: postgresql-PGVERSION-iban
Architecture: any
Depends:
${shlibs:Depends},
${misc:Depends},
${postgresql:Depends}
description: IBAN type for PostgreSQL
PostgreSQL IBAN extension that can verify International Bank Account Numbers.
This ensures that only valid bank account numbers are stored.

29
debian/copyright vendored
View File

@ -1,29 +0,0 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https://github.com/yorickdewid/PostgreSQL-IBAN
Upstream-Name: PostgreSQL-IBAN
Upstream-Contact: yorick17@outlook.com
Files: *
Copyright: 2016 Yorick de Wid
License: GPL-3+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Comment:
On Debian systems, the complete text of the GNU General Public
License version 3 can be found in "/usr/share/common-licenses/GPL-3".
Files: debian/*
Copyright: 2023 jordi fita mas
License: GPL-3+
This debian package is distributed under the same license as the source
package.

1
debian/pgversions vendored
View File

@ -1 +0,0 @@
13+

6
debian/rules vendored
View File

@ -1,6 +0,0 @@
#!/usr/bin/make -f
include /usr/share/postgresql-common/pgxs_debian_control.mk
%:
dh $@ --with pgxs_loop

View File

@ -1 +0,0 @@
3.0 (quilt)

581
iban.cpp
View File

@ -1,7 +1,6 @@
/* /*
* IBAN: PostgreSQL functions and datatype * IBAN: PostgreSQL functions and datatype
* Copyright © 2016 Yorick de Wid <yorick17@outlook.com> * Copyright © 2016 Yorick de Wid <yorick17@outlook.com>
*
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
@ -22,78 +21,52 @@ extern "C"
{ {
#include "postgres.h" #include "postgres.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "libpq/pqformat.h" #include "libpq/pqformat.h"
} }
#include <iostream>
#include <sstream>
#include <string>
#include <cctype>
#include <regex> #include <regex>
class Specification { #include "specification.h"
public: #include "validate.h"
Specification(std::string structure, size_t length)
: structure{ structure }
, m_length{ length }
{
};
inline size_t getLength() const noexcept // #define PG_RETURN_IBAN_P(x) PG_RETURN_POINTER(x)
extern "C"
{ {
return m_length; PG_MODULE_MAGIC;
typedef char Iban;
} }
std::string structure; void Validate::addSpecification(Specification* specPtr) {
this->specifications[specPtr->countryCode] = specPtr;
private:
size_t m_length;
};
class Validate {
public:
Validate();
bool isValid(std::string arg);
void addSpecification(std::string countryCode, size_t length, std::string structure) noexcept
{
specifications.emplace(countryCode, std::make_unique<Specification>(structure, length));
} }
std::map<std::string, std::unique_ptr<Specification>> specifications;
};
/* Validator global instance. */
static Validate validator;
/** /**
* Calculates the MOD 97 10 of the passed IBAN as specified in ISO7064. * Calculates the MOD 97 10 of the passed IBAN as specified in ISO7064.
* *
* @param string iban * @param string iban
* @returns {bool} * @returns {bool}
*/ */
static bool iso7064Mod97_10(std::string iban) { bool iso7064Mod97_10(std::string iBan) {
std::rotate(iban.begin(), iban.begin() + 4, iban.end()); std::rotate(iBan.begin(), iBan.begin() + 4, iBan.end());
std::string numberstring;//will contain the letter substitutions
/* Will contain the letter substitutions */ for (const auto& c : iBan) {
std::string numberstring; if (std::isdigit(c))
numberstring.reserve(iban.size());
for (const auto& c : iban) {
if (std::isdigit(c)) {
numberstring += c; numberstring += c;
} if (std::isupper(c))
if (std::isupper(c)) {
numberstring += std::to_string(static_cast<int>(c) - 55); numberstring += std::to_string(static_cast<int>(c) - 55);
} }
} //implements a stepwise check for mod 97 in chunks of 9 at the first time
// , then in chunks of seven prepended by the last mod 97 operation converted
/* //to a string
* Implements a stepwise check for mod 97 in chunks of 9 at the first time int segstart = 0;
* then in chunks of seven prepended by the last mod 97 operation converted
* to a string
*/
size_t segstart = 0;
int step = 9; int step = 9;
std::string prepended; std::string prepended;
long number = 0; long number = 0;
@ -101,19 +74,17 @@ static bool iso7064Mod97_10(std::string iban) {
number = std::stol(prepended + numberstring.substr(segstart, step)); number = std::stol(prepended + numberstring.substr(segstart, step));
int remainder = number % 97; int remainder = number % 97;
prepended = std::to_string(remainder); prepended = std::to_string(remainder);
if (remainder < 10) { if (remainder < 10)
prepended = "0" + prepended; prepended = "0" + prepended;
}
segstart = segstart + step; segstart = segstart + step;
step = 7; step = 7;
} }
number = std::stol(prepended + numberstring.substr(segstart)); number = std::stol(prepended + numberstring.substr(segstart));
return number % 97 == 1; return (number % 97 == 1);
} }
/** /**
* Parse the IBAN structure used to configure each iban specification and returns a matching regular expression. * parse the bban structure used to configure each iban specification and returns a matching regular expression.
* a structure is composed of blocks of 3 characters (one letter and 2 digits). each block represents * a structure is composed of blocks of 3 characters (one letter and 2 digits). each block represents
* a logical group in the typical representation of the bban. for each group, the letter indicates which characters * a logical group in the typical representation of the bban. for each group, the letter indicates which characters
* are allowed in this group and the following 2-digits number tells the length of the group. * are allowed in this group and the following 2-digits number tells the length of the group.
@ -121,13 +92,14 @@ static bool iso7064Mod97_10(std::string iban) {
* @param {string} structure the structure to parse * @param {string} structure the structure to parse
* @returns {regexp} * @returns {regexp}
*/ */
static std::regex parseStructure(std::string structure) { std::regex parseStructure(std::string structure) {
std::smatch match; std::smatch match;
std::string::const_iterator text_iter = structure.cbegin(); std::string::const_iterator text_iter = structure.cbegin();
std::ostringstream result; std::ostringstream result;
while (std::regex_search(text_iter, structure.cend(), match, std::regex("(.{3})"))) { while (std::regex_search(text_iter, structure.cend(), match,
std::regex("(.{3})"))) {
std::string format; std::string format;
char pattern = match[0].str()[0]; char pattern = match[0].str()[0];
int repeats = std::stoi((match[0].str().substr(1))); int repeats = std::stoi((match[0].str().substr(1)));
@ -152,225 +124,320 @@ static std::regex parseStructure(std::string structure) {
return std::regex(regex.c_str()); return std::regex(regex.c_str());
} }
bool Validate::isValid(std::string account) { bool Validate::isValid(std::string arg) {
/* Convert uppercase */ Specification* spec = new Specification(arg);
std::transform(account.begin(), account.end(), account.begin(), toupper);
/* Reject anything too small */ /* Convert uppercase */
if (account.length() < 3) { std::transform(spec->example.begin(), spec->example.end(),
return false; spec->example.begin(), toupper);
}
/* Match on country */ /* Match on country */
const std::string& countryCode = account.substr(0, 2); spec->countryCode = spec->example.substr(0, 2);
const std::string& shortened = account.substr(4); spec->length = spec->example.length();
Specification* specFound = this->specifications[spec->countryCode];
const std::unique_ptr<Specification>& specFound = specifications[countryCode]; if (!specFound)
if (!specFound) {
return false; return false;
}
/* Test accountnumber */ /* Test accountnumber */
return specFound->getLength() == account.length() std::string shortened = spec->example.substr(4, spec->example.length());
bool result = specFound->length == spec->length
&& specFound->countryCode.compare(spec->countryCode) == 0
&& std::regex_match(shortened, parseStructure(specFound->structure)) && std::regex_match(shortened, parseStructure(specFound->structure))
&& iso7064Mod97_10(account); && iso7064Mod97_10(spec->example);
delete spec;
return result;
}
Validate::~Validate() {
for (auto it = specifications.begin(); it != specifications.end(); it++) {
delete it->second;
}
} }
Validate::Validate() { Validate::Validate() {
addSpecification( addSpecification(new Specification(
"AD", 24, "F04F04A12"); "AD", 24, "F04F04A12",
addSpecification( "AD1200012030200359100100"));
"AE", 23, "F03F16"); addSpecification(new Specification(
addSpecification( "AE", 23, "F03F16",
"AL", 28, "F08A16"); "AE070331234567890123456"));
addSpecification( addSpecification(new Specification(
"AT", 20, "F05F11"); "AL", 28, "F08A16",
addSpecification( "AL47212110090000000235698741"));
"AZ", 28, "U04A20"); addSpecification(new Specification(
addSpecification( "AT", 20, "F05F11",
"BA", 20, "F03F03F08F02"); "AT611904300234573201"));
addSpecification( addSpecification(new Specification(
"BE", 16, "F03F07F02"); "AZ", 28, "U04A20",
addSpecification( "AZ21NABZ00000000137010001944"));
"BG", 22, "U04F04F02A08"); addSpecification(new Specification(
addSpecification( "BA", 20, "F03F03F08F02",
"BH", 22, "U04A14"); "BA391290079401028494"));
addSpecification( addSpecification(new Specification(
"BR", 29, "F08F05F10U01A01"); "BE", 16, "F03F07F02",
addSpecification( "BE68539007547034"));
"CH", 21, "F05A12"); addSpecification(new Specification(
addSpecification( "BG", 22, "U04F04F02A08",
"CR", 21, "F03F14"); "BG80BNBG96611020345678"));
addSpecification( addSpecification(new Specification(
"CY", 28, "F03F05A16"); "BH", 22, "U04A14",
addSpecification( "BH67BMAG00001299123456"));
"CZ", 24, "F04F06F10"); addSpecification(new Specification(
addSpecification( "BR", 29, "F08F05F10U01A01",
"DE", 22, "F08F10"); "BR9700360305000010009795493P1"));
addSpecification( addSpecification(new Specification(
"DK", 18, "F04F09F01"); "CH", 21, "F05A12",
addSpecification( "CH9300762011623852957"));
"DO", 28, "U04F20"); addSpecification(new Specification(
addSpecification( "CR", 21, "F03F14",
"EE", 20, "F02F02F11F01"); "CR0515202001026284066"));
addSpecification( addSpecification(new Specification(
"ES", 24, "F04F04F01F01F10"); "CY", 28, "F03F05A16",
addSpecification( "CY17002001280000001200527600"));
"FI", 18, "F06F07F01"); addSpecification(new Specification(
addSpecification( "CZ", 24, "F04F06F10",
"FO", 18, "F04F09F01"); "CZ6508000000192000145399"));
addSpecification( addSpecification(new Specification(
"FR", 27, "F05F05A11F02"); "DE", 22, "F08F10",
addSpecification( "DE89370400440532013000"));
"GB", 22, "U04F06F08"); addSpecification(new Specification(
addSpecification( "DK", 18, "F04F09F01",
"GE", 22, "U02F16"); "DK5000400440116243"));
addSpecification( addSpecification(new Specification(
"GI", 23, "U04A15"); "DO", 28, "U04F20",
addSpecification( "DO28BAGR00000001212453611324"));
"GL", 18, "F04F09F01"); addSpecification(new Specification(
addSpecification( "EE", 20, "F02F02F11F01",
"GR", 27, "F03F04A16"); "EE382200221020145685"));
addSpecification( addSpecification(new Specification(
"GT", 28, "A04A20"); "ES", 24, "F04F04F01F01F10",
addSpecification( "ES9121000418450200051332"));
"HR", 21, "F07F10"); addSpecification(new Specification(
addSpecification( "FI", 18, "F06F07F01",
"HU", 28, "F03F04F01F15F01"); "FI2112345600000785"));
addSpecification( addSpecification(new Specification(
"IE", 22, "U04F06F08"); "FO", 18, "F04F09F01",
addSpecification( "FO6264600001631634"));
"IL", 23, "F03F03F13"); addSpecification(new Specification(
addSpecification( "FR", 27, "F05F05A11F02",
"IS", 26, "F04F02F06F10"); "FR1420041010050500013M02606"));
addSpecification( addSpecification(new Specification(
"IT", 27, "U01F05F05A12"); "GB", 22, "U04F06F08",
addSpecification( "GB29NWBK60161331926819"));
"KW", 30, "U04A22"); addSpecification(new Specification(
addSpecification( "GE", 22, "U02F16",
"KZ", 20, "F03A13"); "GE29NB0000000101904917"));
addSpecification( addSpecification(new Specification(
"LB", 28, "F04A20"); "GI", 23, "U04A15",
addSpecification( "GI75NWBK000000007099453"));
"LC", 32, "U04F24"); addSpecification(new Specification(
addSpecification( "GL", 18, "F04F09F01",
"LI", 21, "F05A12"); "GL8964710001000206"));
addSpecification( addSpecification(new Specification(
"LT", 20, "F05F11"); "GR", 27, "F03F04A16",
addSpecification( "GR1601101250000000012300695"));
"LU", 20, "F03A13"); addSpecification(new Specification(
addSpecification( "GT", 28, "A04A20",
"LV", 21, "U04A13"); "GT82TRAJ01020000001210029690"));
addSpecification( addSpecification(new Specification(
"MC", 27, "F05F05A11F02"); "HR", 21, "F07F10",
addSpecification( "HR1210010051863000160"));
"MD", 24, "U02A18"); addSpecification(new Specification(
addSpecification( "HU", 28, "F03F04F01F15F01",
"ME", 22, "F03F13F02"); "HU42117730161111101800000000"));
addSpecification( addSpecification(new Specification(
"MK", 19, "F03A10F02"); "IE", 22, "U04F06F08",
addSpecification( "IE29AIBK93115212345678"));
"MR", 27, "F05F05F11F02"); addSpecification(new Specification(
addSpecification( "IL", 23, "F03F03F13",
"MT", 31, "U04F05A18"); "IL620108000000099999999"));
addSpecification( addSpecification(new Specification(
"MU", 30, "U04F02F02F12F03U03"); "IS", 26, "F04F02F06F10",
addSpecification( "IS140159260076545510730339"));
"NL", 18, "U04F10"); addSpecification(new Specification(
addSpecification( "IT", 27, "U01F05F05A12",
"NO", 15, "F04F06F01"); "IT60X0542811101000000123456"));
addSpecification( addSpecification(new Specification(
"PK", 24, "U04A16"); "KW", 30, "U04A22",
addSpecification( "KW81CBKU0000000000001234560101"));
"PL", 28, "F08F16"); addSpecification(new Specification(
addSpecification( "KZ", 20, "F03A13",
"PS", 29, "U04A21"); "KZ86125KZT5004100100"));
addSpecification( addSpecification(new Specification(
"PT", 25, "F04F04F11F02"); "LB", 28, "F04A20",
addSpecification( "LB62099900000001001901229114"));
"RO", 24, "U04A16"); addSpecification(new Specification(
addSpecification( "LC", 32, "U04F24",
"RS", 22, "F03F13F02"); "LC07HEMM000100010012001200013015"));
addSpecification( addSpecification(new Specification(
"SA", 24, "F02A18"); "LI", 21, "F05A12",
addSpecification( "LI21088100002324013AA"));
"SE", 24, "F03F16F01"); addSpecification(new Specification(
addSpecification( "LT", 20, "F05F11",
"SI", 19, "F05F08F02"); "LT121000011101001000"));
addSpecification( addSpecification(new Specification(
"SK", 24, "F04F06F10"); "LU", 20, "F03A13",
addSpecification( "LU280019400644750000"));
"SM", 27, "U01F05F05A12"); addSpecification(new Specification(
addSpecification( "LV", 21, "U04A13",
"ST", 25, "F08F11F02"); "LV80BANK0000435195001"));
addSpecification( addSpecification(new Specification(
"TL", 23, "F03F14F02"); "MC", 27, "F05F05A11F02",
addSpecification( "MC5811222000010123456789030"));
"TN", 24, "F02F03F13F02"); addSpecification(new Specification(
addSpecification( "MD", 24, "U02A18",
"TR", 26, "F05F01A16"); "MD24AG000225100013104168"));
addSpecification( addSpecification(new Specification(
"VG", 24, "U04F16"); "ME", 22, "F03F13F02",
addSpecification( "ME25505000012345678951"));
"XK", 20, "F04F10F02"); addSpecification(new Specification(
addSpecification( "MK", 19, "F03A10F02",
"AO", 25, "F21"); "MK07250120000058984"));
addSpecification( addSpecification(new Specification(
"BF", 27, "F23"); "MR", 27, "F05F05F11F02",
addSpecification( "MR1300020001010000123456753"));
"BI", 16, "F12"); addSpecification(new Specification(
addSpecification( "MT", 31, "U04F05A18",
"BJ", 28, "F24"); "MT84MALT011000012345MTLCAST001S"));
addSpecification( addSpecification(new Specification(
"CI", 28, "U01F23"); "MU", 30, "U04F02F02F12F03U03",
addSpecification( "MU17BOMM0101101030300200000MUR"));
"CM", 27, "F23"); addSpecification(new Specification(
addSpecification( "NL", 18, "U04F10",
"CV", 25, "F21"); "NL91ABNA0417164300"));
addSpecification( addSpecification(new Specification(
"DZ", 24, "F20"); "NO", 15, "F04F06F01",
addSpecification( "NO9386011117947"));
"IR", 26, "F22"); addSpecification(new Specification(
addSpecification( "PK", 24, "U04A16",
"JO", 30, "A04F22"); "PK36SCBL0000001123456702"));
addSpecification( addSpecification(new Specification(
"MG", 27, "F23"); "PL", 28, "F08F16",
addSpecification( "PL61109010140000071219812874"));
"ML", 28, "U01F23"); addSpecification(new Specification(
addSpecification( "PS", 29, "U04A21",
"MZ", 25, "F21"); "PS92PALS000000000400123456702"));
addSpecification( addSpecification(new Specification(
"QA", 29, "U04A21"); "PT", 25, "F04F04F11F02",
addSpecification( "PT50000201231234567890154"));
"SN", 28, "U01F23"); addSpecification(new Specification(
addSpecification( "RO", 24, "U04A16",
"UA", 29, "F25"); "RO49AAAA1B31007593840000"));
addSpecification( addSpecification(new Specification(
"EG", 27, "F23"); "RS", 22, "F03F13F02",
addSpecification( "RS35260005601001611379"));
"CG", 27, "F23"); addSpecification(new Specification(
addSpecification( "SA", 24, "F02A18",
"GA", 27, "F23"); "SA0380000000608010167519"));
addSpecification(new Specification(
"SE", 24, "F03F16F01",
"SE4550000000058398257466"));
addSpecification(new Specification(
"SI", 19, "F05F08F02",
"SI56263300012039086"));
addSpecification(new Specification(
"SK", 24, "F04F06F10",
"SK3112000000198742637541"));
addSpecification(new Specification(
"SM", 27, "U01F05F05A12",
"SM86U0322509800000000270100"));
addSpecification(new Specification(
"ST", 25, "F08F11F02",
"ST68000100010051845310112"));
addSpecification(new Specification(
"TL", 23, "F03F14F02",
"TL380080012345678910157"));
addSpecification(new Specification(
"TN", 24, "F02F03F13F02",
"TN5910006035183598478831"));
addSpecification(new Specification(
"TR", 26, "F05F01A16",
"TR330006100519786457841326"));
addSpecification(new Specification(
"VG", 24, "U04F16",
"VG96VPVG0000012345678901"));
addSpecification(new Specification(
"XK", 20, "F04F10F02",
"XK051212012345678906"));
addSpecification(new Specification(
"AO", 25, "F21",
"AO69123456789012345678901"));
addSpecification(new Specification(
"BF", 27, "F23",
"BF2312345678901234567890123"));
addSpecification(new Specification(
"BI", 16, "F12",
"BI41123456789012"));
addSpecification(new Specification(
"BJ", 28, "F24",
"BJ39123456789012345678901234"));
addSpecification(new Specification(
"CI", 28, "U01F23",
"CI17A12345678901234567890123"));
addSpecification(new Specification(
"CM", 27, "F23",
"CM9012345678901234567890123"));
addSpecification(new Specification(
"CV", 25, "F21",
"CV30123456789012345678901"));
addSpecification(new Specification(
"DZ", 24, "F20",
"DZ8612345678901234567890"));
addSpecification(new Specification(
"IR", 26, "F22",
"IR861234568790123456789012"));
addSpecification(new Specification(
"JO", 30, "A04F22",
"JO15AAAA1234567890123456789012"));
addSpecification(new Specification(
"MG", 27, "F23",
"MG1812345678901234567890123"));
addSpecification(new Specification(
"ML", 28, "U01F23",
"ML15A12345678901234567890123"));
addSpecification(new Specification(
"MZ", 25, "F21",
"MZ25123456789012345678901"));
addSpecification(new Specification(
"QA", 29, "U04A21",
"QA30AAAA123456789012345678901"));
addSpecification(new Specification(
"SN", 28, "U01F23",
"SN52A12345678901234567890123"));
addSpecification(new Specification(
"UA", 29, "F25",
"UA511234567890123456789012345"));
addSpecification(new Specification(
"EG", 27, "F23",
"EG1100006001880800100014553"));
addSpecification(new Specification(
"CG", 27, "F23",
"CG5230011000202151234567890"));
addSpecification(new Specification(
"GA", 27, "F23",
"GA2140002000055602673300064"));
} }
/** /**
* Separate CXX and C logic to minimize unexpected or malformed symbols due to * Separate CXX and C logic to minimize unexpected or malformed symbols due to
* language conversions. Also demark all exceptions the std++ can throw since * language conversions. Also catch all exceptions the std++ can throw since
* PostgreSQL is not able to handle them. * PostgreSQL is not able to handle them.
* *
* @param {string} iban * @param {string} iban
* @returns {bool} * @returns {bool}
*/ */
namespace { namespace {
bool account_validate_text(text *iban) { bool account_validate_text(text *iban) {
char *ciban; char *ciban;
bool result; bool result;
Validate val;
ciban = text_to_cstring(iban); ciban = text_to_cstring(iban);
try { try {
result = validator.isValid(ciban); result = val.isValid(std::string(ciban));
} catch (std::exception& e) { } catch (std::exception& e) {
elog(ERROR, "%s", e.what()); elog(ERROR, "%s", e.what());
return false; return false;
@ -381,9 +448,10 @@ bool account_validate_text(text *iban) {
bool account_validate_str(char *iban) { bool account_validate_str(char *iban) {
bool result; bool result;
Validate val;
try { try {
result = validator.isValid(iban); result = val.isValid(std::string(iban));
} catch (std::exception& e) { } catch (std::exception& e) {
elog(ERROR, "%s", e.what()); elog(ERROR, "%s", e.what());
return false; return false;
@ -391,16 +459,10 @@ bool account_validate_str(char *iban) {
return result; return result;
} }
}
} // namespace
extern "C" extern "C"
{ {
PG_MODULE_MAGIC;
typedef char Iban;
/************************************************************************** /**************************************************************************
* Input/Output functions * Input/Output functions
**************************************************************************/ **************************************************************************/
@ -475,5 +537,4 @@ iban_validate(PG_FUNCTION_ARGS) {
PG_RETURN_BOOL(result); PG_RETURN_BOOL(result);
} }
}
} // extern "C"

18
specification.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include <string>
class Specification {
public:
Specification(std::string countryCode, int length, std::string structure, std::string example) :
countryCode(countryCode),
length(length),
structure(structure),
example(example) {
};
Specification(std::string example) : example(example) {};
std::string countryCode;
int length;
std::string structure;
std::string example;
};

14
validate.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include <memory>
#include <map>
#include "specification.h"
class Validate {
public:
Validate();
~Validate();
bool isValid(std::string arg);
void addSpecification(Specification* specPtr);
std::map<std::string, Specification*> specifications;
};