Compare commits

...

10 Commits

Author SHA1 Message Date
jordi fita mas 1df8abb7d2 Add Debian package 2023-06-19 11:29:15 +02:00
Yorick de Wid 0e533afb4d Move some code stubs 2020-10-24 23:54:50 +02:00
Yorick de Wid c93ff49861
Update README.md 2020-10-24 23:47:01 +02:00
Yorick de Wid 42fe111b70
Update README.md 2020-10-24 23:45:54 +02:00
Yorick de Wid 2bc89b66e8
Update README.md 2020-10-24 23:42:58 +02:00
Yorick de Wid e935980bad Code refinements 2020-10-24 23:38:37 +02:00
Yorick de Wid 33b40f623c Rewrite code to be more efficient 2020-10-24 23:24:17 +02:00
Yorick de Wid 7a8dc557b7 Rewrite C++ code 2020-10-24 19:41:28 +02:00
Yorick de Wid 38fe81f14e Ignore LLVM for now 2020-10-24 19:37:13 +02:00
Yorick de Wid c3511292b0
Update c-cpp.yml 2020-10-24 19:21:12 +02:00
12 changed files with 452 additions and 436 deletions

View File

@ -15,11 +15,7 @@ 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: configure - name: Make
# run: ./configure
- name: make
run: make run: make
# - name: make check # - name: Install
# run: make check # run: sudo make install
# - name: make distcheck
# run: make distcheck

View File

@ -1,23 +1,34 @@
# PostgreSQL-IBAN ![C/C++ CI](https://github.com/yorickdewid/PostgreSQL-IBAN/workflows/C/C++%20CI/badge.svg)
# 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 (
id serial NOT NULL, name text,
name character varying(32), account iban
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
-- Invalid bank account -- Dutch IBAN format
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
@ -31,3 +42,19 @@ 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 Normal file
View File

@ -0,0 +1,5 @@
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 Normal file
View File

@ -0,0 +1,22 @@
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 Normal file
View File

@ -0,0 +1,22 @@
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 Normal file
View File

@ -0,0 +1,29 @@
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 Normal file
View File

@ -0,0 +1 @@
13+

6
debian/rules vendored Executable file
View File

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

1
debian/source/format vendored Normal file
View File

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

717
iban.cpp
View File

@ -1,6 +1,7 @@
/* /*
* 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
@ -21,32 +22,49 @@ 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>
#include "specification.h" class Specification {
#include "validate.h" public:
Specification(std::string structure, size_t length)
: structure{ structure }
, m_length{ length }
{
};
inline size_t getLength() const noexcept
{
return m_length;
}
// #define PG_RETURN_IBAN_P(x) PG_RETURN_POINTER(x) std::string structure;
extern "C" private:
{ size_t m_length;
PG_MODULE_MAGIC; };
typedef char Iban; class Validate {
} public:
Validate();
void Validate::addSpecification(Specification* specPtr) { bool isValid(std::string arg);
this->specifications[specPtr->countryCode] = specPtr;
} 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.
@ -54,37 +72,48 @@ void Validate::addSpecification(Specification* specPtr) {
* @param string iban * @param string iban
* @returns {bool} * @returns {bool}
*/ */
bool iso7064Mod97_10(std::string iBan) { static 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
for (const auto& c : iBan) { /* Will contain the letter substitutions */
if (std::isdigit(c)) std::string numberstring;
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;
while (segstart < numberstring.length() - step) { while (segstart < numberstring.length() - step) {
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 bban structure used to configure each iban specification and returns a matching regular expression. * Parse the IBAN 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.
@ -92,14 +121,13 @@ bool iso7064Mod97_10(std::string iBan) {
* @param {string} structure the structure to parse * @param {string} structure the structure to parse
* @returns {regexp} * @returns {regexp}
*/ */
std::regex parseStructure(std::string structure) { static 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, while (std::regex_search(text_iter, structure.cend(), match, std::regex("(.{3})"))) {
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)));
@ -124,320 +152,225 @@ std::regex parseStructure(std::string structure) {
return std::regex(regex.c_str()); return std::regex(regex.c_str());
} }
bool Validate::isValid(std::string arg) { bool Validate::isValid(std::string account) {
Specification* spec = new Specification(arg);
/* Convert uppercase */ /* Convert uppercase */
std::transform(spec->example.begin(), spec->example.end(), std::transform(account.begin(), account.end(), account.begin(), toupper);
spec->example.begin(), toupper);
/* Reject anything too small */
if (account.length() < 3) {
return false;
}
/* Match on country */ /* Match on country */
spec->countryCode = spec->example.substr(0, 2); const std::string& countryCode = account.substr(0, 2);
spec->length = spec->example.length(); const std::string& shortened = account.substr(4);
Specification* specFound = this->specifications[spec->countryCode];
if (!specFound) const std::unique_ptr<Specification>& specFound = specifications[countryCode];
if (!specFound) {
return false; return false;
}
/* Test accountnumber */ /* Test accountnumber */
std::string shortened = spec->example.substr(4, spec->example.length()); return specFound->getLength() == account.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(spec->example); && iso7064Mod97_10(account);
delete spec;
return result;
}
Validate::~Validate() {
for (auto it = specifications.begin(); it != specifications.end(); it++) {
delete it->second;
}
} }
Validate::Validate() { Validate::Validate() {
addSpecification(new Specification( addSpecification(
"AD", 24, "F04F04A12", "AD", 24, "F04F04A12");
"AD1200012030200359100100")); addSpecification(
addSpecification(new Specification( "AE", 23, "F03F16");
"AE", 23, "F03F16", addSpecification(
"AE070331234567890123456")); "AL", 28, "F08A16");
addSpecification(new Specification( addSpecification(
"AL", 28, "F08A16", "AT", 20, "F05F11");
"AL47212110090000000235698741")); addSpecification(
addSpecification(new Specification( "AZ", 28, "U04A20");
"AT", 20, "F05F11", addSpecification(
"AT611904300234573201")); "BA", 20, "F03F03F08F02");
addSpecification(new Specification( addSpecification(
"AZ", 28, "U04A20", "BE", 16, "F03F07F02");
"AZ21NABZ00000000137010001944")); addSpecification(
addSpecification(new Specification( "BG", 22, "U04F04F02A08");
"BA", 20, "F03F03F08F02", addSpecification(
"BA391290079401028494")); "BH", 22, "U04A14");
addSpecification(new Specification( addSpecification(
"BE", 16, "F03F07F02", "BR", 29, "F08F05F10U01A01");
"BE68539007547034")); addSpecification(
addSpecification(new Specification( "CH", 21, "F05A12");
"BG", 22, "U04F04F02A08", addSpecification(
"BG80BNBG96611020345678")); "CR", 21, "F03F14");
addSpecification(new Specification( addSpecification(
"BH", 22, "U04A14", "CY", 28, "F03F05A16");
"BH67BMAG00001299123456")); addSpecification(
addSpecification(new Specification( "CZ", 24, "F04F06F10");
"BR", 29, "F08F05F10U01A01", addSpecification(
"BR9700360305000010009795493P1")); "DE", 22, "F08F10");
addSpecification(new Specification( addSpecification(
"CH", 21, "F05A12", "DK", 18, "F04F09F01");
"CH9300762011623852957")); addSpecification(
addSpecification(new Specification( "DO", 28, "U04F20");
"CR", 21, "F03F14", addSpecification(
"CR0515202001026284066")); "EE", 20, "F02F02F11F01");
addSpecification(new Specification( addSpecification(
"CY", 28, "F03F05A16", "ES", 24, "F04F04F01F01F10");
"CY17002001280000001200527600")); addSpecification(
addSpecification(new Specification( "FI", 18, "F06F07F01");
"CZ", 24, "F04F06F10", addSpecification(
"CZ6508000000192000145399")); "FO", 18, "F04F09F01");
addSpecification(new Specification( addSpecification(
"DE", 22, "F08F10", "FR", 27, "F05F05A11F02");
"DE89370400440532013000")); addSpecification(
addSpecification(new Specification( "GB", 22, "U04F06F08");
"DK", 18, "F04F09F01", addSpecification(
"DK5000400440116243")); "GE", 22, "U02F16");
addSpecification(new Specification( addSpecification(
"DO", 28, "U04F20", "GI", 23, "U04A15");
"DO28BAGR00000001212453611324")); addSpecification(
addSpecification(new Specification( "GL", 18, "F04F09F01");
"EE", 20, "F02F02F11F01", addSpecification(
"EE382200221020145685")); "GR", 27, "F03F04A16");
addSpecification(new Specification( addSpecification(
"ES", 24, "F04F04F01F01F10", "GT", 28, "A04A20");
"ES9121000418450200051332")); addSpecification(
addSpecification(new Specification( "HR", 21, "F07F10");
"FI", 18, "F06F07F01", addSpecification(
"FI2112345600000785")); "HU", 28, "F03F04F01F15F01");
addSpecification(new Specification( addSpecification(
"FO", 18, "F04F09F01", "IE", 22, "U04F06F08");
"FO6264600001631634")); addSpecification(
addSpecification(new Specification( "IL", 23, "F03F03F13");
"FR", 27, "F05F05A11F02", addSpecification(
"FR1420041010050500013M02606")); "IS", 26, "F04F02F06F10");
addSpecification(new Specification( addSpecification(
"GB", 22, "U04F06F08", "IT", 27, "U01F05F05A12");
"GB29NWBK60161331926819")); addSpecification(
addSpecification(new Specification( "KW", 30, "U04A22");
"GE", 22, "U02F16", addSpecification(
"GE29NB0000000101904917")); "KZ", 20, "F03A13");
addSpecification(new Specification( addSpecification(
"GI", 23, "U04A15", "LB", 28, "F04A20");
"GI75NWBK000000007099453")); addSpecification(
addSpecification(new Specification( "LC", 32, "U04F24");
"GL", 18, "F04F09F01", addSpecification(
"GL8964710001000206")); "LI", 21, "F05A12");
addSpecification(new Specification( addSpecification(
"GR", 27, "F03F04A16", "LT", 20, "F05F11");
"GR1601101250000000012300695")); addSpecification(
addSpecification(new Specification( "LU", 20, "F03A13");
"GT", 28, "A04A20", addSpecification(
"GT82TRAJ01020000001210029690")); "LV", 21, "U04A13");
addSpecification(new Specification( addSpecification(
"HR", 21, "F07F10", "MC", 27, "F05F05A11F02");
"HR1210010051863000160")); addSpecification(
addSpecification(new Specification( "MD", 24, "U02A18");
"HU", 28, "F03F04F01F15F01", addSpecification(
"HU42117730161111101800000000")); "ME", 22, "F03F13F02");
addSpecification(new Specification( addSpecification(
"IE", 22, "U04F06F08", "MK", 19, "F03A10F02");
"IE29AIBK93115212345678")); addSpecification(
addSpecification(new Specification( "MR", 27, "F05F05F11F02");
"IL", 23, "F03F03F13", addSpecification(
"IL620108000000099999999")); "MT", 31, "U04F05A18");
addSpecification(new Specification( addSpecification(
"IS", 26, "F04F02F06F10", "MU", 30, "U04F02F02F12F03U03");
"IS140159260076545510730339")); addSpecification(
addSpecification(new Specification( "NL", 18, "U04F10");
"IT", 27, "U01F05F05A12", addSpecification(
"IT60X0542811101000000123456")); "NO", 15, "F04F06F01");
addSpecification(new Specification( addSpecification(
"KW", 30, "U04A22", "PK", 24, "U04A16");
"KW81CBKU0000000000001234560101")); addSpecification(
addSpecification(new Specification( "PL", 28, "F08F16");
"KZ", 20, "F03A13", addSpecification(
"KZ86125KZT5004100100")); "PS", 29, "U04A21");
addSpecification(new Specification( addSpecification(
"LB", 28, "F04A20", "PT", 25, "F04F04F11F02");
"LB62099900000001001901229114")); addSpecification(
addSpecification(new Specification( "RO", 24, "U04A16");
"LC", 32, "U04F24", addSpecification(
"LC07HEMM000100010012001200013015")); "RS", 22, "F03F13F02");
addSpecification(new Specification( addSpecification(
"LI", 21, "F05A12", "SA", 24, "F02A18");
"LI21088100002324013AA")); addSpecification(
addSpecification(new Specification( "SE", 24, "F03F16F01");
"LT", 20, "F05F11", addSpecification(
"LT121000011101001000")); "SI", 19, "F05F08F02");
addSpecification(new Specification( addSpecification(
"LU", 20, "F03A13", "SK", 24, "F04F06F10");
"LU280019400644750000")); addSpecification(
addSpecification(new Specification( "SM", 27, "U01F05F05A12");
"LV", 21, "U04A13", addSpecification(
"LV80BANK0000435195001")); "ST", 25, "F08F11F02");
addSpecification(new Specification( addSpecification(
"MC", 27, "F05F05A11F02", "TL", 23, "F03F14F02");
"MC5811222000010123456789030")); addSpecification(
addSpecification(new Specification( "TN", 24, "F02F03F13F02");
"MD", 24, "U02A18", addSpecification(
"MD24AG000225100013104168")); "TR", 26, "F05F01A16");
addSpecification(new Specification( addSpecification(
"ME", 22, "F03F13F02", "VG", 24, "U04F16");
"ME25505000012345678951")); addSpecification(
addSpecification(new Specification( "XK", 20, "F04F10F02");
"MK", 19, "F03A10F02", addSpecification(
"MK07250120000058984")); "AO", 25, "F21");
addSpecification(new Specification( addSpecification(
"MR", 27, "F05F05F11F02", "BF", 27, "F23");
"MR1300020001010000123456753")); addSpecification(
addSpecification(new Specification( "BI", 16, "F12");
"MT", 31, "U04F05A18", addSpecification(
"MT84MALT011000012345MTLCAST001S")); "BJ", 28, "F24");
addSpecification(new Specification( addSpecification(
"MU", 30, "U04F02F02F12F03U03", "CI", 28, "U01F23");
"MU17BOMM0101101030300200000MUR")); addSpecification(
addSpecification(new Specification( "CM", 27, "F23");
"NL", 18, "U04F10", addSpecification(
"NL91ABNA0417164300")); "CV", 25, "F21");
addSpecification(new Specification( addSpecification(
"NO", 15, "F04F06F01", "DZ", 24, "F20");
"NO9386011117947")); addSpecification(
addSpecification(new Specification( "IR", 26, "F22");
"PK", 24, "U04A16", addSpecification(
"PK36SCBL0000001123456702")); "JO", 30, "A04F22");
addSpecification(new Specification( addSpecification(
"PL", 28, "F08F16", "MG", 27, "F23");
"PL61109010140000071219812874")); addSpecification(
addSpecification(new Specification( "ML", 28, "U01F23");
"PS", 29, "U04A21", addSpecification(
"PS92PALS000000000400123456702")); "MZ", 25, "F21");
addSpecification(new Specification( addSpecification(
"PT", 25, "F04F04F11F02", "QA", 29, "U04A21");
"PT50000201231234567890154")); addSpecification(
addSpecification(new Specification( "SN", 28, "U01F23");
"RO", 24, "U04A16", addSpecification(
"RO49AAAA1B31007593840000")); "UA", 29, "F25");
addSpecification(new Specification( addSpecification(
"RS", 22, "F03F13F02", "EG", 27, "F23");
"RS35260005601001611379")); addSpecification(
addSpecification(new Specification( "CG", 27, "F23");
"SA", 24, "F02A18", addSpecification(
"SA0380000000608010167519")); "GA", 27, "F23");
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 catch all exceptions the std++ can throw since * language conversions. Also demark 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 = val.isValid(std::string(ciban)); result = validator.isValid(ciban);
} catch (std::exception& e) { } catch (std::exception& e) {
elog(ERROR, "%s", e.what()); elog(ERROR, "%s", e.what());
return false; return false;
@ -448,10 +381,9 @@ 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 = val.isValid(std::string(iban)); result = validator.isValid(iban);
} catch (std::exception& e) { } catch (std::exception& e) {
elog(ERROR, "%s", e.what()); elog(ERROR, "%s", e.what());
return false; return false;
@ -459,82 +391,89 @@ bool account_validate_str(char *iban) {
return result; return result;
} }
}
} // namespace
extern "C" extern "C"
{ {
/**************************************************************************
* Input/Output functions
**************************************************************************/
PG_FUNCTION_INFO_V1(ibanin); PG_MODULE_MAGIC;
Datum typedef char Iban;
ibanin(PG_FUNCTION_ARGS) {
char *inputText = PG_GETARG_CSTRING(0);
if (!account_validate_str(inputText)) /**************************************************************************
ereport(ERROR, * Input/Output functions
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), **************************************************************************/
errmsg("invalid iban format for value: \"%s\"",
inputText)));
PG_RETURN_TEXT_P(cstring_to_text(inputText)); PG_FUNCTION_INFO_V1(ibanin);
}
/* Convert type output */ Datum
ibanin(PG_FUNCTION_ARGS) {
char *inputText = PG_GETARG_CSTRING(0);
PG_FUNCTION_INFO_V1(ibanout); if (!account_validate_str(inputText))
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid iban format for value: \"%s\"",
inputText)));
Datum PG_RETURN_TEXT_P(cstring_to_text(inputText));
ibanout(PG_FUNCTION_ARGS) {
Iban *iban = (Iban *) PG_GETARG_DATUM(0);
PG_RETURN_CSTRING(TextDatumGetCString(iban));
}
/**************************************************************************
* Binary Input/Output functions
**************************************************************************/
PG_FUNCTION_INFO_V1(ibanrecv);
Datum
ibanrecv(PG_FUNCTION_ARGS) {
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
text *result;
Iban *str;
int nbytes;
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
result = cstring_to_text_with_len(str, nbytes);
pfree(str);
PG_RETURN_TEXT_P(result);
}
PG_FUNCTION_INFO_V1(ibansend);
Datum
ibansend(PG_FUNCTION_ARGS) {
text *t = PG_GETARG_TEXT_PP(0);
StringInfoData buf;
pq_begintypsend(&buf);
pq_sendtext(&buf, VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t));
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
/* Manually verify a text */
PG_FUNCTION_INFO_V1(iban_validate);
Datum
iban_validate(PG_FUNCTION_ARGS) {
text *iban = PG_GETARG_TEXT_P(0);
bool result = account_validate_text(iban);
PG_RETURN_BOOL(result);
}
} }
/* Convert type output */
PG_FUNCTION_INFO_V1(ibanout);
Datum
ibanout(PG_FUNCTION_ARGS) {
Iban *iban = (Iban *) PG_GETARG_DATUM(0);
PG_RETURN_CSTRING(TextDatumGetCString(iban));
}
/**************************************************************************
* Binary Input/Output functions
**************************************************************************/
PG_FUNCTION_INFO_V1(ibanrecv);
Datum
ibanrecv(PG_FUNCTION_ARGS) {
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
text *result;
Iban *str;
int nbytes;
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
result = cstring_to_text_with_len(str, nbytes);
pfree(str);
PG_RETURN_TEXT_P(result);
}
PG_FUNCTION_INFO_V1(ibansend);
Datum
ibansend(PG_FUNCTION_ARGS) {
text *t = PG_GETARG_TEXT_PP(0);
StringInfoData buf;
pq_begintypsend(&buf);
pq_sendtext(&buf, VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t));
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
/* Manually verify a text */
PG_FUNCTION_INFO_V1(iban_validate);
Datum
iban_validate(PG_FUNCTION_ARGS) {
text *iban = PG_GETARG_TEXT_P(0);
bool result = account_validate_text(iban);
PG_RETURN_BOOL(result);
}
} // extern "C"

View File

@ -1,18 +0,0 @@
#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;
};

View File

@ -1,14 +0,0 @@
#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;
};