소스 검색

Fix debug for php 8.1

Laurent Destailleur 2 년 전
부모
커밋
e6e4017047

+ 7 - 6
htdocs/compta/bank/class/account.class.php

@@ -1707,19 +1707,20 @@ class Account extends CommonObject
 	 */
 	public function initAsSpecimen()
 	{
+		// Example of IBAN FR7630001007941234567890185
 		$this->specimen        = 1;
 		$this->ref             = 'MBA';
 		$this->label           = 'My Big Company Bank account';
 		$this->bank            = 'MyBank';
 		$this->courant         = Account::TYPE_CURRENT;
 		$this->clos            = Account::STATUS_OPEN;
-		$this->code_banque     = '123';
-		$this->code_guichet    = '456';
-		$this->number          = 'ABC12345';
-		$this->cle_rib         = '50';
+		$this->code_banque     = '30001';
+		$this->code_guichet    = '00794';
+		$this->number          = '12345678901';
+		$this->cle_rib         = '85';
 		$this->bic             = 'AA12';
-		$this->iban            = 'FR999999999';
-		$this->domiciliation   = 'My bank address';
+		$this->iban            = 'FR7630001007941234567890185';
+		$this->domiciliation   = 'Banque de France';
 		$this->proprio         = 'Owner';
 		$this->owner_address   = 'Owner address';
 		$this->country_id      = 1;

+ 3 - 2
htdocs/core/lib/bank.lib.php

@@ -27,6 +27,7 @@
  * \brief      Ensemble de fonctions de base pour le module banque
  */
 
+
 /**
  * Prepare array with list of tabs
  *
@@ -273,13 +274,13 @@ function checkSwiftForAccount($account)
  *      @param  Account     $account    A bank account
  *      @return boolean                 True if informations are valid, false otherwise
  */
-function checkIbanForAccount($account)
+function checkIbanForAccount(Account $account)
 {
 	require_once DOL_DOCUMENT_ROOT.'/includes/php-iban/oophp-iban.php';
 
 	$ibantocheck = ($account->iban ? $account->iban : $account->iban_prefix);		// iban or iban_prefix for backward compatibility
 
-	$iban = new IBAN($ibantocheck);
+	$iban = new PHP_IBAN\IBAN($ibantocheck);
 	$check = $iban->Verify();
 
 	if ($check) {

+ 21 - 0
htdocs/includes/php-iban/.travis.yml

@@ -0,0 +1,21 @@
+matrix:
+  include:
+    - php: 5.3
+      dist: precise
+language: php
+dist: trusty
+php:
+ - '5.4'
+ - '5.5'
+ - '5.6'
+ - '7.0'
+ - '7.4'
+ - '8.0'
+ - '8.1'
+ - hhvm-3.3
+ - hhvm-3.6
+ - hhvm-3.9
+ - hhvm-3.12
+ - hhvm-3.15
+ - hhvm-3.18
+script: php utils/test.php && php utils/ootest.php && php utils/other-tests.php

+ 1467 - 0
htdocs/includes/php-iban/README.md

@@ -0,0 +1,1467 @@
+php-iban
+========
+
+`php-iban` is a library for parsing, validating and generating IBAN (and IIBAN) bank account information in PHP.
+
+[![Build Status](https://travis-ci.org/globalcitizen/php-iban.png)](https://travis-ci.org/globalcitizen/php-iban)
+[![Latest Stable Version](https://poser.pugx.org/globalcitizen/php-iban/v/stable)](https://packagist.org/packages/globalcitizen/php-iban) 
+[![License](https://poser.pugx.org/globalcitizen/php-iban/license)](https://packagist.org/packages/globalcitizen/php-iban)
+
+All parts of an IBAN can be retrieved, including country code, checksum, BBAN, financial institution or bank code, account number, and where a fixed-length national system is in use, also branch/sort code. Legacy national checksums may also be retrieved, validated and correctly set, where available, whether they apply to the account number portion, bank and branch identifiers, part or all of the above. IBAN country codes can be converted in to ISO3166-1 alpha-2 and IANA formats, the parent IBAN country acting as registrar for dependent territories may be queried, the official national currency (ISO4217 alpha code format), central bank name and central bank URL may also be queried to ease integration. IBANs may be converted between human and machine representation. IBANs may be obfuscated for presentation to humans in special circumstances such as relative identification. A database of example/test IBANs from different countries is included. Finally, highly accurate suggestions for originally intended input can be made when an incorrect IBAN is detected and is due to mistranscription error.
+
+Tested on PHP versions: ![PHP 5.2](https://img.shields.io/badge/version-PHP%205.2%2B-lightgrey.svg) ![PHP 5.3](https://img.shields.io/badge/version-PHP%205.3%2B-lightgrey.svg) ![PHP 5.4](https://img.shields.io/badge/version-PHP%205.4%2B-lightgrey.svg) ![PHP 5.5](https://img.shields.io/badge/version-PHP%205.5%2B-lightgrey.svg) ![PHP 5.6](https://img.shields.io/badge/version-PHP%205.6%2B-lightgrey.svg) ![PHP 7.0](https://img.shields.io/badge/version-PHP%207.0%2B-lightgrey.svg) ![PHP 7.4](https://img.shields.io/badge/version-PHP%207.4%2B-lightgrey.svg)
+
+Test on HHVM versions: ![HHVM 3.3](https://img.shields.io/badge/version-HHVM%203.3%2B-lightgrey.svg) ![HHVM 3.6](https://img.shields.io/badge/version-HHVM%203.6%2B-lightgrey.svg) ![HHVM 3.9](https://img.shields.io/badge/version-HHVM%203.9%2B-lightgrey.svg) ![HHVM 3.12](https://img.shields.io/badge/version-HHVM%203.12%2B-lightgrey.svg) ![HHVM 3.15](https://img.shields.io/badge/version-HHVM%203.15%2B-lightgrey.svg) ![HHVM 3.18](https://img.shields.io/badge/version-HHVM%203.18%2B-lightgrey.svg)
+
+The parser was built using regular expressions to adapt the contents of the _official_ IBAN registry available from SWIFT then manually modified for special cases such as [errors and omissions in SWIFT's official specifications](https://raw.githubusercontent.com/globalcitizen/php-iban/master/docs/COMEDY-OF-ERRORS).
+
+Various deficiencies in the initial adaptation have since been rectified, and the current version should be a fairly correct and reliable implementation.
+
+Where appropriate, __European Committee for Banking Standards__ (ECBS) recommendations have also been incorporated.
+
+Please bear in mind that because the specification changes frequently, it may not be 100% up to date if a new version has been recently released - I do my best though. We are currently thought to be up to date with [the January 2020 release, ie. PDF release #86](https://www.swift.com/standards/data-standards/iban).
+
+Licensed under LGPL, it is free to use in commercial settings.
+
+
+Countries Supported
+-------------------
+
+The following 116 official and *unofficial* IBAN countries are supported.
+
+* Albania (AL)
+* *Algeria* (DZ)
+* Andorra (AD)
+* *Angola* (AO)
+* Austria (AT)
+* Azerbaijan (AZ)
+* Bahrain (BH)
+* Belarus (BY)
+* Belgium (BE)
+* *Benin* (BJ)
+* Bosnia and Herzegovina (BA)
+* Brazil (BR)
+* British Virgin Islands (VG)
+* Bulgaria (BG)
+* *Burkina Faso* (BF)
+* *Burundi* (BI)
+* *Cameroon* (CM)
+* *Central African Republic* (CF)
+* *Chad* (TD)
+* *Cape Verde* (CV)
+* *Comoros* (KM)
+* *Congo* (CG)
+* Costa Rica (CR)
+* *Côte d'Ivoire* (CI)
+* Croatia (HR)
+* Cyprus (CY)
+* Czech Republic (CZ)
+* Denmark (DK)
+ * Faroe Islands (FO)
+ * Greenland (GL)
+* *Djibouti* (DJ)
+* Dominican Republic (DO)
+* East Timor (TL)
+* *Egypt* (EG)
+* El Salvador (SV)
+* *Equitorial Guinea* (GQ)
+* Estonia (EE)
+* Finland (FI)
+ * Åland Islands (AX)
+* France (FR)
+ * French Guiana (GF)
+ * French Polynesia (PF)
+ * French Southern Territories (TF)
+ * Guadelope (GP)
+ * Martinique (MQ)
+ * Mayotte (YT)
+ * New Caledonia (NC)
+ * Réunion (RE)
+ * Saint Barhélemy (BL)
+ * Saint Martin (French Part) (MF)
+ * Saint-Pierre and Miquelon (PM)
+ * Wallis and Futuna (WF)
+* *Gabon* (GA)
+* Georgia (GE)
+* Germany (DE)
+* Gibraltar (GI)
+* Greece (GR)
+* Guatemala (GT)
+* *Guinea-Bissau* (GW)
+* *Honduras* (HN)
+* Hungary (HU)
+* Iceland (IS)
+* *IIBAN (Internet)* (AA)
+* *Iran* (IR)
+* Iraq (IQ)
+* Ireland (IE)
+* Israel (IL)
+* Italy (IT)
+* Jordan (JO)
+* Kazakhstan (KZ)
+* Kosovo (XK)
+* Kuwait (KW)
+* Latvia (LV)
+* Lebanon (LB)
+* Liechtenstein (LI)
+* Lithuania (LT)
+* Luxembourg (LU)
+* Macedonia (MK)
+* *Madagascar* (MG)
+* *Mali* (ML)
+* Malta (MT)
+* Mauritania (MR)
+* Mauritius (MU)
+* Moldova (MD)
+* Monaco (MC)
+* Montenegro (ME)
+* *Morocco* (MA)
+* *Mozambique* (MZ)
+* Netherlands (NL)
+* *Nicaragua* (NI)
+* *Niger* (NE)
+* Norway (NO)
+* Pakistan (PK)
+* Palestine (PS)
+* Poland (PL)
+* Portugal (PT)
+* Qatar (QA)
+* Romania (RO)
+* Saint Lucia (LC)
+* San Marino (SM)
+* São Tomé and Príncipe (ST)
+* Saudi Arabia (SA)
+* *Senegal* (SN)
+* Serbia (RS)
+* Seychelles (SC)
+* Slovakia (SK)
+* Slovenia (SI)
+* Spain (ES)
+* Sweden (SE)
+* Switzerland (CH)
+* *Togo* (TG)
+* Tunisia (TN)
+* Turkey (TR)
+* *Ukraine* (UA)
+* United Arab Emirates (AE)
+* United Kingdom (GB)
+
+
+Installation via composer
+-------------------------
+
+If you use [composer](https://getcomposer.org/) you can simply run `composer require globalcitizen/php-iban` to get going. Reportedly [![Daily Downloads](https://poser.pugx.org/globalcitizen/php-iban/d/daily)](https://packagist.org/packages/globalcitizen/php-iban) (and [![Monthly Downloads](https://poser.pugx.org/globalcitizen/php-iban/d/monthly)](https://packagist.org/packages/globalcitizen/php-iban)) were done via composer.
+
+(If you don't yet have `composer` and wish to install it in an insecure fashion (not recommended, but convenient) you can run `curl -sS https://getcomposer.org/installer | php` or `wget -O- https://getcomposer.org/installer | php`)
+
+Then just add the following to your `composer.json` file:
+
+```js
+// composer.json
+{
+    "require": {
+        "globalcitizen/php-iban": "4.1.0"
+    }
+}
+```
+
+Then, you can install the new dependencies by running `composer`'s update command from the directory where your `composer.json` file is located:
+
+```sh
+# install
+$ php composer.phar install
+# update
+$ php composer.phar update globalcitizen/php-iban
+
+# or you can simply execute composer command if you set it to
+# your PATH environment variable
+$ composer install
+$ composer update globalcitizen/php-iban
+```
+
+You can [see this library on Packagist](https://packagist.org/packages/globalcitizen/php-iban).
+
+
+Installation via git
+--------------------
+
+For a regular install, use the `git clone` command:
+
+```sh
+# HTTP
+$ git clone https://github.com/globalcitizen/php-iban.git
+# SSH
+$ git clone git@github.com:globalcitizen/php-iban.git
+```
+
+
+Installation via git submodule
+------------------------------
+
+Alternatively, to embed the `php-iban` library in your own `git`-managed repository at a specific revision number, such that it is possible to update the version in a predictable way while maintaining a larger system that depends upon its functionality:
+```sh
+# enter your project's git repo
+$ cd my-existing-project-with-a-git-repo/
+# select an appropriate place to create the php-iban subdir
+$ cd lib/
+# add php-iban as a submodule
+$ git submodule add https://github.com/globalcitizen/php-iban.git
+# commit new submodule
+$ git commit -m 'Add php-iban submodule'
+```
+
+Then, when checking out `git` projects with submodules for the first time, normally you need to make a couple of extra steps:
+```sh
+# check out your project as normal
+$ git clone git@your-server.com:your/project.git
+# initialize submodules
+$ git submodule init
+# update submodules
+$ git submodule update
+```
+
+To skip these steps, add the `--recursive` argument to `git clone` when checking out:
+```sh
+# check out your project, initialize and update all submodules
+$ git clone --recursive git@your-server.com:your/project.git
+```
+
+If you later wish to your project to use a newer version of `php-iban`, run:
+```sh
+# fetch changes
+$ git submodule update --remote php-iban
+# commit
+$ git commit -m 'Update php-iban submodule'
+```
+
+
+Manual installation
+-------------------
+
+1. Fetch the latest release from [our github releases page](https://github.com/globalcitizen/php-iban/releases) in either `zip` or `tar.gz` format.
+2. Extract the library using your favourite archive utility, for example `unzip filename.zip` on Unix-like platforms.
+3. Write your code to depend on the library based upon its relative location to your source code. For example if you wish to include `php-iban` from the parent directory's subdirectory `libraries/php-iban` you could use the following [require_once()](http://php.net/manual/en/function.require-once.php) statement:
+```php
+<?php
+require_once(dirname(__FILE__) . '/../libraries/php-iban/php-iban.php');
+# ... your code utilizing php-iban
+?>
+```
+
+
+Comparison of PHP IBAN libraries
+--------------------------------
+
+The following table compares __php-iban__ to other PHP projects offering IBAN-related functionality, on the basis of general project information and the programming paradigms supported.
+
+| Project                                                    | Lic. | Proc | OO  | Began  | Latest | Star | Watch | Fork | Installs | Home culture | Deps    |
+| ---------------------------------------------------------- | ---- | ---- | --- | ------ | ------ | ---- | ----- | ---- | -------- | ------------ | ------- |
+| __php-iban__                                               | LGPL | ✔    | ✔   | 2009   | 4.1.0  | 344  | 26    | 76   | ~2M*    | Global*      | *none*  |
+| [Iban](https://github.com/jschaedl/Iban)                   | MIT  | ✘    | ✔   | 2013   | 1.3.0  | 50   | 9     | 19   | 178.39k  | German       | lots    |
+| [IsoCodes](https://github.com/ronanguilloux/IsoCodes)      | GPL3 | ✘    | ✔   | 2012   | 2.1.1  | 466  | 22    | 54   | 145k     | French       | lots    |
+| [SepaUtil's](https://github.com/AbcAeffchen/SepaUtilities) | GPL3 | ✘    | ✔   | 2014   | 1.2.3  | 8    | 4     | 3    | 25k      | German       | phpunit |
+| [Symfony](https://github.com/symfony/symfony)              | MIT  | ✘    | ✔   | 2013   | 3.3.6  | 15k  | 1214  | 5.6k | 23M+     | French       | lots    |
+
+Notes:
+ * Original download records for __php-iban__ releases were hosted on Google Code and are now lost. Prior to establishing a release process on Github, we just expected that people would download the code... so we're really not sure how many installs exist, but this is a fair guess (~11k + composer installs + a little bit now and then).
+ * __php-iban__ also powers:
+    * [adm-gravity-iban](https://github.com/InternativeNL/adm-gravity-iban)
+    * [Azzana consulting's XML Solver for ISO20022](http://www.azzana-consulting.com/xmlsolver/)
+    * [basepa Payment Gateway for WooCommerce](https://github.com/besepa/woocommerce-besepa)
+    * [org.civicoop.ibanaccounts extension](https://github.com/CiviCooP/org.civicoop.ibanaccounts) for [CiviCoop](http://www.civicoop.org/)
+    * [commerce_sepa](https://github.com/StephanGeorg/commerce_sepa)
+    * [contao-haste_plus](https://github.com/heimrichhannot/contao-haste_plus)
+    * [Dolibarr ERP &amp; CRM](http://www.dolibarr.org/) ([website](https://github.com/Dolibarr/dolibarr/tree/develop/htdocs/includes/php-iban))
+    * [fieldwork: Web forms for cool people](https://github.com/jmversteeg/fieldwork)
+    * [IBAN Validator](https://www.drupal.org/project/iban_validator) for Drupal
+    * [identity](https://github.com/mpijierro/identity) component for Laravel to check Spanish IDs
+    * [lib-bankaccount](https://github.com/majestixx/lib-bankaccount) (conversion to/from legacy German account format)
+    * [PHP SEPA XML](http://www.phpclasses.org/package/8179-PHP-Generate-XML-for-the-Single-Euro-Payments-Area.html) class ([github](https://github.com/dmitrirussu/php-sepa-xml-generator))
+    * [Project60 SEPA direct debit](https://github.com/Project60/org.project60.sepa)
+    * [SEPA Payment Plugin](https://github.com/subs-guru/sepa-payment-plugin) for [SubsGuru](http://subs.guru/)
+    * [Silverstripe CMS module](https://github.com/denkfabrik-neueMedien/silverstripe-siteinfo)
+    * [statement](https://github.com/hiwye/statement) 
+    * [WooCommerce Germanized](http://hookr.io/plugins/woocommerce-germanized/)
+    * [WooCommerce SEPA Payment Gateway](https://codecanyon.net/item/woocommerce-sepa-payment-gateway/7963419)
+ * php-iban's author is an Australian born, Australia/New Zealand/German citizen based in mainland China, who has formerly also worked and banked in the US, UK, and many Asian countries.
+ * The IsoCodes and SepaUtil's projects cover standards other than IBAN so their popularity should be considered in this light. (In essence, there is really only one directly competing library, Iban)
+
+Now let's take a look at features.
+
+|                                                               | +   | ISO | IANA | SEPA | ₶   | UO  | MT  | NC  | ₴   | CB  | H?  | Registry                                                               |
+| ------------------------------------------------------------- | --- | --- | ---- | ---- | --- | --- | --- | --- | --- | --- | --- | ---------------------------------------------------------------------- |
+| __php-iban__                                                  | ✔   | ✔   |  ✔   | ✔    | ✔   | ✔   | ✔   | ✔   | ✔   | ✔   | ✔   | 116: [full, error-corrected CSV](https://github.com/globalcitizen/php-iban/blob/master/registry.txt) with [open-source toolchain](https://github.com/globalcitizen/php-iban/blob/master/utils/convert-registry.php) and [documentation](https://github.com/globalcitizen/php-iban/blob/master/docs/COMEDY-OF-ERRORS) |
+| [Iban](https://github.com/jschaedl/Iban)                      | ✔*  | ✘   |  ✘   | ✘    | ✘   | ✘   | ✘   | ✘   | ✘   | ✘   | ✘   | 54: [partial, hardcoded, dubious origin](https://github.com/jschaedl/Iban/blob/master/library/IBAN/Core/Constants.php#L44)   |
+| [IsoCodes](https://github.com/ronanguilloux/IsoCodes)         | ✘   | ✘   |  ✘   | ✘    | ✘   | ✘   | ✘   | ✘   | ✘   | ✘   | ✘   | 66: [partial, hardcoded, dubious origin](https://github.com/ronanguilloux/IsoCodes/blob/master/src/IsoCodes/Iban.php#L25)    |
+| [SepaUtil's](https://github.com/AbcAeffchen/SepaUtilities)    | ✘   | ✘   |  ✘   | ✘    | ✘   | ✘   | ✘   | ✘   | ✘   | ✘   | ✘   | 89: [partial, hardcoded, dubious origin](https://github.com/AbcAeffchen/SepaUtilities/blob/master/src/SepaUtilities.php#L89) |
+| [Symfony](https://github.com/symfony/symfony)                 | ✘   | ✘   |  ✘   | ✘    | ✘   | ✘   | ✘   | ✘   | ✘   | ✘   | ✘   | 95: [partial, hardcoded](https://github.com/symfony/symfony/blob/09f92ba516b8840f2ee2dc630b75cbccfca5976b/src/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php), [dubious origin](https://github.com/symfony/symfony/blob/a4f3baae3758b0e72005353f624101f089e4302b/src/Symfony/Component/Validator/Constraints/IbanValidator.php)
+
+Note:
+ * __+__ refers to the capacity to create checksum-accurate potential IBANs programatically. It is the author's opinion that generation features without IIBAN support (ie. authority) are of dubious use, except in one-off migrations. (See also NC, below)
+ * __ISO__ refers to the capacity to convert between IBAN country codes and ISO3166-1 alpha-2 country codes
+ * __IANA__ refers to the capacity to convert between IBAN country codes and IANA country codes (eg. 'GB' to '.uk' and vice versa)
+ * __SEPA__ refers to the ability to check whether a particular IBAN country is a member of the Single Euro Payments Area (SEPA)
+ * __₶__ describes support for IIBAN, the open [proposal](http://www.ifex-project.org/) for decentralized financial endpoint generation by private parties, such as crypto-currency exchanges, whilst maintaining compatibility with the emerging IBAN system. This system has been adopted by major cryptocurrency exchanges such as [Kraken](https://www.kraken.com/).
+ * __UO__ refers to support for unofficial countries whose IBAN formats have been [published as in informal use](http://www.nordea.com/en/our-services/cashmanagement/iban-validator-and-information/iban-countries/index.html) by major financial institutions, but are not official SWIFT-published registry entries.
+ * __MT__ refers to mistranscription support: the capacity to automatically detect what the user probably meant when they make a transcription error on IBANs, such as those manually written or printed in confusing fonts, for instance writing 'L' instead of 'I' or '1', or vice versa.
+ * __NC__ refers to national checksum support: the capacity to verify and, where appropriate, set and extract the national checksum portion of a BBAN, for countries that offered pre-IBAN national checksum algorithms.
+ * __₴__ refers to support for querying the official national currency's ISO4217 code for an IBAN country
+ * __CB__ refers to support for querying the name and URL of the central bank of an IBAN country
+ * __H?__ refers to support for input and output for the human, space-laden or presentation variant of an IBAN, ie. `IBAN XXXX XXXX XXXX XXXX` instead of `XXXXXXXXXXXXXXXX` - a lot more reasonable.
+
+In short, while composer users have apparently lept on rival libraries (particularly Iban), probably due to the time it took us to integrate a composer file, those libraries are often either full-fledged web frameworks or burdensome in dependencies, less mature, fail to hat-tip to the free software foundation, do not support the procedural programming paradigm (for when AbstractProductClassMakerFactories just won't cut it), use data from dubious sources, tend to use licenses that are incompatible with certain commercial uses, and are frankly short on features.
+
+So, fearless user ... __choose php-iban__: the ethical, functional, forward-looking, low-hassle library of choice for IBAN and IIBAN processing. __Choose to win!__ ;)
+
+
+Your Help Wanted
+----------------
+
+ * If you know the URL of __national IBAN, BBAN or national checksum documentation__ from official sources, please let us know at [issue #39](https://github.com/globalcitizen/php-iban/issues/39) and [issue #41](https://github.com/globalcitizen/php-iban/issues/41).
+  * __Faroe Islands__ (FO) banks do not respond, neither does the Danish National Bank who referred me to them.
+  * __Luxembourg__ (LU) does not seem to conform to any single checksum system. While some IBAN do validate with reasonably common systems, others don't or use others. The suggestion that Luxembourg has a national checksum system may in fact be incorrect. We need some clarification here, hopefully someone can dig up an official statement.
+  * __Mauritania__ (MR) has a dual character checksum system but our example IBAN does not match MOD97-10 which would be the expected system. Previously the IBAN here was always fixed to '13' checksum digits, however as of registry v66 it is now dynamic, which suggests a changed or at least now nationally relaxed checksum system.
+
+ * If you are willing to spend some time searching, we could do with some more test IBANs for most countries, especially smaller ones...
+
+News: July 2021
+---------------
+
+__[Version 4.1.0](https://github.com/globalcitizen/php-iban/releases/tag/v4.1.0)__ has been released.
+ * New feature to check for EU memberships - thanks to [@julianpollmann](https://github.com/julianpollman)
+
+News: August 2020
+-----------------
+__[Version 4.0.0](https://github.com/globalcitizen/php-iban/releases/tag/v4.0.0)__ has been released.
+ * Major version upgrade to certainly fix missing dot in prior release version string, thus avoiding composer hassles. (See [#108](https://github.com/globalcitizen/php-iban/issues/108)). I am really beginning to hate composer.
+
+__[Version 3.0.3](https://github.com/globalcitizen/php-iban/releases/tag/v3.0.3)__ has been released.
+ * Official support for php-7.4
+
+__[Version 3.0.2](https://github.com/globalcitizen/php-iban/releases/tag/v3.0.2)__ has been released.
+ * BBAN length fixes for Bahrain and Quatar (thanks to @jledrogo)
+
+News: July 2020
+---------------
+
+__[Version 3.0.0](https://github.com/globalcitizen/php-iban/releases/tag/v3.0.0)__ has been released.
+ * Same as previous but bump version to fix issues with the addition of namespaces. (See [#104](https://github.com/globalcitizen/php-iban/issues/104))
+ * Versions 2.8.x are being removed from the releases.
+ * Hopefully this should fix things for users upgrading from earlier versions via composer.
+
+__[Version 2.8.2](https://github.com/globalcitizen/php-iban/releases/tag/v2.8.1)__ has been released.
+ * Same as previous but officially drop php-5.2 support due to lack of namespacing.
+
+__[Version 2.8.1](https://github.com/globalcitizen/php-iban/releases/tag/v2.8.1)__ has been released.
+ * `TL` BBAN format regex removed extraneous spaces (did not affect IBAN validation). (Thanks to @DanyCorbineauBappli)
+
+News: June 2020
+---------------
+__[Version 2.8.0](https://github.com/globalcitizen/php-iban/releases/tag/v2.8.0)__ has been released.
+ * Object oriented class is now namespaced.
+
+News: May 2020
+--------------
+__[Version 2.7.5](https://github.com/globalcitizen/php-iban/releases/tag/v2.7.5)__ has been released.
+ * Corrections from newer IBAN registry releases
+   * Updated Egypt example IBAN and registry entry (disabled French national checksum scheme as this no longer works with the example IBAN provided. Users with insight please check, there are no examples visible online!)
+   * Corrections to Polish BBAN length (now fixed, previously spuriously specified as variable)
+   * Corrections to Seychelles BBAN and IBAN structure
+
+__[Version 2.7.4](https://github.com/globalcitizen/php-iban/releases/tag/v2.7.4)__ has been released.
+ * New function `iban_to_obfsucated_format()` or `ObfuscatedFormat()` to obfuscate IBAN for specific output scenarios (such as relative identification)
+   * Thanks to @jaysee for feature request #99
+
+News: November 2019
+------------------
+__[Version 2.7.3](https://github.com/globalcitizen/php-iban/releases/tag/v2.7.3)__ has been released.
+ * Load registry only when used. This creates slightly more overhead in real world use, but nominally substantially reduces load times in the edge case event that you include the library but only want to use a function that does not require the IBAN registry to be loaded.
+   * Thanks to @manitu-opensource
+
+__[Version 2.7.2](https://github.com/globalcitizen/php-iban/releases/tag/v2.7.2)__ has been released.
+ * Fix composer file to add license.
+   * Thanks to @SunMar
+
+News: October 2019
+------------------
+__[Version 2.7.1](https://github.com/globalcitizen/php-iban/releases/tag/v2.7.1)__ has been released.
+ * Update erroneous bank ID stop offset for Costa Rica.
+   * Thanks to @thinkpozzitive
+ * Minor syntax updates
+   * Thanks to @bwurst
+ * Add quite a number of Costa Rica example IBANs for confidence in testing.
+
+News: July 2019
+---------------
+
+__[Version 2.7.0](https://github.com/globalcitizen/php-iban/releases/tag/v2.7.0)__ has been released.
+ * Fixed erroneous Liechtenstein BBAN length.
+ * Update National Bank of Greece name/website.
+
+News: August 2018
+-----------------
+
+__[Version 2.6.9](https://github.com/globalcitizen/php-iban/releases/tag/v2.6.9)__ has been released.
+ * Added national checksum implementation for San Marino (`SM`)
+ * Thanks to @francescozanoni 
+
+__[Version 2.6.8](https://github.com/globalcitizen/php-iban/releases/tag/v2.6.8)__ has been released.
+ * Added national checksum implementation for Italy (`IT`)
+ * Thanks to @francescozanoni 
+
+News: June 2018
+---------------
+
+__[Version 2.6.7](https://github.com/globalcitizen/php-iban/releases/tag/v2.6.7)__ has been released.
+ * Added national checksum implementation for Slovakia (`SK`)
+ * Thanks to @ostrolucky
+
+News: June 2018
+---------------
+
+__[Version 2.6.6](https://github.com/globalcitizen/php-iban/releases/tag/v2.6.6)__ has been released.
+ * Fixed generation of voluminous errors in environments without `ini_set` enabled
+ * Thanks to @agil-NUBBA
+
+News: March 2018
+----------------
+
+__[Version 2.6.5](https://github.com/globalcitizen/php-iban/releases/tag/v2.6.5)__ has been released.
+ * Fixed spurious warning when `gmp` extension was enabled
+ * Thanks to @marcovo
+
+__[Version 2.6.4](https://github.com/globalcitizen/php-iban/releases/tag/v2.6.4)__ has been released.
+ * Remove spurious dependency on `bcmath` extension
+ * Minor documentation updates
+
+__[Version 2.6.3](https://github.com/globalcitizen/php-iban/releases/tag/v2.6.3)__ has been released.
+ * Upgrade travis environment as old one broken
+ * Fix test execution under new Travis environment
+ * Re-addition of HHVM test environments
+ * Addition of PHP-5.2 test environment
+ * A few new test IBANs
+
+__[Version 2.6.2](https://github.com/globalcitizen/php-iban/releases/tag/v2.6.2)__ has been released.
+ * Update Croatia SEPA status
+ * Thanks to @Pappshadow
+
+News: August 2017
+-----------------
+
+__[Version 2.6.1](https://github.com/globalcitizen/php-iban/releases/tag/v2.6.1)__ has been released.
+ * Fixed missing registry data.
+ * Thanks to @monojp
+
+__[Version 2.6.0](https://github.com/globalcitizen/php-iban/releases/tag/v2.6.0)__ has been released.
+ * World = conquered.
+   * We now have well over 100 supported countries.
+   * According to packagist, we are now the most popular IBAN-related project for PHP ... and quite possibly the internet!
+ * Addition of official countries
+   * Belarus (BY)
+   * El Salvador (SV)
+   * Iraq (IQ)
+ * Addition of unofficial countries
+   * Central African Republic (CF)
+   * Chad (TD)
+   * Comoros (KM)
+   * Congo (CG)
+   * Djibouti (DJ)
+   * Egypt (EG)
+   * Equitorial Guinea (GQ)
+   * Gabon (GA)
+   * Guinea-Bissau (GW)
+   * Honduras (HN)
+   * Morocco (MA)
+   * Nicaragua (NI)
+   * Niger (NE)
+   * Togo (TG)
+ * Additional example Iran (IR) IBANs.
+ * As HHVM is no longer supported by Travis we have dropped it from our automated testing, although php-iban should continue to work fine on HHVM.
+ * Minor documentation updates
+
+
+News: October 2016
+------------------
+
+__[Version 2.5.9](https://github.com/globalcitizen/php-iban/releases/tag/v2.5.9)__ has been released.
+ * Bring us up to date with IBAN registry release #69 from #66
+   * Release #67: fixes broken Costa Rica format and disables Croatia SEPA status 
+   * Release #69: adds Sao Tome and Principe bank + branch offsets
+
+
+News: August 2016
+-----------------
+
+__[Version 2.5.8](https://github.com/globalcitizen/php-iban/releases/tag/v2.5.8)__ has been released.
+ * Fix [issue #52](https://github.com/globalcitizen/php-iban/issues/52) (thanks to [@simeucci](https://github.com/simeucci) for reporting), apologies for the delay!
+ * Minor documentation updates
+
+
+News: June 2016
+---------------
+
+__[Version 2.5.7](https://github.com/globalcitizen/php-iban/releases/tag/v2.5.7)__ has been released.
+ * Minor changes missed in latest edition (May 2016, version 66) registry release
+  * New Seychelles (SC) example IBAN
+  * Unfix Mauritania (MR) checksum digits (no functional change)
+ * Minor documentation updates
+
+
+News: May 2016
+--------------
+
+__[Version 2.5.6](https://github.com/globalcitizen/php-iban/releases/tag/v2.5.6)__ has been released.
+ * Update to conform with latest edition (May 2016, version 66) registry release
+  * Many of the corrections we had apparently already resolved on initial data import
+  * Moldova (MD): Split 20!c to 2!c18!c
+  * Seychelles (SC): Fix IBAN format (SWIFT markup)
+  * Tunisia (TN): Remove hardcoded 59 as IBAN checksum (following SWIFT; though inefficient)
+ * Minor documentation updates
+  * Update stats/figures for php-iban installs/stars/etc.
+  * Add new 'powered by'
+
+
+News: April 2016
+----------------
+
+__[Version 2.5.5](https://github.com/globalcitizen/php-iban/releases/tag/v2.5.5)__ has been released.
+ * Update to conform with latest edition (April 2016, version 65) registry release
+  * Corrected account format for Seychelles (SC) to permit alphabetic characters (formerly numeric only)
+
+
+News: March 2016
+----------------
+
+__[Version 2.5.4](https://github.com/globalcitizen/php-iban/releases/tag/v2.5.4)__ has been released.
+ * Update to conform with latest edition (March 2016, version 64) registry release
+  * Added Seychelles (SC)
+  * The three other changes apparently corrected registry errors we had already caught during record ingestion and testing
+
+__[Version 2.5.3](https://github.com/globalcitizen/php-iban/releases/tag/v2.5.3)__ has been released.
+ * Added [Falsehoods Programmers Believe About IBANs](https://github.com/globalcitizen/php-iban/blob/master/docs/FALSEHOODS.md), inspired by...
+  * [Falsehoods Programmers Believe About Phone Numbers](https://github.com/googlei18n/libphonenumber/blob/master/FALSEHOODS.md)
+  * [Falsehoods Programmers Believe About Names](http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/)
+  * [Falsehoods Programmers Believe About Time](http://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time)
+  * [Falsehoods Programmers Believe About Geography](http://wiesmann.codiferes.net/wordpress/?p=15187)
+  * [Falsehoods Programmers Believe About Addresses](https://www.mjt.me.uk/posts/falsehoods-programmers-believe-about-addresses/)
+ * Additional example IBANs
+  * Azerbaijan (AZ)
+  * Austria (AT)
+  * Angola (AO)
+  * San Marino (SM)
+ * Various minor changes
+
+
+News: February 2016
+-------------------
+
+__[Version 2.5.2](https://github.com/globalcitizen/php-iban/releases/tag/v2.5.2)__ has been released.
+ * Miscellaneous test library updated to validate example IBANs collection.
+
+__[Version 2.5.1](https://github.com/globalcitizen/php-iban/releases/tag/v2.5.1)__ has been released.
+ * The 'Narodna banka Srbije' (`908`) bank in Serbia (RS) appears to have multiple live IBANs with broken national checksums, so we ignore all national checksums on accounts from that bank.
+
+__[Version 2.5.0](https://github.com/globalcitizen/php-iban/releases/tag/v2.5.0)__ has been released.
+ * All users are encouraged to upgrade; this release is considered long term stable.
+ * The following national checksum schemes added in the 2.4.x series are now included and well validated, while invalid assumptions have been removed:
+  * Belgium (BE)
+  * Spain (ES)
+  * Monaco (MC)
+  * France (FR)
+  * Norway (NO)
+  * Montenegro (ME)
+  * Macedonia (MK)
+  * Netherlands (NL) - including exception for `INGB` (ING Bank) who have dropped the original checksum
+  * Portugal (PT)
+  * Serbia (RS)
+  * Slovenia (SI) - including exception for `01` (Bank of Slovenia) who do not honour checksums
+  * Timor Lest (TL)
+ * In addition, a library of test IBANs is being maintained under `utils/example-ibans` which has a good number of entries for a good number of countries already. This should simplify future research.
+ * Documented [ideas for the enhancement of the mistranscription error correction suggestion function](https://github.com/globalcitizen/php-iban/commit/045f39b33468e04ff4a64a3bd8cba92611149935#diff-61178a0267b9e23c2b5c19c0f4671a22).
+
+__[Version 2.4.20](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.20)__ has been released.
+ * Another bugfix release, based on further real world test IBANs from certain countries:
+  * Remove Bosnia (BA) national checksum support
+
+__[Version 2.4.19](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.19)__ has been released.
+ * Another bugfix release, based on further real world test IBANs from certain countries:
+  * Remove Finland (FI) national checksum support
+
+__[Version 2.4.18](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.18)__ has been released.
+ * Another bugfix release, based on further real world test IBANs from certain countries:
+  * Remove Poland (PL) national checksum support
+
+__[Version 2.4.17](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.17)__ has been released.
+ * Bank of Slovenia (bank code `01` under Slovenia (SI)) does not implement the national checksum scheme, as a special case. An exception has been added to the Slovenia national checksum implementation.
+
+__[Version 2.4.16](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.16)__ has been released.
+ * Another bugfix release, based on further real world test IBANs from certain countries:
+  * Remove Sweden (SE) national checksum support
+ * I am now instituting a new rule that if national checksum support has not been tested on 10+ real world IBANs, preferably 20+ across a range of institutions, then it does not get committed. This means that small countries will be impossible to add until research is done beyond web-browsing.
+
+__[Version 2.4.15](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.15)__ has been released.
+ * The Netherlands (NL) bank 'INGB' no longer uses the national checksum scheme, and has been excepted from the check. This marks our first bank-specific checksum feature.
+
+__[Version 2.4.14](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.14)__ has been released.
+ * Another bugfix release, based on further real world test IBANs from certain countries:
+  * Remove Estonia (EE) national checksum support
+  * Remove Hungary (HU) national checksum support
+
+__[Version 2.4.13](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.13)__ has been released.
+ * This release is mostly about bugfixes, after spending a lot of time gathering IBANs online and using them for further testing.
+ * Tunisia (TN) national checksum support has been removed, after additional testing with IBAN gathered from the internet it was found not to be correct. Perils of reverse-engineering!
+ * A couple of other bugfixes:
+  * The function `iban_mistranscription_suggestions()` now behaves correctly when passed loosely formatted IBAN-like strings
+  * The checksum algorithm `_verhoeff()` which supports certain national checksum implementations now behaves correctly when passed invalid input
+
+__[Version 2.4.12](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.12)__ has been released.
+ * Tunisia (TN) national checksum support has been added.
+
+__[Version 2.4.11](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.11)__ has been released.
+ * It is now possible to query the central bank name and URL for each country, from new registry fields `central_bank_url` and `central_bank_name`, for example:
+  * The central bank for New Caledonia (NC) is the 'Overseas Issuing Institute (Institut d'émission d'Outre-Mer)' and their URL is http://www.ieom.fr/
+  * The central bank for the British Virgin Islands (BV) is 'The British Virgin Islands Financial Services Commission' and their URL is http://www.bvifsc.vg/
+  * There is no central bank for the IIBAN (Internet) (AA).
+
+__[Version 2.4.10](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.10)__ has been released.
+ * New registry field `currency_iso4217` stores the official currency of the country in ISO4217 alpha code format, for example:
+  * The currency of Iceland (IS) is ISD
+  * The currency of Saint-Pierre and Miquelon (PM) is EUR
+  * The currency of Wallis and Futuna (WF) is XPF
+
+__[Version 2.4.9](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.9)__ has been released.
+ * New registry field `parent_registrar` stores the parent registrar IBAN country of an IBAN country, for example:
+  * Åland Islands (AX) parent registrar is Finland (FI)
+  * Faroe Islands (FO) parent registrar is Denmark (DK)
+  * New Caledonia (NC) parent registrar is France (FR)
+
+__[Version 2.4.8](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.8)__ has been released.
+ * Monaco (MC) national checksum support has been added.
+
+__[Version 2.4.7](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.7)__ has been released.
+ * Netherlands (NL) national checksum support has been added.
+
+__[Version 2.4.6](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.6)__ has been released.
+ * Poland (PL) national checksum support has been added.
+
+__[Version 2.4.5](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.5)__ has been released.
+ * Estonia (EE) national checksum support has been added.
+ * Finland (FI) national checksum support has been added.
+ * Macedonia (MK) national checksum support has been added.
+ * Montenegro (ME) national checksum support has been added.
+ * Norway (NO) national checksum support has been added.
+ * Serbia (RS) national checksum support has been added.
+ * Slovenia (SI) national checksum support has been added.
+ * Sweden (SE) national checksum support has been added.
+
+__[Version 2.4.4](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.4)__ has been released.
+ * Portugal (PT) national checksum support has been added.
+
+__[Version 2.4.3](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.3)__ has been released.
+ * Hungary (HU) national checksum support has been added.
+
+__[Version 2.4.2](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.2)__ has been released.
+ * Albania (AL) national checksum support has been added.
+ * Timor-Leste (TL) national checksum support has been added.
+
+__[Version 2.4.1](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.1)__ has been released.
+ * Bosnia (BA) national checksum support has been added.
+
+__[Version 2.4.0](https://github.com/globalcitizen/php-iban/releases/tag/v2.4.0)__ has been released.
+ * It is now possible to determine, verify and set the correct national checksums for some countries that offered a pre-IBAN national checksum algorithm via the new functions `iban_{set|find|verify}_nationalchecksum()` and their OO-wrapper equivalents. Presently Belgium (BE), France (FR) and Spain (ES) are supported. If you would like to see your country supported, please see [issue #39](https://github.com/globalcitizen/php-iban/issues/39) and [issue #41](https://github.com/globalcitizen/php-iban/issues/41).
+
+
+News: January 2016
+------------------
+
+__[Version 2.3.1](https://github.com/globalcitizen/php-iban/releases/tag/v2.3.1)__ has been released.
+ * Fix paste error in Bosnia IANA code
+ * Additional tests for new country functions
+
+__[Version 2.3.0](https://github.com/globalcitizen/php-iban/releases/tag/v2.3.0)__ has been released.
+ * All IBAN country records can now be cross-referenced with their corresponding [IANA](https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains#Country_code_top-level_domains) and [ISO3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Current_codes) codes, if available
+
+__[Version 2.2.0](https://github.com/globalcitizen/php-iban/releases/tag/v2.2.0)__ has been released.
+ * Fully up to date with SEPA membership list. (Added new member for 2016, Andorra)
+ * Fully up to date with latest SWIFT IBAN registry PDF.
+ * Many fixes and new features since 2.1.0
+ * All users are encouraged to ugprade.
+
+__[Version 2.1.9](https://github.com/globalcitizen/php-iban/releases/tag/v2.1.9)__ has been released.
+ * Example field updates attempting to include what is possible from SWIFT IBAN registry PDF version #63. There persist [significant issues with this release process](https://github.com/globalcitizen/php-iban/blob/master/docs/COMEDY-OF-ERRORS).
+
+__[Version 2.1.8](https://github.com/globalcitizen/php-iban/releases/tag/v2.1.8)__ has been released.
+ * National BBAN checksum offset data for Belgium added.
+
+__[Version 2.1.7](https://github.com/globalcitizen/php-iban/releases/tag/v2.1.7)__ has been released.
+ * National BBAN checksum offset data added to registry. This can be queried via the new functions `iban_get_nationalchecksum_part()`, `iban_country_get_nationalchecksum_start_offset()` and `iban_country_get_nationalchecksum_stop_offset()` and their OO-wrapper equivalents `$myIban->NationalChecksum()`, `$myCountry->NationalChecksumStartOffset()` and `$mycountry->NationalChecksumStopOffset()`. Test and documentation updated. If you know anything about national checksum algorithms, please lend a hand at [issue #39](https://github.com/globalcitizen/php-iban/issues/39).
+
+__[Version 2.1.6](https://github.com/globalcitizen/php-iban/releases/tag/v2.1.6)__ has been released.
+ * OO wrapper and documentation updated for new strict `machine_format_only` validation.
+
+__[Version 2.1.5](https://github.com/globalcitizen/php-iban/releases/tag/v2.1.5)__ has been released.
+ * Additional strict `machine_format_only` mode for `verify_iban()` to close [issue #22](https://github.com/globalcitizen/php-iban/issues/22).
+
+__[Version 2.1.4](https://github.com/globalcitizen/php-iban/releases/tag/v2.1.4)__ has been released.
+ * Simplified a function using a php4+ builtin.
+
+__[Version 2.1.3](https://github.com/globalcitizen/php-iban/releases/tag/v2.1.3)__ has been released.
+ * Behavior of `iban_to_human_format()` has been fixed when passed input already containing spaces.
+ * OO-based tests are now executed following successful procedural tests.
+ * An additional test library for testing edge-case behavior in general functions is now executed following the main tests.
+
+__[Version 2.1.2](https://github.com/globalcitizen/php-iban/releases/tag/v2.1.2)__ has been released. All known unofficial IBAN country codes are now integrated. As well as minor documentation updates and a shortening of the reported name of Kosovo, this version adds:
+ * Ivory Coast (CI)
+ * Madagascar (MG)
+ * Mali (ML)
+ * Mozambique (MZ)
+ * Senegal (SN)
+ * Ukraine (UA)
+
+__[Version 2.1.1](https://github.com/globalcitizen/php-iban/releases/tag/v2.1.1)__ has been released. Currently unofficial IBAN country codes are being integrated, and the process remains ongoing. This version adds:
+ * Burkina Faso (BF)
+ * Burundi (BI)
+ * Cameroon (CM)
+ * Cape Verde (CV)
+ * Iran (IR) 
+
+__[Version 2.1.0](https://github.com/globalcitizen/php-iban/releases/tag/v2.1.0)__ has been released.  
+Currently unofficial IBAN country codes are being integrated, and the process remains ongoing.  A new flag has been created to check whether a country is an official, SWIFT-issued record or not. The following new countries have therefore been added.
+ * Algeria (DZ)
+ * Angola (AO)
+ * Benin (BJ)
+
+Note also that the IIBAN (AA) record has been marked unofficial, and features listed in `docs/TODO` have been migrated to Github issues and that file deleted.
+
+__[Version 2.0.1](https://github.com/globalcitizen/php-iban/releases/tag/v2.0.1)__ has been released. This is to celebrate real testing, composer support, as well as finally catching up with changes. This version should be up to date with all registry changes to the present, including changes or additions to the countries:
+ * IIBAN (AA)
+ * Brazil (BR)
+ * Costa Rica (CR)
+ * Kazakhstan (KZ)
+ * Kosovo (XK)
+ * Kuwait (KW)
+ * Saint Barthelemy (BL)
+ * Saint Lucia (LC) 
+ * Saint Martin (French Part) (MF)
+ * Sao Tome and Principe (ST)
+ * Timor Leste (TL)
+ * Turkey (TR)
+
+__[Version 1.6.0](https://github.com/globalcitizen/php-iban/releases/tag/v1.6.0)__ has been released. This version features more registry corrections (newly added territories with faulty data, bad checksums in sample IBANs, etc.) as well as enhanced testing routines, extended documentation, and corrected documentation. All users are advised to upgrade. We now have automated test script execution with Travis CI, to provide additional robustness for all committed code. This took longer than expected as unfortunately I picked the exact time Travis broke their build logs - https://www.traviscistatus.com/incidents/fcllblkclgmb - to see what all the fuss was about... proving again that cloud computing is just *great* for breaking things unexpectedly. Because they want to hide things, there was literally no debug output whatsoever, and I was led to believe this was my fault. Fellow programmers, behold: it is the dawning of the age of the mystical fail.
+
+__[Version 1.5.0](https://github.com/globalcitizen/php-iban/releases/tag/v1.5.0)__ has been released. There are no code changes, but we now have http://packagist.org/ integration, hopefully this triggers it to start working. If you use packagist, you can now add the library to your project by just running `composer require globalcitizen/php-iban` (thanks to @acoulton for pointing the way)
+
+__[Version 1.4.9](https://github.com/globalcitizen/php-iban/releases/tag/v1.4.9)__ has been released using the new Github-based release process. Hopefully this provides a solid anchor point for those bundling the library with other software. We also have a contributed composer metadata file to ease integration.
+New IBAN registry URLs integrated.
+Removed old SVN tag/trunk structure.
+
+News: July 2015
+---------------
+Corrected SWIFT URL to IBAN page.
+Emphasized mistranscription error support.
+
+News: March 2015
+----------------
+Finally, google has killed `code.google.com` and we have migrated to Github! Once the old `trunk`/`tag` structure (lingering from `svn`) is cleaned up and this document translated from the old wiki format to markdown, a new version will be issued.
+
+News: June 2014
+---------------
+
+__Version 1.4.6__ has been released:
+ * Fixes for Jordan and Qatar. Turns out both of them have broken TXT registry entries, PDF entries differ and the PDF is the one to go for (familiar story).
+ * Some further improvements.
+
+Unfortunately, Google now requires `code.google.com` projects to use Google Drive. I tried to use Google Drive (sign up for a new account, jump through email hoops, get treated as a robot, learn stupid new touchy-feely-friendly interface, get meaningless error messages like 'Your sharing limit has been exceeded' (with 2x290KB files on a new account I was told to create) and lost patience entirely.
+
+So for the moment, you'll just have to download using `git`, instead. I will migrate `php-iban` to Github shortly. Google really is a pain in the ass recently, what with all of this Google+ and Google Drive junk, ruining Picasa, ruining Sketchup by lack of attention, etc. What are they thinking?
+
+News: March 2014
+----------------
+__Version 1.4.5__ has been released:
+ * Addition of Jordan and Qatar
+ * Minor changes to documentation and support scripts.
+
+__Version 1.4.4__ has been released:
+ * Fix SEPA status of Croatia (HR)
+ * Subsqeuent SEPA status audit based upon https://en.wikipedia.org/wiki/Single_Euro_Payments_Area turned up some other status issues (this information is not contained within the official IBAN registry)
+    * Faroe Islands, Greenland, San Marino status fixed. Everything else apparently hunky dory.
+
+*The project source code repository has switched from `svn` (ugh) to `git` (yay!)*.
+ * This should make future changes less painful.
+
+
+News: September 2013
+--------------------
+__Version 1.4.3__ has been released:
+ * Add Aland Islands (AX), part of Finland (FI) that is only documented in the SEPA status field of Finland and does not have its own entry or mention elsewhere in the IBAN registry document.
+    * Consider but do not add either of the somewhat similar Canary Islands (CI) or Ceuta/Melilla (EA) - both minor territories of Spain (ES) - due to lack of any evidence of usage.
+ * Fix SEPA status for Spain (ES), Finland (FI), Porgual (PT) due to registry values being mixed with free text.
+    * Document this and further issues with the official IBAN registry document, both as documentation in `docs/COMEDY-OF-ERRORS` and inline within the registry converter.
+ * Update human country name of Palestine to better mirror current registry document ("State of" is dropped as is the reigning style, so simply "Palestine" is presented)
+ * Updating an outstanding last modified date within the registry from the previous release
+
+News: August 2013
+-----------------
+__Version 1.4.2__ has been released:
+ * Resolve issue #19: incorrect SEPA status of France/French territories due to a parser bug. (Thanks to the reporter)
+
+__Version 1.4.1__ has been released:
+ * Requests
+    * Attempts to intelligently calculate the 'account' portion of a BBAN based upon the (non-)presence of a branch ID and bank ID portion, by request (for Germany/Austria. Previously this was requested for the Netherlands, however this solution should fix results for everyone!)
+    * Add 'IIBAN' prefix removal support to machine format conversion function
+    * Add _gmp_ disable flag (`$__disable_iiban_gmp_extension=true;`)
+ * Silence warnings on some PHP engine configurations
+ * Update Brazil record (minor)
+ * No longer redistribute IBAN registry in .txt format
+ * Improve inline documentation
+
+News: June 2013
+---------------
+__Version 1.4.1__ is still being prepared, squashing some bugs and updating the registry ... meanwhile, it has come to my attention that we have been featured in the Code Candy blog!  http://www.codecandies.com/2012/05/30/no-exceptions/ Hooray for the German sense of humour! Hahah.
+
+News: March 2013
+----------------
+__Version 1.4.0__ has been released:
+ * Resolves an issue reported affecting the last few versions when attempting to generate a correct checksum for a checksum-invalid IBAN.
+ * Adds `VERSION` file, to include hard version information in source tree, by request.
+
+News: February 2013
+-------------------
+__Version 1.3.9__ has been released:
+ * Resolves issue reported in 1.3.7 re-enables the more efficient PHP _gmp_ library based checksum code (thanks to rpkamp)
+
+__Version 1.3.8__ has been released:
+ * An error in checksum processing for some IBANs using the new _gmp_ library based MOD97 routine (_only affects users with php-iban 1.3.7 and the PHP _gmp_ library enabled_) has been reported. As an immediate workaround 1.3.8 is being released with the following changes:
+ ** Code from 1.3.6
+ ** Registry from 1.3.7
+
+__Version 1.3.7__ has been released:
+ * Added Brazil
+ * Added two new French overseas territories
+ * Reduced 'Moldova' to normalized short-form name
+ * Large CPU efficiency improvement in IBAN validation routine (16x if PHP _gmp_ extension is installed, 5x otherwise. Special thanks to algorithmic contributor Chris and to engineers everywhere upholding the Germanic tradition of precision and efficiency! Alas, I am but part-German, for shame...)
+ * Minor internal/tool updates
+ * Some comedy of errors additions
+
+News: November 2012
+-------------------
+
+__Version 1.3.6__ has been released:
+ * Update IIBAN format for latest IETF draft.
+
+News: October 2012
+------------------
+
+__Version 1.3.5__ has been released:
+ * Correct lack of support for lower case alphabetic characters (ie. non ECBS-compliant) in human to machine format conversion function.
+
+__Version 1.3.4__ has been released:
+ * Add reference to the latest ECBS recommendations and include them in documentation.
+
+__Version 1.3.3__ has been released:
+ * Very minor efficiency improvement.
+
+News: September 2012
+--------------------
+
+__Version 1.3.2__ has been released:
+ * Registry updates
+   * Added Palestinian Territories
+   * Moldova fixed its format
+   * Finland fixed its bank identifier location
+   * Saudi Arabia - remove spurious trailing space in example
+
+News: June 2012
+---------------
+
+__Version 1.3.1__ has been released:
+ * New countries added
+   * Azerbaijan (AZ)
+   * Costa Rica (CR)
+   * Guatemala (GT)
+   * Moldova (MD)
+   * Pakistan (PK)
+   * British Virgin Islands (VG)
+ * Miscellaneous updates
+   * Normalize/simplify examples (FI,PT,SA)
+   * Normalize/simplify human country name (BH,LI,MK)
+   * Documentation updates
+
+News: December 2011
+-------------------
+__Version 1.3.0__ has been released. This release adds mistranscription error suggestion support.
+
+__Version 1.2.0__ has been released. This release adds Internet International Bank Account Number (IIBAN) support, as per the current IIBAN Internet Draft at http://tools.ietf.org/html/draft-iiban-01
+
+News: September 2011
+--------------------
+__Version 1.1.2__ has been released. This adds long open tags to the main library file in order to simplify deployment on many default PHP installations.
+
+News: August 2011
+-----------------
+__Version 1.1.1__ has been released. This fixes a typo in a function call in the new OO wrapper. Non OO users do not need to upgrade.
+
+News: July 2011
+---------------
+__Version 1.1.0__ has been released. This version adds an object oriented wrapper library and related updates to documentation and test scripts. It is not critical for existing users to upgrade.
+
+__Version 1.0.0__ has been released. This version includes the following changes:
+ * *Support for the SEPA flag* ("Is this country a member of the Single Euro Payments Area?"), both in the registry and with a new function `iban_country_is_sepa($iban_country)`
+ * *Placeholder support for converting machine format IBAN to human format* (simply adds a space every four characters) with the function `iban_to_human_format($iban)`
+ * *Fixed a series of domestic example issues* in the registry file that had been imported from SWIFT's own broken IBAN registry
+ * *Normalised example fields* in the registry to better facilitate use in automated contexts (Austria, Germany, etc.)
+ * *Updated test code*
+ * *Added a significant amount of new documentation*
+ * *Reorganised file layout•
+ * *Moved to _x.y.z_ format versioning and use of subversion 'tags'* in conjunction with the 1.0.0 release.
+
+---
+
+Earlier in the month... *Small maintenance release*, not critical.
+ * The _split()_ function has been replaced with _explode()_ to prevent warnings (or error on _very_ new PHP engines)
+ * Resolved an issue on PHP environments configured to display warnings would display a warning when an IBAN input to be validated did not include a prefix that was a valid IBAN country code. (Nobody should be running production PHP environments with such warnings enabled, anyway!) 
+
+News: June 2011
+---------------
+ * We are now well over 1000 downloads: not bad considering how specific this project is!
+ * A *new version* has been released that fixes many important changes to the official registry, plus adds some new features.
+   * *Add New French Territories* (GF,GP,MQ,RE)
+     Older versions of the specification did not include the GF,GP,MQ,RE French territories, only the PF,TF,YT,NC,PM,WF French territories. The new territories have now been added to the database.
+   * *Add New Countries*
+     We welcome Bahrain (BH), Dominican Republic (DO), Khazakstan (KZ), United Arab Emirates (AE) to the database.
+   * *Format/example updates*
+     There have apparently been some minor format/example changes, these have been rolled in to existing countries.
+   * *Inclusion of altered IBAN_Registry.txt*
+     Errors and omissions have been found within the official IBAN_Registry.txt file, namely the exclusion of Khazakstan (KZ) and only partial information on Kuwait (KW), and errors in both of these countries' PDF specifications. This is SWIFT's fault: shame on them! I suspect they have changed staff recently. Anyway, a version of IBAN_Registry.txt with these problems solved is now distributed along with php-iban.
+   * *Fix for Tunisia*
+     Strangely I visited Tunisia during the revolution in January this year. Sorry to the Tunisian people for getting their IBAN format wrong! TN59 + 20 digits is the correct format. This is now included in the new registry file.
+   * *Fix for Albania*
+     The SWIFT format information was updated for Albania. (Did not affect validation, since this uses regular expressions which were already correct)
+   * *Additional and revised documentation*
+     Further documentation has been added to the project.
+   * *Automated IBAN_Registry.txt fix/conversion tool*
+     A new _convert-registry_ tool has been added to the project that attempts to automatically normalise/fix problems with the official SWIFT .txt specification as much as possible. Note that this is not enough to get a good registry.txt file (the internal format used by php-iban) as SWIFT's .txt release excludes entire countries in the PDF specification. In addition, there are some errors in the PDF specification that need to be manually resolved at present. These can be seen resolved in the _IBAN_Registry.txt_ file.
+
+News: December 2009
+-------------------
+
+*We now have a http://groups.google.com/group/php-iban-users mailing list.  Feel free to post your feedback, queries or suggestions - we'd love to know how you are using the library.  To date, the project has reached over 400 downloads and still going strong, with more than one new user per day - a pretty good showing for a specialised library!
+
+*__version 12__ has been released.  The registry file has been improved, partly as a result of user reports and partly as a result of issues uncovered while performing automated tests against version 11.
+
+ * *Corrected header row*
+   Two columns were not represented in the title (`bban_length` and `iban_length`).  They have now been added.
+
+ * *Fixes to registry entries for French Territories* (PF,TF,YT,NC,PM,WF)
+   French territories are not explicitly included in the SWIFT specification textfile. 
+   They were duplicated from France according to an unstructured comments against 
+   that entry.  Example IBANs were then made for illustrative purposes by simply
+   modifying the country prefix without regenerating the checksums.  The IBAN 
+   examples included for these territories should now be correct.
+
+ * *Gibraltar and Hungary* (GI,HU)
+   Fixed a bug where both territories had a superfluous colon appended to their regular expressions after initial document conversion, which was causing validation failures for all IBANs in those countries.
+
+ * *Mauritius* (MU)
+   Corrected IBAN length expectation from 31 to 30.
+
+ * *Sweden* (SE)
+   Example IBAN had been manually modified from IBAN specification example early in development and did not pass checksum.  The IBAN official example has been restored.
+
+ * *Tunisia* (TN)
+   Corrected improper validation strings caused by a bug in initial document conversion (IBAN format-specifier to regular-expression conversion function).
+ 
+
+Documentation (Procedural/Recommended)
+======================================
+
+```php
+require_once('php-iban.php');
+# ... your code utilising IBAN functions...
+```
+
+Validation Functions
+--------------------
+
+```php
+# Verify an IBAN number.
+#  An optional second argument specifies $machine_format_only (default is false)
+#  If true, the function will not tolerate unclean inputs
+#   (eg. spaces, dashes, leading 'IBAN ' or 'IIBAN ', lower case)
+#  If false (default), input can be in either:
+#   - printed ('IIBAN xx xx xx...' or 'IBAN xx xx xx...'); or 
+#   - machine ('xxxxx')
+#  ... string formats.
+#  Returns true or false.
+if(!verify_iban($iban,$machine_format_only=false)) {
+ # ...
+}
+
+# Check the checksum of an IBAN - code modified from Validate_Finance PEAR class
+if(!iban_verify_checksum($iban)) {
+ # ...
+}
+
+# Suggest what the user really meant in the case of transcription errors
+$suggestions = iban_mistranscription_suggestions($bad_iban);
+if(count($suggestions) == 1) {
+ print "You really meant " . $suggestions[0] . ", right?\n";
+}
+
+# Find the correct checksum for an IBAN
+$correct_checksum = iban_find_checksum($iban);
+
+# Set the correct checksum for an IBAN
+$fixed_iban = iban_set_checksum($iban);
+
+# Verify the pre-IBAN era, BBAN-level national checksum for those countries that
+# have such a system and we have implemented.
+# (Returns '' if unimplemented, true or false)
+$result = iban_verify_nationalchecksum($iban);
+if($result == '') {
+ print "National checksum system does not exist or remains unimplemented for the country of IBAN '$iban'.\n";
+}
+elseif($result == true) {
+ print "IBAN '$iban' passes the national checksum algorithm for its country.\n";
+}
+else {
+ print "IBAN '$iban' FAILS the national checksum algorithm for its country.\n";
+}
+
+# Set the pre-IBAN era, BBAN-level national checksum for those countries that
+# have such a system, where that system results in a dedicated checksum
+# substring, and that we have implemented.
+# (Returns '' if unimplemented, or the corrected string)
+# (NOTE: On success, the function also subsequently recalculates the IBAN-level checksum)
+$national_checksum_algorithm_valid_iban = iban_set_nationalchecksum($iban);
+
+# Determine, but do not set, the pre-IBAN era, BBAN-level national checksum 
+# for those countries that have such a system, where that system results in
+# a dedicated checksum substring, and that we have implemented.
+# (Returns '' if unimplemented, or the expected national checksum substring)
+$expected_national_checksum = iban_find_nationalchecksum($iban);
+```
+
+
+Utility Functions
+-----------------
+
+```php
+# Convert an IBAN to machine format.  To do this, we
+# remove IBAN from the start, if present, and remove
+# non basic roman letter / digit characters
+$machine_iban = iban_to_machine_format($iban);
+
+# Convert an IBAN to human format.  To do this, we
+# add a space every four characters.
+$human_iban = iban_to_human_format($iban);
+
+# Convert an IBAN to obfuscated format for relative
+# identification. To do this, we replace all but the
+# leading country code and final four characters with
+# asterisks.
+$obfuscated_iban = iban_to_obfuscated_format($iban);
+```
+
+
+IBAN Country-Level Functions
+----------------------------
+```php
+# Get the name of an IBAN country
+$country_name = iban_country_get_country_name($iban_country);
+
+# Get the domestic example for an IBAN country
+$country_domestic_example = iban_country_get_domestic_example($iban_country);
+
+# Get the BBAN example for an IBAN country
+$country_bban_example = iban_country_get_bban_example($iban_country);
+
+# Get the BBAN format (in SWIFT format) for an IBAN country
+$country_bban_format_as_swift = iban_country_get_bban_format_swift($iban_country);
+
+# Get the BBAN format (as a regular expression) for an IBAN country
+$country_bban_format_as_regex = iban_country_get_bban_format_regex($iban_country);
+
+# Get the BBAN length for an IBAN country
+$country_bban_length = iban_country_get_bban_length($iban_country);
+
+# Get the IBAN example for an IBAN country
+$country_iban_example = iban_country_get_iban_example($iban_country);
+
+# Get the IBAN length for an IBAN country
+$country_iban_length = iban_country_get_iban_length($iban_country);
+
+# Get the IBAN format (in SWIFT format) for an IBAN country
+$country_iban_format_as_swift = iban_country_get_iban_format_swift ($iban_country);
+
+# Get the IBAN format (as a regular expression) for an IBAN country
+$country_iban_format_as_regex = iban_country_get_iban_format_regex($iban_country);
+
+# Determine whether an IBAN country is a member of SEPA (Single Euro Payments Area)
+if(!iban_country_is_sepa($iban_country)) {
+ # ... do something xenophobic ...
+}
+
+# Get the bank ID start offset for an IBAN country
+$country_bankid_start_offset = iban_country_get_bankid_start_offset($iban_country);
+
+# Get the bank ID stop offset for an IBAN country
+$country_bankid_stop_offset = iban_country_get_bankid_stop_offset($iban_country);
+
+# Get the branch ID start offset for an IBAN country
+$country_branchid_start_offset = iban_country_get_branchid_start_offset($iban_country);
+
+# Get the branch ID stop offset for an IBAN country
+$country_branchid_stop_offset = iban_country_get_branchid_stop_offset($iban_country);
+
+# Get the registry edition for an IBAN country (note: IIBAN country 'AA' returns 'N/A')
+$country_registry_edition = iban_country_get_registry_edition($iban_country);
+
+# Determine whether an IBAN country is an official, SWIFT issued country record
+if(!iban_country_get_country_swift_official($iban_country)) {
+ # ... do something against decentralization ...
+}
+
+# Get the IANA code for an IBAN country
+$country_iana = iban_country_get_iana($iban_country);
+
+# Get the ISO3166-1 alpha-2 code for an IBAN country
+$country_iso3166 = iban_country_get_iso3166($iban_country);
+
+# Get the parent registrar IBAN country of an IBAN country
+# (Returns '' in the normal case that the country is independently registered)
+$registrar_country = iban_country_get_parent_registrar($iban_country);
+if($registrar_country=='') {
+ print "The mighty nation of '$iban_country' stands strong and proud...\n";
+ print " ... with its own heirarchy of bureaucrats!\n";
+}
+else {
+ print "It has been foretold that the downtrodden natives of '$iban_country' will one day\n";
+ print "rise up and throw off the shackles of the evil '$registrar_country' oppressors!\n";
+}
+
+# Get the official currency of an IBAN country as an ISO4217 alpha code
+# (Returns '' in the Internet (IIBAN) case, ie. no official currency)
+$official_currency = iban_country_get_currency_iso4217($iban_country);
+if($official_currency == '') {
+ print "There is no official currency for the IBAN country '$iban_country'.\n";
+}
+
+# Get the URL of an IBAN country's central bank
+# (Note: Returns '' if there is no central bank. Also, note that
+#        sometimes multiple countries share one central bank)
+$central_bank_url = iban_country_get_central_bank_url($iban_country);
+
+# Get the name of an IBAN country's central bank
+# (Note: Returns '' if there is no central bank. Also, note that
+#        sometimes multiple countries share one central bank)
+$central_bank_name = iban_country_get_central_bank_name($iban_country);
+
+# Get the membership type of the country
+# There are four types of memberships:
+# * EU-Member States (eu_member)
+# * EFTA-Member States (efta_member)
+# * Other Memberships, which have monetary agreements with the EU (other_member)
+# * Non-Members, which don't belong to the EU or have agreements (non_member)
+$country_membership = iban_country_get_membership($iban_country);
+
+# Get if the country is a eu member state
+# (Note: Returns true, if member state; false otherwise)
+$country_membership = iban_country_get_is_eu_member($iban_country);
+```
+
+
+Parsing Functions
+-----------------
+```php
+# Get an array of all the parts from an IBAN
+$iban_parts = iban_get_parts($iban);
+
+# Get the country part from an IBAN
+$iban_country = iban_get_country_part($iban);
+
+# Get the BBAN part from an IBAN
+$bban = iban_get_bban_part($iban);
+
+# Get the Bank ID (institution code) from an IBAN
+$bank = iban_get_bank_part($iban);
+
+# Get the Branch ID (sort code) from an IBAN
+#  (NOTE: only available for some countries)
+$sortcode = iban_get_branch_part($iban);
+
+# Get the (branch-local) account ID from an IBAN
+#  (NOTE: only available for some countries)
+$account = iban_get_account_part($iban);
+
+# Get the checksum part from an IBAN
+$checksum = iban_get_checksum_part($iban);
+
+# Get the national checksum part from an IBAN (if it exists)
+$checksum = iban_get_nationalchecksum_part($iban);
+```
+
+
+Documentation (Object Oriented Wrapper/Discouraged)
+===================================================
+
+OO use is discouraged as there is a present-day trend to overuse the model.  However, if you prefer OO PHP then by all means use the object oriented wrapper, described below.
+```php
+require_once('oophp-iban.php');
+# ... your code utilising object oriented PHP IBAN functions...
+```
+
+Validation Functions
+--------------------
+```php
+# Example instantiation
+$iban = 'AZ12345678901234'
+$myIban = new IBAN($iban);
+
+# Verify an IBAN number.
+#  Tolerates spaces, prefixes "IBAN ...", dashes, lowercase input, etc.
+#  Returns true or false.
+if(!$myIban->Verify()) {
+ # ...
+}
+# Verify an IBAN number in machine format only.
+#  Does not tolerate lowercase input, separators, whitespace or prefixes.
+#  Returns true or false.
+if(!$myIban->VerifyMachineFormatOnly()) {
+ # ...
+}
+
+# Check the checksum of an IBAN - code modified from Validate_Finance PEAR class
+if(!$myIban->VerifyChecksum()) {
+ # ...
+}
+
+# Suggest what the user really meant in the case of mistranscription errors
+$suggestions = $badIban->MistranscriptionSuggestions();
+if(count($suggestions)==1) {
+ print "You really meant " . $suggestions[0] . ", right?\n";
+}
+
+# Find the correct checksum for an IBAN
+$correct_checksum = $myIban->FindChecksum();
+
+# Set the correct checksum for an IBAN
+$fixed_iban = $myIban->SetChecksum()
+
+# Verify the pre-IBAN era, BBAN-level national checksum for those countries that
+# have such a system and we have implemented.
+# (Returns '' if unimplemented, true or false)
+$result = $myIban->VerifyNationalChecksum();
+if($result == '') {
+ print "National checksum system does not exist or remains unimplemented for this IBAN's country.\n";
+}
+elseif($result == true) {
+ print "IBAN passes the national checksum algorithm for its country.\n";
+}
+else {
+ print "IBAN FAILS the national checksum algorithm for its country.\n";
+}
+
+# Set the pre-IBAN era, BBAN-level national checksum for those countries that
+# have such a system, where that system results in a dedicated checksum
+# substring, and that we have implemented.
+# (Returns '' if unimplemented, or the corrected string)
+# (NOTE: On success, the function also subsequently recalculates the IBAN-level checksum)
+$myIban->SetNationalChecksum();
+
+# Determine, but do not set, the pre-IBAN era, BBAN-level national checksum
+# for those countries that have such a system, where that system results in
+# a dedicated checksum substring, and that we have implemented.
+# (Returns '' if unimplemented, or the expected national checksum substring)
+$national_checksum = $myIban->FindNationalChecksum();
+```
+
+Utility Functions
+-----------------
+
+```php
+# Convert an IBAN to machine format.  To do this, we
+# remove IBAN from the start, if present, and remove
+# non basic roman letter / digit characters
+$machine_iban = $myIban->MachineFormat();
+
+# Convert an IBAN to human format.  To do this, we
+# add a space every four characters.
+$human_iban = $myIban->HumanFormat();
+
+# Convert an IBAN to obfuscated format for relative
+# identification. To do this, we replace all but the
+# leading country code and final four characters with
+# asterisks.
+$obfsucated_iban = $myIban->ObfuscatedFormat();
+```
+
+IBAN Country-Level Functions
+----------------------------
+
+```php
+# To list countries, use the IBAN Class...
+$myIban->Countries();
+
+# ... everything else is in the IBANCountry class.
+
+# Example instantiation
+$countrycode = 'DE';
+$myCountry = new IBANCountry($countrycode);
+
+# Get the country code of an IBAN country
+$country_code = $myCountry->Code();
+
+# Get the name of an IBAN country
+$country_name = $myCountry->Name();
+
+# Get the domestic example for an IBAN country
+$country_domestic_example = $myCountry->DomesticExample();
+
+# Get the BBAN example for an IBAN country
+$country_bban_example = $myCountry->BBANExample();
+
+# Get the BBAN format (in SWIFT format) for an IBAN country
+$country_bban_format_as_swift = $myCountry->BBANFormatSWIFT();
+
+# Get the BBAN format (as a regular expression) for an IBAN country
+$country_bban_format_as_regex = $myCountry->BBANFormatRegex();
+
+# Get the BBAN length for an IBAN country
+$country_bban_length = $myCountry->BBANLength();
+
+# Get the IBAN example for an IBAN country
+$country_iban_example = $myCountry->IBANExample();
+
+# Get the IBAN length for an IBAN country
+$country_iban_length = $myCountry->IBANLength();
+
+# Get the IBAN format (in SWIFT format) for an IBAN country
+$country_iban_format_as_swift = $myCountry->IBANFormatSWIFT();
+
+# Get the IBAN format (as a regular expression) for an IBAN country
+$country_iban_format_as_regex = $myCountry->IBANFormatRegex();
+
+# Determine whether an IBAN country is a member of SEPA (Single Euro Payments Area)
+if(!$myCountry->IsSEPA()) {
+ # ... do something xenophobic ...
+}
+
+# Get the bank ID start offset for an IBAN country
+$country_bankid_start_offset = $myCountry->BankIDStartOffset();
+
+# Get the bank ID stop offset for an IBAN country
+$country_bankid_stop_offset = $myCountry->BankIDStopOffset();
+
+# Get the branch ID start offset for an IBAN country
+$country_branchid_start_offset = $myCountry->BranchIDStartOffset();
+
+# Get the branch ID stop offset for an IBAN country
+$country_branchid_stop_offset = $myCountry->BranchIDStopOffset();
+
+# Get the national checksum start offset for an IBAN country
+$country_nationalchecksum_start_offset = $myCountry->NationalChecksumStartOffset();
+
+# Get the national checksum stop offset for an IBAN country
+$country_nationalchecksum_stop_offset = $myCountry->NationalChecksumStopOffset();
+
+# Get the registry edition for an IBAN country (note: IIBAN country 'AA' returns 'N/A')
+$country_registry_edition = $myCountry->RegistryEdition();
+
+# Determine whether an IBAN country is an official, SWIFT issued country record
+if(!$myCountry->SWIFTOfficial()) {
+ # ... do something against decentralization ...
+}
+
+# Get the IANA code for an IBAN country
+$country_iana = $myCountry->IANA();
+
+# Get the ISO3166-1 alpha-2 code for an IBAN country
+$country_iso3166 = $myCountry->ISO3166();
+
+# Get the parent registrar IBAN country of an IBAN country
+# (Returns '' in the normal case that the country is independently registered)
+$registrar_country = $myCountry->ParentRegistrar();
+if($registrar_country=='') {
+ print "The mighty nation of '$iban_country' stands strong and proud...\n";
+ print " ... with its own heirarchy of bureaucrats!\n";
+}
+else {
+ print "It has been foretold that the downtrodden natives of '$iban_country' will one day\n";
+ print "rise up and throw off the shackles of the evil '$registrar_country' oppressors!\n";
+}
+
+# Get the official currency of an IBAN country as an ISO4217 alpha code
+# (Returns '' in the Internet (IIBAN) case, ie. no official currency)
+$official_currency = $myCountry->CurrencyISO4217();
+if($official_currency == '') {
+ print "There is no official currency for the IBAN country '$iban_country'.\n";
+}
+
+# Get the URL of an IBAN country's central bank
+# (Note: Returns '' if there is no central bank. Also, note that
+#        sometimes multiple countries share one central bank)
+$central_bank_url = $myCountry->CentralBankURL();
+
+# Get the name of an IBAN country's central bank
+# (Note: Returns '' if there is no central bank. Also, note that
+#        sometimes multiple countries share one central bank)
+$central_bank_name = $myCountry->CentralBankName();
+```
+
+
+Parsing Functions
+-----------------
+
+```php
+# Get an array of all the parts from an IBAN
+$iban_parts = $myIban->Parts();
+
+# Get the country part from an IBAN
+$iban_country = $myIban->Country();
+
+# Get the checksum part from an IBAN
+$checksum = $myIban->Checksum();
+
+# Get the BBAN part from an IBAN
+$bban = $myIban->BBAN();
+
+# Get the Bank ID (institution code) from an IBAN
+$bank = $myIban->Bank();
+
+# Get the Branch ID (sort code) from an IBAN
+#  (NOTE: only available for some countries)
+$sortcode = $myIban->Branch();
+
+# Get the (branch-local) account ID from an IBAN
+#  (NOTE: only available for some countries)
+$account = $myIban->Account();
+
+# Get the national checksum part from an IBAN
+#  (NOTE: only available for some countries)
+$checksum = $myIban->NationalChecksum();
+```
+
+
+IBAN Libraries in Other Languages
+---------------------------------
+See for yourself how our approach and features compare favourably with all of these libraries...
+
+| Language   | Library
+| ---------- | --------------------------------------------------------- 
+| C#         | [iban-api-net](https://github.com/aventum-solutions/iban-api-net)
+| Java       | [iban-api-java](https://github.com/aventum-solutions/iban-api-java)
+| Java       | [iban4j](https://github.com/arturmkrtchyan/iban4j)
+| Java       | [java-iban](https://github.com/barend/java-iban)
+| Javascript | [iban.js](https://github.com/arhs/iban.js)
+| Javascript | [ng-iban](https://github.com/mmjmanders/ng-iban)
+| ObjectiveC | [IBAN-Helper](https://github.com/xs4some/IBAN-Helper)
+| ObjectiveC | [ibanValidation](https://github.com/smoldovansky/ibanValidation)
+| Perl       | [various CPAN libraries](http://search.cpan.org/search?query=iban&mode=all)
+| Python     | [django-localflavor](https://github.com/django/django-localflavor)
+| Python     | [iban-generator](https://github.com/lkraider/iban-generator)
+| Ruby       | [bank](https://github.com/max-power/bank)
+| Ruby       | [iban-tools](https://github.com/iulianu/iban-tools)
+| Ruby       | [ibandit](https://github.com/gocardless/ibandit)
+| Ruby       | [ibanizator](https://github.com/softwareinmotion/ibanizator)
+| Ruby       | [iso-iban](https://github.com/apeiros/iso-iban)

+ 12 - 0
htdocs/includes/php-iban/composer.json

@@ -0,0 +1,12 @@
+{
+  "name": "globalcitizen/php-iban",
+  "description": "php-iban is a library for parsing and validating IBAN (and IIBAN) bank account information.",
+  "license": "LGPL-3.0-only",
+  "require": {
+    "php": "^5.4 || ^5.5 || ^5.6 || ^7.0 || ^7.4 || ^8.0 || ^8.1"
+  },
+  "autoload": {
+    "files": ["oophp-iban.php","php-iban.php"]
+  }
+}
+

+ 76 - 3
htdocs/includes/php-iban/oophp-iban.php

@@ -1,4 +1,5 @@
 <?php
+namespace PHP_IBAN;
 
 # OO wrapper for 'php-iban.php'
 Class IBAN {
@@ -8,9 +9,9 @@ Class IBAN {
   $this->iban = $iban;
  }
 
- public function Verify($iban='') {
-  if($iban!='') { return verify_iban($iban); }
-  return verify_iban($this->iban);
+ public function Verify($iban='',$machine_format_only=false) {
+  if($iban!='') { return verify_iban($iban,$machine_format_only); }
+  return verify_iban($this->iban,$machine_format_only);
   # we could throw exceptions of various types, but why - does it really
   # add anything? possibly some slightly better user feedback potential.
   # however, this can be written by hand by performing individual checks
@@ -19,6 +20,11 @@ Class IBAN {
   # maintenance/documentation cost, i say, therefore: no. no exceptions.
  }
 
+ public function VerifyMachineFormatOnly($iban='') {
+  if($iban!='') { return verify_iban($iban,true); }
+  return verify_iban($this->iban,true);
+ }
+
  public function MistranscriptionSuggestions() {
   return iban_mistranscription_suggestions($this->iban);
  }
@@ -31,6 +37,10 @@ Class IBAN {
   return iban_to_human_format($this->iban);
  }
 
+ public function ObfuscatedFormat() {
+  return iban_to_obfuscated_format($this->iban);
+ }
+
  public function Country($iban='') {
   return iban_get_country_part($this->iban);
  }
@@ -39,6 +49,10 @@ Class IBAN {
   return iban_get_checksum_part($this->iban);
  }
 
+ public function NationalChecksum($iban='') {
+  return iban_get_nationalchecksum_part($this->iban);
+ }
+
  public function BBAN() {
   return iban_get_bban_part($this->iban);
  }
@@ -59,6 +73,18 @@ Class IBAN {
   return iban_checksum_string_replace($this->iban);
  }
 
+ public function FindNationalChecksum() {
+  return iban_find_nationalchecksum($this->iban);
+ }
+
+ public function SetNationalChecksum() {
+  $this->iban = iban_set_nationalchecksum($this->iban);
+ }
+
+ public function VerifyNationalChecksum() {
+  return iban_verify_nationalchecksum($this->iban);
+ }
+
  public function Parts() {
   return iban_get_parts($this->iban);
  }
@@ -88,6 +114,10 @@ Class IBANCountry {
   $this->code = $code;
  }
 
+ public function Code() {
+  return $this->code;
+ }
+
  public function Name() {
   return iban_country_get_country_name($this->code);
  }
@@ -144,14 +174,57 @@ Class IBANCountry {
   return iban_country_get_branchid_stop_offset($this->code);
  }
 
+ public function NationalChecksumStartOffset() {
+  return iban_country_get_nationalchecksum_start_offset($this->code);
+ }
+
+ public function NationalChecksumStopOffset() {
+  return iban_country_get_nationalchecksum_stop_offset($this->code);
+ }
+
  public function RegistryEdition() {
   return iban_country_get_registry_edition($this->code);
  }
 
+ public function SWIFTOfficial() {
+  return iban_country_get_country_swift_official($this->code);
+ }
+
  public function IsSEPA() {
   return iban_country_is_sepa($this->code);
  }
 
+ public function IANA() {
+  return iban_country_get_iana($this->code);
+ }
+
+ public function ISO3166() {
+  return iban_country_get_iso3166($this->code);
+ }
+
+ public function ParentRegistrar() {
+  return iban_country_get_parent_registrar($this->code);
+ }
+
+ public function CurrencyISO4217() {
+  return iban_country_get_currency_iso4217($this->code);
+ }
+
+ public function CentralBankURL() {
+  return iban_country_get_central_bank_url($this->code);
+ }
+
+ public function CentralBankName() {
+  return iban_country_get_central_bank_name($this->code);
+ }
+
+ public function Membership() {
+  return iban_country_get_membership($this->code);
+ }
+
+ public function IsEuMember() {
+  return iban_country_get_is_eu_member($this->code);
+ }
 }
 
 ?>

+ 887 - 37
htdocs/includes/php-iban/php-iban.php

@@ -1,16 +1,18 @@
 <?php
 
-# PHP IBAN - http://code.google.com/p/php-iban - LGPLv3
+# PHP IBAN - http://github.com/globalcitizen/php-iban - LGPLv3
 
 # Global flag by request
 $__disable_iiban_gmp_extension=false;
 
-# Verify an IBAN number.  Returns true or false.
-#  NOTE: Input can be printed 'IIBAN xx xx xx...' or 'IBAN xx xx xx...' or machine 'xxxxx' format.
-function verify_iban($iban) {
+# Verify an IBAN number.
+#  If $machine_format_only, do not tolerate unclean (eg. spaces, dashes, leading 'IBAN ' or 'IIBAN ', lower case) input.
+#  (Otherwise, input can be printed 'IIBAN xx xx xx...' or 'IBAN xx xx xx...' or machine 'xxxxx' format.)
+#  Returns true or false.
+function verify_iban($iban,$machine_format_only=false) {
 
  # First convert to machine format.
- $iban = iban_to_machine_format($iban);
+ if(!$machine_format_only) { $iban = iban_to_machine_format($iban); }
 
  # Get country of IBAN
  $country = iban_get_country_part($iban);
@@ -27,7 +29,7 @@ function verify_iban($iban) {
  # Check regex
  if(preg_match($regex,$iban)) {
   # Regex passed, check checksum
-  if(!iban_verify_checksum($iban)) { 
+  if(!iban_verify_checksum($iban)) {
    return false;
   }
  }
@@ -54,19 +56,40 @@ function iban_to_machine_format($iban) {
 
 # Convert an IBAN to human format. To do this, we
 # simply insert spaces right now, as per the ECBS
-# (European Committee for Banking Standards) 
+# (European Committee for Banking Standards)
 # recommendations available at:
-# http://www.europeanpaymentscouncil.eu/knowledge_bank_download.cfm?file=ECBS%20standard%20implementation%20guidelines%20SIG203V3.2.pdf 
+# http://www.europeanpaymentscouncil.eu/knowledge_bank_download.cfm?file=ECBS%20standard%20implementation%20guidelines%20SIG203V3.2.pdf
 function iban_to_human_format($iban) {
- # First verify validity, or return
- if(!verify_iban($iban)) { return false; }
+ # Remove all spaces
+ $iban = str_replace(' ','',$iban);
  # Add spaces every four characters
- $human_iban = '';
- for($i=0;$i<strlen($iban);$i++) {
-  $human_iban .= substr($iban,$i,1);
-  if(($i>0) && (($i+1)%4==0)) { $human_iban .= ' '; }
+ return wordwrap($iban,4,' ',true);
+}
+
+# Convert an IBAN to obfuscated presentation. To do this, we
+# replace the checksum and all subsequent characters with an
+# asterisk, except for the final four characters, and then
+# return in human format, ie.
+#  HU69107000246667654851100005 -> HU** **** **** **** **** **** 0005
+#
+# We avoid the checksum as it may be used to infer the rest
+# of the IBAN in cases where the country has few valid banks
+# and branches, or other information about the account such
+# as bank, branch, or date issued is known (where a sequential
+# issuance scheme is in use).
+#
+# Note that output of this function should be presented with
+# other information to a user, such as the date last used or
+# the date added to their account, in order to better facilitate
+# unambiguous relative identification.
+function iban_to_obfuscated_format($iban) {
+ $iban = iban_to_machine_format($iban);
+ $tr = substr($iban,0,2);
+ for($i=2;$i<strlen($iban)-4;$i++) {
+  $tr .= '*';
  }
- return $human_iban;
+ $tr .= substr($iban,strlen($iban)-4);
+ return iban_to_human_format($tr);
 }
 
 # Get the country part from an IBAN
@@ -147,11 +170,11 @@ function iban_mod97_10_checksum($numeric_representation) {
  return $checksum;
 }
 
-# Perform MOD97-10 checksum calculation ('Germanic-level effiency' version - thanks Chris!)
+# Perform MOD97-10 checksum calculation ('Germanic-level efficiency' version - thanks Chris!)
 function iban_mod97_10($numeric_representation) {
  global $__disable_iiban_gmp_extension;
  # prefer php5 gmp extension if available
- if(!($__disable_iiban_gmp_extension) && function_exists('gmp_intval')) { return gmp_intval(gmp_mod(gmp_init($numeric_representation, 10),'97')) === 1; }
+ if(!($__disable_iiban_gmp_extension) && function_exists('gmp_intval') && $numeric_representation!='') { return gmp_intval(gmp_mod(gmp_init($numeric_representation, 10),'97')) === 1; }
 
 /*
  # old manual processing (~16x slower)
@@ -180,13 +203,13 @@ function iban_mod97_10($numeric_representation) {
 # Get an array of all the parts from an IBAN
 function iban_get_parts($iban) {
  return array(
-         'country'	=>      iban_get_country_part($iban),
- 	 'checksum'	=>	iban_get_checksum_part($iban),
-	 'bban'		=>	iban_get_bban_part($iban),
- 	 'bank'		=>	iban_get_bank_part($iban),
-	 'country'	=>	iban_get_country_part($iban),
-	 'branch'	=>	iban_get_branch_part($iban),
-	 'account'	=>	iban_get_account_part($iban)
+ 	 'checksum'		=>	iban_get_checksum_part($iban),
+	 'bban'			=>	iban_get_bban_part($iban),
+ 	 'bank'			=>	iban_get_bank_part($iban),
+	 'country'		=>	iban_get_country_part($iban),
+	 'branch'		=>	iban_get_branch_part($iban),
+	 'account'		=>	iban_get_account_part($iban),
+	 'nationalchecksum'	=>	iban_get_nationalchecksum_part($iban)
         );
 }
 
@@ -231,6 +254,18 @@ function iban_get_account_part($iban) {
  return '';
 }
 
+# Get the national checksum part from an IBAN
+function iban_get_nationalchecksum_part($iban) {
+ $iban = iban_to_machine_format($iban);
+ $country = iban_get_country_part($iban);
+ $start = iban_country_get_nationalchecksum_start_offset($country);
+ if($start == '') { return ''; }
+ $stop = iban_country_get_nationalchecksum_stop_offset($country);
+ if($stop == '') { return ''; }
+ $bban = iban_get_bban_part($iban);
+ return substr($bban,$start,($stop-$start+1));
+}
+
 # Get the name of an IBAN country
 function iban_country_get_country_name($iban_country) {
  return _iban_country_get_info($iban_country,'country_name');
@@ -301,33 +336,119 @@ function iban_country_get_branchid_stop_offset($iban_country) {
  return _iban_country_get_info($iban_country,'bban_branchid_stop_offset');
 }
 
+# Get the BBAN (national) checksum start offset for an IBAN country
+#  Returns '' when (often) not present)
+function iban_country_get_nationalchecksum_start_offset($iban_country) {
+ return _iban_country_get_info($iban_country,'bban_checksum_start_offset');
+}
+
+# Get the BBAN (national) checksum stop offset for an IBAN country
+#  Returns '' when (often) not present)
+function iban_country_get_nationalchecksum_stop_offset($iban_country) {
+ return _iban_country_get_info($iban_country,'bban_checksum_stop_offset');
+}
+
 # Get the registry edition for an IBAN country
 function iban_country_get_registry_edition($iban_country) {
  return _iban_country_get_info($iban_country,'registry_edition');
 }
 
+# Is the IBAN country one official issued by SWIFT?
+function iban_country_get_country_swift_official($iban_country) {
+ return _iban_country_get_info($iban_country,'country_swift_official');
+}
+
 # Is the IBAN country a SEPA member?
 function iban_country_is_sepa($iban_country) {
  return _iban_country_get_info($iban_country,'country_sepa');
 }
 
+# Get the IANA code of an IBAN country
+function iban_country_get_iana($iban_country) {
+ return _iban_country_get_info($iban_country,'country_iana');
+}
+
+# Get the ISO3166-1 alpha-2 code of an IBAN country
+function iban_country_get_iso3166($iban_country) {
+ return _iban_country_get_info($iban_country,'country_iso3166');
+}
+
+# Get the parent registrar IBAN country of an IBAN country
+function iban_country_get_parent_registrar($iban_country) {
+ return _iban_country_get_info($iban_country,'parent_registrar');
+}
+
+# Get the official currency of an IBAN country as an ISO4217 alpha code
+# (Note: Returns '' if there is no official currency, eg. for AA (IIBAN))
+function iban_country_get_currency_iso4217($iban_country) {
+ return _iban_country_get_info($iban_country,'currency_iso4217');
+}
+
+# Get the URL of an IBAN country's central bank
+# (Note: Returns '' if there is no central bank. Also, note that
+#        sometimes multiple countries share one central bank)
+function iban_country_get_central_bank_url($iban_country) {
+ $result = _iban_country_get_info($iban_country,'central_bank_url');
+ if($result!='') { $result = 'http://' . $result . '/'; }
+ return $result;
+}
+
+# Get the name of an IBAN country's central bank
+# (Note: Returns '' if there is no central bank. Also, note that
+#        sometimes multiple countries share one central bank)
+function iban_country_get_central_bank_name($iban_country) {
+ return _iban_country_get_info($iban_country,'central_bank_name');
+}
+
 # Get the list of all IBAN countries
 function iban_countries() {
+ _iban_load_registry();
  global $_iban_registry;
  return array_keys($_iban_registry);
 }
 
+# Get the membership of an IBAN country
+# (Note: Possible Values eu_member, efta_member, other_member, non_member)
+function iban_country_get_membership($iban_country) {
+ return _iban_country_get_info($iban_country,'membership');
+}
+
+# Get the membership of an IBAN country
+# (Note: Possible Values eu_member, efta_member, other_member, non_member)
+function iban_country_get_is_eu_member($iban_country) {
+ $membership = _iban_country_get_info($iban_country,'membership');
+ if ($membership === 'eu_member') {
+  $result = true;
+ } else {
+  $result = false;
+ }
+
+ return $result;
+}
+
 # Given an incorrect IBAN, return an array of zero or more checksum-valid
 # suggestions for what the user might have meant, based upon common
 # mistranscriptions.
+#  IDEAS:
+#   - length correction via adding/removing leading zeros from any single component
+#   - overlength correction via dropping final digit(s)
+#   - national checksum algorithm checks (apply same testing methodology, abstract to separate function)
+#   - length correction by removing double digits (xxyzabxybaaz = change aa to a, or xx to x)
+#   - validate bank codes
+#   - utilize format knowledge with regards to alphanumeric applicability in that offset in that national BBAN format
+#   - turkish TL/TK thing
+#   - norway NO gets dropped due to mis-identification with "No." for number (ie. if no country code try prepending NO)
 function iban_mistranscription_suggestions($incorrect_iban) {
- 
+
+ # remove funky characters
+ $incorrect_iban = iban_to_machine_format($incorrect_iban);
+
  # abort on ridiculous length input (but be liberal)
  $length = strlen($incorrect_iban);
- if($length<5 || $length>34) { return array('(length bad)'); }
+ if($length<5 || $length>34) { return array('(supplied iban length insane)'); }
 
  # abort if mistranscriptions data is unable to load
- if(!_iban_load_mistranscriptions()) { return array('(failed to load)'); }
+ if(!_iban_load_mistranscriptions()) { return array('(failed to load mistranscriptions)'); }
 
  # init
  global $_iban_mistranscriptions;
@@ -396,7 +517,6 @@ function iban_mistranscription_suggestions($incorrect_iban) {
 # Load the IBAN registry from disk.
 global $_iban_registry;
 $_iban_registry = array();
-_iban_load_registry();
 function _iban_load_registry() {
  global $_iban_registry;
  # if the registry is not yet loaded, or has been corrupted, reload
@@ -407,14 +527,20 @@ function _iban_load_registry() {
   # loop through lines
   foreach($lines as $line) {
    if($line!='') {
-    # split to fields
-    $old_display_errors_value = ini_get('display_errors');
-    ini_set('display_errors',false);
-    $old_error_reporting_value = ini_get('error_reporting');
-    ini_set('error_reporting',false);
-    list($country,$country_name,$domestic_example,$bban_example,$bban_format_swift,$bban_format_regex,$bban_length,$iban_example,$iban_format_swift,$iban_format_regex,$iban_length,$bban_bankid_start_offset,$bban_bankid_stop_offset,$bban_branchid_start_offset,$bban_branchid_stop_offset,$registry_edition,$country_sepa) = explode('|',$line);
-    ini_set('display_errors',$old_display_errors_value);
-    ini_set('error_reporting',$old_error_reporting_value);
+    # avoid spewing tonnes of PHP warnings under bad PHP configs - see issue #69
+    if(function_exists('ini_set')) {
+     # split to fields
+     $old_display_errors_value = ini_get('display_errors');
+     ini_set('display_errors',false);
+     $old_error_reporting_value = ini_get('error_reporting');
+     ini_set('error_reporting',false);
+    }
+    list($country,$country_name,$domestic_example,$bban_example,$bban_format_swift,$bban_format_regex,$bban_length,$iban_example,$iban_format_swift,$iban_format_regex,$iban_length,$bban_bankid_start_offset,$bban_bankid_stop_offset,$bban_branchid_start_offset,$bban_branchid_stop_offset,$registry_edition,$country_sepa,$country_swift_official,$bban_checksum_start_offset,$bban_checksum_stop_offset,$country_iana,$country_iso3166,$parent_registrar,$currency_iso4217,$central_bank_url,$central_bank_name,$membership) = explode('|',$line);
+    # avoid spewing tonnes of PHP warnings under bad PHP configs - see issue #69
+    if(function_exists('ini_set')) {
+     ini_set('display_errors',$old_display_errors_value);
+     ini_set('error_reporting',$old_error_reporting_value);
+    }
     # assign to registry
     $_iban_registry[$country] = array(
                                 'country'			=>	$country,
@@ -433,7 +559,17 @@ function _iban_load_registry() {
 				'bban_bankid_stop_offset'	=>	$bban_bankid_stop_offset,
 				'bban_branchid_start_offset'	=>	$bban_branchid_start_offset,
 				'bban_branchid_stop_offset'	=>	$bban_branchid_stop_offset,
-				'registry_edition'		=>	$registry_edition
+				'registry_edition'		=>	$registry_edition,
+                'country_swift_official'        =>      $country_swift_official,
+				'bban_checksum_start_offset'	=>	$bban_checksum_start_offset,
+				'bban_checksum_stop_offset'	=>	$bban_checksum_stop_offset,
+				'country_iana'			=>	$country_iana,
+				'country_iso3166'		=>	$country_iso3166,
+				'parent_registrar'		=>	$parent_registrar,
+				'currency_iso4217'		=>	$currency_iso4217,
+				'central_bank_url'		=>	$central_bank_url,
+				'central_bank_name'		=>	$central_bank_name,
+                'membership'            =>  $membership
                                );
    }
   }
@@ -448,6 +584,7 @@ function _iban_get_info($iban,$code) {
 
 # Get information from the IBAN registry by country / code combination
 function _iban_country_get_info($country,$code) {
+ _iban_load_registry();
  global $_iban_registry;
  $country = strtoupper($country);
  $code = strtolower($code);
@@ -483,4 +620,717 @@ function _iban_load_mistranscriptions() {
  return true;
 }
 
+# Find the correct national checksum for an IBAN
+#  (Returns the correct national checksum as a string, or '' if unimplemented for this IBAN's country)
+#  (NOTE: only works for some countries)
+function iban_find_nationalchecksum($iban) {
+ return _iban_nationalchecksum_implementation($iban,'find');
+}
+
+# Verify the correct national checksum for an IBAN
+#  (Returns true or false, or '' if unimplemented for this IBAN's country)
+#  (NOTE: only works for some countries)
+function iban_verify_nationalchecksum($iban) {
+ return _iban_nationalchecksum_implementation($iban,'verify');
+}
+
+# Verify the correct national checksum for an IBAN
+#  (Returns the (possibly) corrected IBAN, or '' if unimplemented for this IBAN's country)
+#  (NOTE: only works for some countries)
+function iban_set_nationalchecksum($iban) {
+ $result = _iban_nationalchecksum_implementation($iban,'set');
+ if($result != '' ) {
+  $result = iban_set_checksum($result); # recalculate IBAN-level checksum
+ }
+ return $result;
+}
+
+# Internal function to overwrite the national checksum portion of an IBAN
+function _iban_nationalchecksum_set($iban,$nationalchecksum) {
+ $country = iban_get_country_part($iban);
+ $start = iban_country_get_nationalchecksum_start_offset($country);
+ if($start == '') { return ''; }
+ $stop = iban_country_get_nationalchecksum_stop_offset($country);
+ if($stop == '') { return ''; }
+ # determine the BBAN
+ $bban = iban_get_bban_part($iban);
+ # alter the BBAN
+ $firstbit = substr($bban,0,$start);  # 'string before the checksum'
+ $lastbit = substr($bban,$stop+1);    # 'string after the checksum'
+ $fixed_bban = $firstbit . $nationalchecksum . $lastbit;
+ # reconstruct the fixed IBAN
+ $fixed_iban = $country . iban_get_checksum_part($iban) . $fixed_bban;
+ return $fixed_iban;
+}
+
+# Currently unused but may be useful for Norway.
+# ISO7064 MOD11-2
+# Adapted from https://gist.github.com/andreCatita/5714353 by Andrew Catita
+function _iso7064_mod112_catita($input) {
+ $p = 0;
+ for ($i = 0; $i < strlen($input); $i++) {
+  $c = $input[$i];
+  $p = 2 * ($p + $c);
+ }
+ $p %= 11;
+ $result = (12 - $p) % 11;
+ if($result == 10) { $result = 'X'; }
+ return $result;
+}
+
+# Currently unused but may be useful for Norway.
+# ISO 7064:1983.MOD 11-2
+# by goseaside@sina.com
+function _iso7064_mod112_goseaside($vString) {
+ $sigma = '';
+ $wi = array(1, 2, 4, 8, 5, 10, 9, 7, 3, 6);
+ $hash_map = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
+ $i_size = strlen($vString);
+ $bModify = '?' == substr($vString, -1);
+ $i_size1 = $bModify ? $i_size : $i_size + 1;
+ for ($i = 1; $i <= $i_size; $i++) {
+  $i1 = $vString[$i - 1] * 1;
+  $w1 = $wi[($i_size1 - $i) % 10];
+  $sigma += ($i1 * $w1) % 11;
+ }
+ if($bModify) return str_replace('?', $hash_map[($sigma % 11)], $vString);
+ else return $hash_map[($sigma % 11)];
+}
+
+# ISO7064 MOD97-10 (Bosnia, etc.)
+# (Credit: Adapted from https://github.com/stvkoch/ISO7064-Mod-97-10/blob/master/ISO7064Mod97_10.php)
+function _iso7064_mod97_10($str) {
+ $ai=1;
+ $ch = ord($str[strlen($str)-1]) - 48;
+ if($ch < 0 || $ch > 9) return false;
+ $check=$ch;
+ for($i=strlen($str)-2;$i>=0;$i--) {
+  $ch = ord($str[$i]) - 48;
+  if ($ch < 0 || $ch > 9) return false;
+  $ai=($ai*10)%97;
+  $check+= ($ai * ((int)$ch));
+ }
+ return (98-($check%97));
+}
+
+# Implement the national checksum for a Belgium (BE) IBAN
+#  (Credit: @gaetan-be)
+function _iban_nationalchecksum_implementation_be($iban,$mode) {
+ if($mode != 'set' && $mode != 'find' && $mode != 'verify') { return ''; } # blank value on return to distinguish from correct execution
+ $nationalchecksum = iban_get_nationalchecksum_part($iban);
+ $account = iban_get_account_part($iban);
+ $account_less_checksum = substr($account,strlen($account)-2);
+ $expected_nationalchecksum = $account_less_checksum % 97;
+ if($mode=='find') {
+  return $expected_nationalchecksum;
+ }
+ elseif($mode=='set') {
+  return _iban_nationalchecksum_set($iban,$expected_nationalchecksum);
+ }
+ elseif($mode=='verify') {
+  return ($nationalchecksum == $expected_nationalchecksum);
+ }
+}
+
+# MOD11 helper function for the Spanish (ES) IBAN national checksum implementation
+#  (Credit: @dem3trio, code lifted from Spanish Wikipedia at https://es.wikipedia.org/wiki/C%C3%B3digo_cuenta_cliente)
+function _iban_nationalchecksum_implementation_es_mod11_helper($numero) {
+ if(strlen($numero)!=10) return "?";
+ $cifras = Array(1,2,4,8,5,10,9,7,3,6);
+ $chequeo=0;
+ for($i=0; $i<10; $i++) {
+  $chequeo += substr($numero,$i,1) * $cifras[$i];
+ }
+ $chequeo = 11 - ($chequeo % 11);
+ if ($chequeo == 11) $chequeo = 0;
+ if ($chequeo == 10) $chequeo = 1;
+ return $chequeo;
+}
+
+# Implement the national checksum for a Spanish (ES) IBAN
+#  (Credit: @dem3trio, adapted from code on Spanish Wikipedia at https://es.wikipedia.org/wiki/C%C3%B3digo_cuenta_cliente)
+function _iban_nationalchecksum_implementation_es($iban,$mode) {
+ if($mode != 'set' && $mode != 'find' && $mode != 'verify') { return ''; } # blank value on return to distinguish from correct execution
+ # extract appropriate substrings
+ $bankprefix = iban_get_bank_part($iban) . iban_get_branch_part($iban);
+ $nationalchecksum = iban_get_nationalchecksum_part($iban);
+ $account = iban_get_account_part($iban);
+ $account_less_checksum = substr($account,2);
+ # first we calculate the initial checksum digit, which is MOD11 of the bank prefix with '00' prepended
+ $expected_nationalchecksum  = _iban_nationalchecksum_implementation_es_mod11_helper("00".$bankprefix);
+ # then we append the second digit, which is MOD11 of the account
+ $expected_nationalchecksum .= _iban_nationalchecksum_implementation_es_mod11_helper($account_less_checksum);
+ if($mode=='find') {
+  return $expected_nationalchecksum;
+ }
+ elseif($mode=='set') {
+  return _iban_nationalchecksum_set($iban,$expected_nationalchecksum);
+ }
+ elseif($mode=='verify') {
+  return ($nationalchecksum == $expected_nationalchecksum);
+ }
+}
+
+# Helper function for the France (FR) BBAN national checksum implementation
+#  (Credit: @gaetan-be)
+function _iban_nationalchecksum_implementation_fr_letters2numbers_helper($bban) {
+ $allNumbers = "";
+ $conversion = array(
+                     "A" => 1, "B" => 2, "C" => 3, "D" => 4, "E" => 5, "F" => 6, "G" => 7, "H" => 8, "I" => 9,
+                     "J" => 1, "K" => 2, "L" => 3, "M" => 4, "N" => 5, "O" => 6, "P" => 7, "Q" => 8, "R" => 9,
+                     "S" => 2, "T" => 3, "U" => 4, "V" => 5, "W" => 6, "X" => 7, "Y" => 8, "Z" => 9
+                    );
+ for ($i=0; $i < strlen($bban); $i++) {
+  if(is_numeric($bban[$i])) {
+   $allNumbers .= $bban[$i];
+  }
+  else {
+   $letter = strtoupper($bban[$i]);
+   if(array_key_exists($letter, $conversion)) {
+    $allNumbers .= $conversion[$letter];
+   }
+   else {
+    return null;
+   }
+  }
+ }
+ return $allNumbers;
+}
+
+# NOTE: Worryingly at least one domestic number found within CF online is
+#       not passing national checksum support. Perhaps banks do not issue
+#       with correct RIB (French-style national checksum) despite using
+#       the legacy format? Perhaps this is a mistranscribed number?
+#        http://www.radiomariacentrafrique.org/virement-bancaire.aspx
+#	  ie. CF19 20001 00001 01401832401 40
+#	The following two numbers work:
+#        http://fondationvoixducoeur.net/fr/pour-contribuer.html
+#	  ie. CF4220002002003712551080145 and CF4220001004113717538890110
+#       Since in the latter case the bank is the same as the former and
+#       the French structure, terminology and 2/3 correct is a fairly high
+#       correlation, we are going to assume that the first error is theirs.
+#
+# Implement the national checksum for a Central African Republic (CF) IBAN
+function _iban_nationalchecksum_implementation_cf($iban,$mode) {
+ return _iban_nationalchecksum_implementation_fr($iban,$mode);
+}
+
+# Implement the national checksum for a Chad (TD) IBAN
+function _iban_nationalchecksum_implementation_td($iban,$mode) {
+ return _iban_nationalchecksum_implementation_fr($iban,$mode);
+}
+
+# Implement the national checksum for a Comoros (KM) IBAN
+function _iban_nationalchecksum_implementation_km($iban,$mode) {
+ return _iban_nationalchecksum_implementation_fr($iban,$mode);
+}
+
+# Implement the national checksum for a Congo (CG) IBAN
+function _iban_nationalchecksum_implementation_cg($iban,$mode) {
+ return _iban_nationalchecksum_implementation_fr($iban,$mode);
+}
+
+# Implement the national checksum for a Djibouti (DJ) IBAN
+function _iban_nationalchecksum_implementation_dj($iban,$mode) {
+ return _iban_nationalchecksum_implementation_fr($iban,$mode);
+}
+
+# Implement the national checksum for an Equitorial Guinea (GQ) IBAN
+function _iban_nationalchecksum_implementation_gq($iban,$mode) {
+ return _iban_nationalchecksum_implementation_fr($iban,$mode);
+}
+
+# Implement the national checksum for a Gabon (GA) IBAN
+function _iban_nationalchecksum_implementation_ga($iban,$mode) {
+ return _iban_nationalchecksum_implementation_fr($iban,$mode);
+}
+
+# Implement the national checksum for a Monaco (MC) IBAN
+#  (Credit: @gaetan-be)
+function _iban_nationalchecksum_implementation_mc($iban,$mode) {
+ return _iban_nationalchecksum_implementation_fr($iban,$mode);
+}
+
+# Implement the national checksum for a France (FR) IBAN
+#  (Credit: @gaetan-be, http://www.credit-card.be/BankAccount/ValidationRules.htm#FR_Validation and
+#           https://docs.oracle.com/cd/E18727_01/doc.121/e13483/T359831T498954.htm)
+function _iban_nationalchecksum_implementation_fr($iban,$mode) {
+ if($mode != 'set' && $mode != 'find' && $mode != 'verify') { return ''; } # blank value on return to distinguish from correct execution
+ # first, extract the BBAN
+ $bban = iban_get_bban_part($iban);
+ # convert to numeric form
+ $bban_numeric_form = _iban_nationalchecksum_implementation_fr_letters2numbers_helper($bban);
+ # if the result was null, something is horribly wrong
+ if(is_null($bban_numeric_form)) { return ''; }
+ # extract other parts
+ $bank = substr($bban_numeric_form,0,5);
+ $branch = substr($bban_numeric_form,5,5);
+ $account = substr($bban_numeric_form,10,11);
+ # actual implementation: mod97( (89 x bank number "Code banque") + (15 x branch code "Code guichet") + (3 x account number "Numéro de compte") )
+ $sum = (89*($bank+0)) + ((15*($branch+0)));
+ $sum += (3*($account+0));
+ $expected_nationalchecksum = 97 - ($sum % 97);
+ if(strlen($expected_nationalchecksum) == 1) { $expected_nationalchecksum = '0' . $expected_nationalchecksum; }
+ # return
+ if($mode=='find') {
+  return $expected_nationalchecksum;
+ }
+ elseif($mode=='set') {
+  return _iban_nationalchecksum_set($iban,$expected_nationalchecksum);
+ }
+ elseif($mode=='verify') {
+  return (iban_get_nationalchecksum_part($iban) == $expected_nationalchecksum);
+ }
+}
+
+# Implement the national checksum for a Norway (NO) IBAN
+#  (NOTE: Built from description at https://docs.oracle.com/cd/E18727_01/doc.121/e13483/T359831T498954.htm, not well tested)
+function _iban_nationalchecksum_implementation_no($iban,$mode) {
+ if($mode != 'set' && $mode != 'find' && $mode != 'verify') { return ''; } # blank value on return to distinguish from correct execution
+ # first, extract the BBAN
+ $bban = iban_get_bban_part($iban);
+ # then, the account
+ $account = iban_get_account_part($iban);
+ # existing checksum
+ $nationalchecksum = iban_get_nationalchecksum_part($iban);
+ # bban less checksum
+ $bban_less_checksum = substr($bban,0,strlen($bban)-strlen($nationalchecksum));
+ # factor table
+ $factors = array(5,4,3,2,7,6,5,4,3,2);
+ # calculate checksum
+ $total = 0;
+ for($i=0;$i<10;$i++) {
+  $total += $bban_less_checksum[$i] * $factors[$i];
+ }
+ $total += $nationalchecksum;
+ # mod11
+ $remainder = $total % 11;
+ # to find the correct check digit, we add the remainder to the current check digit,
+ #  mod10 (ie. rounding at 10, such that 10 = 0, 11 = 1, etc.)
+ $calculated_checksum = ($nationalchecksum + $remainder)%10;
+ if($mode == 'find') {
+  if($remainder == 0) { return $nationalchecksum; }
+  else {
+   return $calculated_checksum;
+  }
+ }
+ elseif($mode == 'set') {
+  return _iban_nationalchecksum_set($iban,$calculated_checksum);
+ }
+ elseif($mode == 'verify') {
+  if($remainder == 0) { return true; }
+  return false;
+ }
+}
+
+# ISO/IEC 7064, MOD 11-2
+# @param $input string Must contain only characters ('0123456789').
+# @output A 1 character string containing '0123456789X',
+#         or '' (empty string) on failure due to bad input.
+# (Credit: php-iso7064 @ https://github.com/globalcitizen/php-iso7064)
+function _iso7064_mod11_2($input) {
+ $input = strtoupper($input); # normalize
+ if(!preg_match('/^[0123456789]+$/',$input)) { return ''; } # bad input
+ $modulus       = 11;
+ $radix         = 2;
+ $output_values = '0123456789X';
+ $p             = 0;
+ for($i=0; $i<strlen($input); $i++) {
+  $val = strpos($output_values,substr($input,$i,1));
+  if($val < 0) { return ''; } # illegal character encountered
+  $p = (($p + $val) * $radix) % $modulus;
+ }
+ $checksum = ($modulus - $p + 1) % $modulus;
+ return substr($output_values,$checksum,1);
+}
+
+# Implement the national checksum systems based on ISO7064 MOD11-2 Algorithm
+function _iban_nationalchecksum_implementation_iso7064_mod11_2($iban,$mode,$drop_at_front=0,$drop_at_end=1) {
+ if($mode != 'set' && $mode != 'find' && $mode != 'verify') { return ''; } # blank value on return to distinguish from correct execution
+ # first, extract the BBAN
+ $bban = iban_get_bban_part($iban);
+ # get the current and computed checksum
+ $nationalchecksum = iban_get_nationalchecksum_part($iban);
+ # drop characters from the front and end of the BBAN as requested
+ $bban_less_checksum = substr($bban,$drop_at_front,strlen($bban)-$drop_at_end);
+ # calculate expected checksum
+ $expected_nationalchecksum = _iso7064_mod11_2($bban_less_checksum);
+ # return
+ if($mode=='find') {
+  return $expected_nationalchecksum;
+ }
+ elseif($mode=='set') {
+  return _iban_nationalchecksum_set($iban,$expected_nationalchecksum);
+ }
+ elseif($mode=='verify') {
+  return (iban_get_nationalchecksum_part($iban) == $expected_nationalchecksum);
+ }
+}
+
+# Implement the national checksum systems based on Damm Algorithm
+function _iban_nationalchecksum_implementation_damm($iban,$mode) {
+ if($mode != 'set' && $mode != 'find' && $mode != 'verify') { return ''; } # blank value on return to distinguish from correct execution
+ # first, extract the BBAN
+ $bban = iban_get_bban_part($iban);
+ # get the current and computed checksum
+ $nationalchecksum = iban_get_nationalchecksum_part($iban);
+ # drop trailing checksum characters
+ $bban_less_checksum = substr($bban,0,strlen($bban)-strlen($nationalchecksum));
+ # calculate expected checksum
+ $expected_nationalchecksum = _damm($bban_less_checksum);
+ # return
+ if($mode=='find') {
+  return $expected_nationalchecksum;
+ }
+ elseif($mode=='set') {
+  return _iban_nationalchecksum_set($iban,$expected_nationalchecksum);
+ }
+ elseif($mode=='verify') {
+  return (iban_get_nationalchecksum_part($iban) == $expected_nationalchecksum);
+ }
+}
+
+# Implement the national checksum systems based on Verhoeff Algorithm
+function _iban_nationalchecksum_implementation_verhoeff($iban,$mode,$strip_length_end,$strip_length_front=0) {
+ if($mode != 'set' && $mode != 'find' && $mode != 'verify') { return ''; } # blank value on return to distinguish from correct execution
+ # first, extract the BBAN
+ $bban = iban_get_bban_part($iban);
+ # if necessary, drop this many leading characters
+ $bban = substr($bban,$strip_length_front);
+ # drop the trailing checksum digit
+ $bban_less_checksum = substr($bban,0,strlen($bban)-$strip_length_end);
+ # get the current and computed checksum
+ $nationalchecksum = iban_get_nationalchecksum_part($iban);
+ $expected_nationalchecksum = _verhoeff($bban_less_checksum);
+ # return
+ if($mode=='find') {
+  return $expected_nationalchecksum;
+ }
+ elseif($mode=='set') {
+  return _iban_nationalchecksum_set($iban,$expected_nationalchecksum);
+ }
+ elseif($mode=='verify') {
+  return (iban_get_nationalchecksum_part($iban) == $expected_nationalchecksum);
+ }
+}
+
+# ISO/IEC 7064, MOD 97-10
+# @param $input string Must contain only characters ('0123456789').
+# @output A 2 character string containing '0123456789',
+#         or '' (empty string) on failure due to bad input.
+# (Credit: php-iso7064 @ https://github.com/globalcitizen/php-iso7064)
+function _iso7064_mod97_10_generated($input) {
+ $input = strtoupper($input); # normalize
+ if(!preg_match('/^[0123456789]+$/',$input)) { return ''; } # bad input
+ $modulus       = 97;
+ $radix         = 10;
+ $output_values = '0123456789';
+ $p             = 0;
+ for($i=0; $i<strlen($input); $i++) {
+  $val = strpos($output_values,substr($input,$i,1));
+  if($val < 0) { return ''; } # illegal character encountered
+  $p = (($p + $val) * $radix) % $modulus;
+ }
+$p = ($p*$radix) % $modulus;
+ $checksum = ($modulus - $p + 1) % $modulus;
+ $second = $checksum % $radix;
+ $first = ($checksum - $second) / $radix;
+ return substr($output_values,$first,1) . substr($output_values,$second,1);
+}
+
+# Implement the national checksum for an Montenegro (ME) IBAN
+#  (NOTE: Reverse engineered)
+function _iban_nationalchecksum_implementation_me($iban,$mode) {
+ return _iban_nationalchecksum_implementation_mod97_10($iban,$mode);
+}
+
+# Implement the national checksum for an Macedonia (MK) IBAN
+#  (NOTE: Reverse engineered)
+function _iban_nationalchecksum_implementation_mk($iban,$mode) {
+ return _iban_nationalchecksum_implementation_mod97_10($iban,$mode);
+}
+
+# Implement the national checksum for an Netherlands (NL) IBAN
+#  This applies to most banks, but not to 'INGB', therefore we
+#  treat it specially here.
+#  (Original code: Validate_NL PEAR class, since extended)
+function _iban_nationalchecksum_implementation_nl($iban,$mode) {
+ if($mode != 'set' && $mode != 'find' && $mode != 'verify') { return ''; } # blank value on return to distinguish from correct execution
+ $bank = iban_get_bank_part($iban);
+ if(strtoupper($bank) == 'INGB') {
+  return '';
+ }
+ $account = iban_get_account_part($iban);
+ $checksum = 0;
+ for ($i = 0; $i < 10; $i++) {
+  $checksum += ((int)$account[$i] * (10 - $i));
+ }
+ $remainder = $checksum % 11;
+ if($mode=='verify') {
+  return ($remainder==0); # we return the result of mod11, if 0 it's good
+ }
+ elseif($mode=='set') {
+  if($remainder==0) {
+   return $iban; # we return as expected if the checksum is ok
+  }
+  return ''; # we return unimplemented if the checksum is bad
+ }
+ elseif($mode=='find') {
+  return ''; # does not make sense for this 0-digit checksum
+ }
+}
+
+# Implement the national checksum for an Portugal (PT) IBAN
+#  (NOTE: Reverse engineered)
+function _iban_nationalchecksum_implementation_pt($iban,$mode) {
+ if($mode != 'set' && $mode != 'find' && $mode != 'verify') { return ''; } # blank value on return to distinguish from correct execution
+ $nationalchecksum = iban_get_nationalchecksum_part($iban);
+ $bban = iban_get_bban_part($iban);
+ $bban_less_checksum = substr($bban,0,strlen($bban)-2);
+ $expected_nationalchecksum = _iso7064_mod97_10_generated($bban_less_checksum);
+ if($mode=='find') {
+  return $expected_nationalchecksum;
+ }
+ elseif($mode=='set') {
+  return _iban_nationalchecksum_set($iban,$expected_nationalchecksum);
+ }
+ elseif($mode=='verify') {
+  return ($nationalchecksum == $expected_nationalchecksum);
+ }
+}
+
+# Implement the national checksum for an Serbia (RS) IBAN
+#  (NOTE: Reverse engineered, including bank 'Narodna banka Srbije' (908) exception. For two
+#         separately published and legitimate looking IBANs from that bank, there appears to
+#         be a +97 offset on the checksum, so we simply ignore all checksums for this bank.)
+function _iban_nationalchecksum_implementation_rs($iban,$mode) {
+ $bank = iban_get_bank_part($iban);
+ if($bank == '908') {
+  return '';
+ }
+ return _iban_nationalchecksum_implementation_mod97_10($iban,$mode);
+}
+
+# Implement the national checksum for an Slovenia (SI) IBAN
+#  Note: It appears that the central bank does not use these
+#        checksums, thus an exception has been added.
+#  (NOTE: Reverse engineered)
+function _iban_nationalchecksum_implementation_si($iban,$mode) {
+ $bank = iban_get_bank_part($iban);
+ # Bank of Slovenia does not use the legacy checksum scheme.
+ #  Accounts in this namespace appear to be the central bank
+ #  accounts for licensed local banks.
+ if($bank == '01') {
+  return '';
+ }
+ return _iban_nationalchecksum_implementation_mod97_10($iban,$mode);
+}
+
+# Implement the national checksum for Slovak Republic (SK) IBAN
+# Source of algorithm: https://www.nbs.sk/_img/Documents/_Legislativa/_Vestnik/OPAT8-09.pdf
+# Account number is currently verified only, it's possible to also add validation for bank code and account number prefix
+function _iban_nationalchecksum_implementation_sk($iban,$mode) {
+ if ($mode !== 'verify') {
+  return '';
+ }
+
+ $account = iban_get_account_part($iban);
+ $weights = array(6, 3, 7, 9, 10, 5, 8, 4, 2, 1);
+
+ $sum = 0;
+ for ($i=0; $i < 10; $i++) {
+  $sum += $account[$i] * $weights[$i];
+ }
+
+ return $sum % 11 === 0;
+}
+
+# Implement the national checksum for MOD97-10 countries
+function _iban_nationalchecksum_implementation_mod97_10($iban,$mode) {
+ if($mode != 'set' && $mode != 'find' && $mode != 'verify') { return ''; } # blank value on return to distinguish from correct execution
+ $nationalchecksum = iban_get_nationalchecksum_part($iban);
+ $bban = iban_get_bban_part($iban);
+ $bban_less_checksum = substr($bban,0,strlen($bban)-2);
+ $expected_nationalchecksum = _iso7064_mod97_10_generated($bban_less_checksum);
+ if($mode=='find') {
+  return $expected_nationalchecksum;
+ }
+ elseif($mode=='set') {
+  return _iban_nationalchecksum_set($iban,$expected_nationalchecksum);
+ }
+ elseif($mode=='verify') {
+  return ($nationalchecksum == $expected_nationalchecksum);
+ }
+}
+
+# Implement the national checksum for an Timor-Lest (TL) IBAN
+#  (NOTE: Reverse engineered, but works on 2 different IBAN from official sources)
+function _iban_nationalchecksum_implementation_tl($iban,$mode) {
+ if($mode != 'set' && $mode != 'find' && $mode != 'verify') { return ''; } # blank value on return to distinguish from correct execution
+ $nationalchecksum = iban_get_nationalchecksum_part($iban);
+ $bban = iban_get_bban_part($iban);
+ $bban_less_checksum = substr($bban,0,strlen($bban)-2);
+ $expected_nationalchecksum = _iso7064_mod97_10_generated($bban_less_checksum);
+ if($mode=='find') {
+  return $expected_nationalchecksum;
+ }
+ elseif($mode=='set') {
+  return _iban_nationalchecksum_set($iban,$expected_nationalchecksum);
+ }
+ elseif($mode=='verify') {
+  return ($nationalchecksum == $expected_nationalchecksum);
+ }
+}
+
+# Luhn Check
+# (Credit: Adapted from @gajus' https://gist.github.com/troelskn/1287893#gistcomment-857491)
+function _luhn($string) {
+ $checksum='';
+ foreach (str_split(strrev((string) $string)) as $i => $d) {
+  $checksum .= $i %2 !== 0 ? $d * 2 : $d;
+ }
+ return array_sum(str_split($checksum)) % 10;
+}
+
+# Verhoeff checksum
+# (Credit: Adapted from Semyon Velichko's code at https://en.wikibooks.org/wiki/Algorithm_Implementation/Checksums/Verhoeff_Algorithm#PHP)
+function _verhoeff($input) {
+ if($input == '' || preg_match('/[^0-9]/',$input)) { return ''; } # reject non-numeric input
+ $d = array(
+       array(0,1,2,3,4,5,6,7,8,9),
+       array(1,2,3,4,0,6,7,8,9,5),
+       array(2,3,4,0,1,7,8,9,5,6),
+       array(3,4,0,1,2,8,9,5,6,7),
+       array(4,0,1,2,3,9,5,6,7,8),
+       array(5,9,8,7,6,0,4,3,2,1),
+       array(6,5,9,8,7,1,0,4,3,2),
+       array(7,6,5,9,8,2,1,0,4,3),
+       array(8,7,6,5,9,3,2,1,0,4),
+       array(9,8,7,6,5,4,3,2,1,0)
+      );
+  $p = array(
+        array(0,1,2,3,4,5,6,7,8,9),
+        array(1,5,7,6,2,8,3,0,9,4),
+        array(5,8,0,3,7,9,6,1,4,2),
+        array(8,9,1,6,0,4,3,5,2,7),
+        array(9,4,5,3,1,2,6,8,7,0),
+        array(4,2,8,6,5,7,3,9,0,1),
+        array(2,7,9,3,8,0,6,4,1,5),
+        array(7,0,4,6,9,1,3,2,5,8)
+       );
+  $inv = array(0,4,3,2,1,5,6,7,8,9);
+  $r = 0;
+  foreach(array_reverse(str_split($input)) as $n => $N) {
+   $r = $d[$r][$p[($n+1)%8][$N]];
+  }
+  return $inv[$r];
+}
+
+# Damm checksum
+# (Credit: https://en.wikibooks.org/wiki/Algorithm_Implementation/Checksums/Damm_Algorithm#PHP)
+function _damm($input) {
+ if($input=='' || preg_match('/[^0-9]/',$input)) { return ''; } # non-numeric input
+ // from http://www.md-software.de/math/DAMM_Quasigruppen.txt
+ $matrix = array(
+                array(0, 3, 1, 7, 5, 9, 8, 6, 4, 2),
+                array(7, 0, 9, 2, 1, 5, 4, 8, 6, 3),
+                array(4, 2, 0, 6, 8, 7, 1, 3, 5, 9),
+                array(1, 7, 5, 0, 9, 8, 3, 4, 2, 6),
+                array(6, 1, 2, 3, 0, 4, 5, 9, 7, 8),
+                array(3, 6, 7, 4, 2, 0, 9, 5, 8, 1),
+                array(5, 8, 6, 9, 7, 2, 0, 1, 3, 4),
+                array(8, 9, 4, 5, 3, 6, 2, 0, 1, 7),
+                array(9, 4, 3, 8, 6, 1, 7, 2, 0, 5),
+                array(2, 5, 8, 1, 4, 3, 6, 7, 9, 0),
+           );
+ $checksum = 0;
+ for ($i=0; $i<strlen($input); $i++) {
+  $character = substr($input,$i,1);
+  $checksum = $matrix[$checksum][$character];
+ }
+ return $checksum;
+}
+
+# Implement the national checksum for an Italian (IT) IBAN
+function _iban_nationalchecksum_implementation_it($iban,$mode) {
+ if($mode != 'set' && $mode != 'find' && $mode != 'verify') { return ''; } # blank value on return to distinguish from correct execution
+ $nationalchecksum = iban_get_nationalchecksum_part($iban);
+ $bban = iban_get_bban_part($iban);
+ $bban_less_checksum = substr($bban,1);
+ $expected_nationalchecksum = _italian($bban_less_checksum);
+ if($mode=='find') {
+  return $expected_nationalchecksum;
+ }
+ elseif($mode=='set') {
+  return _iban_nationalchecksum_set($iban,$expected_nationalchecksum);
+ }
+ elseif($mode=='verify') {
+  return (iban_get_nationalchecksum_part($iban) == $expected_nationalchecksum);
+ }
+}
+
+# Implement the national checksum for a San Marino (SM) IBAN
+function _iban_nationalchecksum_implementation_sm($iban,$mode) {
+  // San Marino adheres to Italian rules.
+  return _iban_nationalchecksum_implementation_it($iban,$mode);
+}
+
+# Italian (and San Marino's) checksum
+# (Credit: Translated by Francesco Zanoni from http://community.visual-basic.it/lucianob/archive/2004/12/26/2464.aspx)
+# (Source: European Commettee of Banking Standards' Register of European Account Numbers (TR201 V3.23 — FEBRUARY 2007),
+#          available at URL http://www.cnb.cz/cs/platebni_styk/iban/download/TR201.pdf)
+function _italian($input)
+{
+  $digits = str_split('0123456789');
+  $letters = str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZ-. ');
+  $lengthOfBbanWithoutChecksum = 22;
+  $divisor = 26;
+  $evenList = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28);
+  $oddList = array(1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20, 11, 3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23, 27, 28, 26);
+
+  // Character value computation
+  $sum = 0;
+
+  for ($k = 0; $k < $lengthOfBbanWithoutChecksum; $k++) {
+
+    $i = array_search($input[$k], $digits);
+    if ($i === false) {
+      $i = array_search($input[$k], $letters);
+    }
+
+    // In case of wrong characters,
+    // an unallowed checksum value is returned.
+    if ($i === false) {
+      return '';
+    }
+
+    $sum += (($k % 2) == 0 ? $oddList[$i] : $evenList[$i]);
+
+  }
+
+  return $letters[$sum % $divisor];
+}
+
+
+# Internal proxy function to access national checksum implementations
+#  $iban = IBAN to work with (length and country must be valid, IBAN checksum and national checksum may be incorrect)
+#  $mode = 'find', 'set', or 'verify'
+#    - In 'find' mode, the correct national checksum for $iban is returned.
+#    - In 'set' mode, a (possibly) modified version of $iban with the national checksum corrected is returned.
+#    - In 'verify' mode, the checksum within $iban is compared to correctly calculated value, and true or false is returned.
+#  If a national checksum algorithm does not exist or remains unimplemented for this country, or the supplied $iban or $mode is invalid, '' is returned.
+#  (NOTE: We cannot collapse 'verify' mode and implement here via simple string comparison between 'find' mode output and the nationalchecksum part,
+#         because some countries have systems which do not map to this approach, for example the Netherlands has no checksum part yet an algorithm exists)
+function _iban_nationalchecksum_implementation($iban,$mode) {
+ if($mode != 'set' && $mode != 'find' && $mode != 'verify') { return ''; } #  blank value on return to distinguish from correct execution
+ $iban = iban_to_machine_format($iban);
+ $country = iban_get_country_part($iban);
+ if(strlen($iban)!=iban_country_get_iban_length($country)) { return ''; }
+ $function_name = '_iban_nationalchecksum_implementation_' . strtolower($country);
+ if(function_exists($function_name)) {
+  return $function_name($iban,$mode);
+ }
+ return '';
+}
+
 ?>

+ 117 - 81
htdocs/includes/php-iban/registry.txt

@@ -1,81 +1,117 @@
-country_code|country_name|domestic_example|bban_example|bban_format_swift|bban_format_regex|bban_length|iban_example|iban_format_swift|iban_format_regex|iban_length|bban_bankid_start_offset|bban_bankid_stop_offset|bban_branchid_start_offset|bban_branchid_stop_offset|registry_edition|country_sepa
-AA|IIBAN (Internet)|0011123Z5678|0011123Z5678|12!a|^[A-Z0-9]{12}$|12|AA120011123Z5678|AA2!n12!a|^AA(\d{2})([A-Z0-9]{12})$|16|0|3|||N/A|0
-AL|Albania|0000000235698741|212110090000000235698741|8!n16!c|^(\d{8})([A-Za-z0-9]{16})$|24|AL47212110090000000235698741|AL2!n8!n16!c|^AL(\d{2})(\d{8})([A-Za-z0-9]{16})$|28|0|2|3|6|2011-06-20|0
-AD|Andorra|2030200359100100|00012030200359100100|4!n4!n12!c|^(\d{4})(\d{4})([A-Za-z0-9]{12})$|20|AD1200012030200359100100|AD2!n4!n4!n12!c|^AD(\d{2})(\d{4})(\d{4})([A-Za-z0-9]{12})$|24|0|3|4|7|2011-06-20|0
-AT|Austria|19043-234573201|1904300234573201|5!n11!n|^(\d{5})(\d{11})$|16|AT611904300234573201|AT2!n5!n11!n|^AT(\d{2})(\d{5})(\d{11})$|20|0|4|||2011-06-20|1
-AX|Aland Islands|123456-785|12345600000785|6!n7!n1!n|^(\d{6})(\d{7})(\d{1})$|14|AX2112345600000785|AX2!n6!n7!n1!n|^AX(\d{2})(\d{6})(\d{7})(\d{1})$|18|0|2|||2013-09-05|1
-AZ|Azerbaijan|NABZ00000000137010001944|NABZ00000000137010001944|4!a20!c|^([A-Z]{4})([A-Za-z0-9]{20})$|24|AZ21NABZ00000000137010001944|AZ2!n4!a20!c|^AZ(\d{2})([A-Z]{4})([A-Za-z0-9]{20})$|28|0|3|||2012-05-29|0
-BH|Bahrain|00001299123456|BMAG00001299123456|4!a14!c|^([A-Z]{4})([A-Za-z0-9]{14})$|22|BH67BMAG00001299123456|BH2!n4!a14!c|^BH(\d{2})([A-Z]{4})([A-Za-z0-9]{14})$|22|0|3|||2012-05-29|0
-BE|Belgium|539-0075470-34|539007547034|3!n7!n2!n|^(\d{3})(\d{7})(\d{2})$|12|BE68539007547034|BE2!n3!n7!n2!n|^BE(\d{2})(\d{3})(\d{7})(\d{2})$|16|0|2|||2011-06-20|1
-BA|Bosnia and Herzegovina|199-044-00012002-79|1990440001200279|3!n3!n8!n2!n|^(\d{3})(\d{3})(\d{8})(\d{2})$|16|BA391290079401028494|BA2!n3!n3!n8!n2!n|^BA(\d{2})(\d{3})(\d{3})(\d{8})(\d{2})$|20|0|2|3|5|2011-06-20|0
-BR|Brazil|0009795493C1|00360305000010009795493P1|8!n5!n10!n1!a1!c|^(\d{8})(\d{5})(\d{10})([A-Z]{1})([A-Za-z0-9]{1})$|25|BR2300360305000010009795493P1BR1800000000141455123924100C2|BR2!n8!n5!n10!n1!a1!c|^BR(\d{2})(\d{8})(\d{5})(\d{10})([A-Z]{1})([A-Za-z0-9]{1})$|29|0|7|8|12|2013-06-20|0
-BG|Bulgaria|BNBG 9661 1020 3456 78|BNBG96611020345678|4!a4!n2!n8!c|^([A-Z]{4})(\d{4})(\d{2})([A-Za-z0-9]{8})$|18|BG80BNBG96611020345678|BG2!n4!a4!n2!n8!c|^BG(\d{2})([A-Z]{4})(\d{4})(\d{2})([A-Za-z0-9]{8})$|22|0|3|4|7|2011-06-20|1
-CR|Costa Rica|1026284066|15202001026284066|3!n14!n|^(\d{3})(\d{14})$|7|CR91202001026284066|CR2!n3!n14!n|^CR(\d{2})(\d{3})(\d{14})$|21|0|2|||2012-05-29|0
-HR|Croatia|1001005-1863000160|10010051863000160|7!n10!n|^(\d{7})(\d{10})$|17|HR1210010051863000160|HR2!n7!n10!n|^HR(\d{2})(\d{7})(\d{10})$|21|0|6|||2011-06-20|1
-CY|Cyprus|1200527600|002001280000001200527600|3!n5!n16!c|^(\d{3})(\d{5})([A-Za-z0-9]{16})$|24|CY17002001280000001200527600|CY2!n3!n5!n16!c|^CY(\d{2})(\d{3})(\d{5})([A-Za-z0-9]{16})$|28|0|2|3|7|2011-06-20|1
-CZ|Czech Republic|19-2000145399/0800|08000000192000145399|4!n6!n10!n|^(\d{4})(\d{6})(\d{10})$|20|CZ6508000000192000145399|CZ2!n4!n6!n10!n|^CZ(\d{2})(\d{4})(\d{6})(\d{10})$|24|0|3|4|9|2011-06-20|1
-DK|Denmark|0040 0440116243, 6460 0001631634, 6471 0001000206|00400440116243, 64600001631634, 64710001000206|4!n9!n1!n|^(\d{4})(\d{9})(\d{1})$|14|DK5000400440116243|DK2!n4!n9!n1!n|^DK(\d{2})(\d{4})(\d{9})(\d{1})$|18|0|3|||2011-06-20|1
-FO|Faroe Islands|0040 0440116243, 6460 0001631634, 6471 0001000206|00400440116243, 64600001631634, 64710001000206|4!n9!n1!n|^(\d{4})(\d{9})(\d{1})$|14|FO2000400440116243|FO2!n4!n9!n1!n|^FO(\d{2})(\d{4})(\d{9})(\d{1})$|18|0|3|||2011-06-20|0
-GL|Greenland|0040 0440116243, 6460 0001631634, 6471 0001000206|00400440116243, 64600001631634, 64710001000206|4!n9!n1!n|^(\d{4})(\d{9})(\d{1})$|14|GL2000400440116243|GL2!n4!n9!n1!n|^GL(\d{2})(\d{4})(\d{9})(\d{1})$|18|0|3|||2011-06-20|0
-DO|Dominican Republic|1212453611324|AGR00000001212453611324|4!c20!n|^([A-Za-z0-9]{4})(\d{20})$|24|DO28BAGR00000001212453611324|DO2!n4!c20!n|^DO(\d{2})([A-Za-z0-9]{4})(\d{20})$|28|0|3|||2011-06-20|0
-EE|Estonia|221020145685|2200221020145685|2!n2!n11!n1!n|^(\d{2})(\d{2})(\d{11})(\d{1})$|16|EE382200221020145685|EE2!n2!n2!n11!n1!n|^EE(\d{2})(\d{2})(\d{2})(\d{11})(\d{1})$|20|0|1|||2011-06-20|1
-FI|Finland|123456-785|12345600000785|6!n7!n1!n|^(\d{6})(\d{7})(\d{1})$|14|FI2112345600000785|FI2!n6!n7!n1!n|^FI(\d{2})(\d{6})(\d{7})(\d{1})$|18|0|2|||2013-08-05|1
-FR|France|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|FR1420041010050500013M02606|FR2!n5!n5!n11!c2!n|^FR(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1
-BL|Saint Barthelemy|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|BL9820041010050500013M02606|BL2!n5!n5!n11!c2!n|^BL(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-02-08|0
-GF|French Guyana|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|GF4120041010050500013M02606|GF2!n5!n5!n11!c2!n|^GF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1
-GP|Guadelope|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|GP1120041010050500013M02606|GP2!n5!n5!n11!c2!n|^GP(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1
-MF|Saint Martin (French Part)|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|MF9820041010050500013M02606|MF2!n5!n5!n11!c2!n|^MF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-02-08|0
-MQ|Martinique|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|MQ5120041010050500013M02606|MQ2!n5!n5!n11!c2!n|^MQ(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1
-RE|Reunion|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|RE4220041010050500013M02606|RE2!n5!n5!n11!c2!n|^RE(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1
-PF|French Polynesia|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|PF5720041010050500013M02606|PF2!n5!n5!n11!c2!n|^PF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|0
-TF|French Southern Territories|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|TF2120041010050500013M02606|TF2!n5!n5!n11!c2!n|^TF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|0
-YT|Mayotte|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|YT3120041010050500013M02606|YT2!n5!n5!n11!c2!n|^YT(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1
-NC|New Caledonia|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|NC8420041010050500013M02606|NC2!n5!n5!n11!c2!n|^NC(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|0
-PM|Saint Pierre et Miquelon|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|PM3620041010050500013M02606|PM2!n5!n5!n11!c2!n|^PM(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1
-WF|Wallis and Futuna Islands|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|WF9120041010050500013M02606|WF2!n5!n5!n11!c2!n|^WF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|0
-GE|Georgia|0000000101904917|NB0000000101904917|2!a16!n|^([A-Z]{2})(\d{16})$|18|GE29NB0000000101904917|GE2!n2!a16!n|^GE(\d{2})([A-Z]{2})(\d{16})$|22|0|1|||2011-06-20|0
-DE|Germany|37040044-532013000|370400440532013000|8!n10!n|^(\d{8})(\d{10})$|18|DE89370400440532013000|DE2!n8!n10!n|^DE(\d{2})(\d{8})(\d{10})$|22|0|7|||2011-06-20|1
-GI|Gibraltar|0000 00007099 453|NWBK000000007099453|4!a15!c|^([A-Z]{4})([A-Za-z0-9]{15})$|19|GI75NWBK000000007099453|GI2!n4!a15!c|^GI(\d{2})([A-Z]{4})([A-Za-z0-9]{15})$|23|0|3|||2011-06-20|1
-GR|Greece|01250000000012300695|01101250000000012300695|3!n4!n16!c|^(\d{3})(\d{4})([A-Za-z0-9]{16})$|23|GR1601101250000000012300695|GR2!n3!n4!n16!c|^GR(\d{2})(\d{3})(\d{4})([A-Za-z0-9]{16})$|27|0|2|3|6|2011-06-20|1
-GT|Guatemala|01020000001210029690|TRAJ01020000001210029690|4!c20!c|^([A-Za-z0-9]{4})([A-Za-z0-9]{20})$|24|GT82TRAJ01020000001210029690|GT2!n4!c20!c|^GT(\d{2})([A-Za-z0-9]{4})([A-Za-z0-9]{20})$|28|0|3|||2012-05-29|0
-HU|Hungary|11773016-11111018-00000000|117730161111101800000000|3!n4!n1!n15!n1!n|^(\d{3})(\d{4})(\d{1})(\d{15})(\d{1})$|24|HU42117730161111101800000000|HU2!n3!n4!n1!n15!n1!n|^HU(\d{2})(\d{3})(\d{4})(\d{1})(\d{15})(\d{1})$|28|0|2|3|6|2011-06-20|1
-IS|Iceland|0159-26-007654-551073-0339|0159260076545510730339|4!n2!n6!n10!n|^(\d{4})(\d{2})(\d{6})(\d{10})$|22|IS140159260076545510730339|IS2!n4!n2!n6!n10!n|^IS(\d{2})(\d{4})(\d{2})(\d{6})(\d{10})$|26|0|3|6|11|2011-06-20|1
-IE|Ireland|93-11-52 12345678|AIBK93115212345678|4!a6!n8!n|^([A-Z]{4})(\d{6})(\d{8})$|18|IE29AIBK93115212345678|IE2!n4!a6!n8!n|^IE(\d{2})([A-Z]{4})(\d{6})(\d{8})$|22|0|3|4|9|2011-06-20|1
-IL|Israel|10-800-99999999|100800000099999000|3!n3!n13!n|^(\d{3})(\d{3})(\d{13})$|19|IL620108000000099999999|IL2!n3!n3!n13!n|^IL(\d{2})(\d{3})(\d{3})(\d{13})$|23|0|2|3|5|2011-06-20|0
-IT|Italy|X 05428 11101 000000123456|X0542811101000000123456|1!a5!n5!n12!c|^([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$|23|IT60X0542811101000000123456|IT2!n1!a5!n5!n12!c|^IT(\d{2})([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$|27|0|5|6|10|2011-06-20|1
-JO|Jordan|1310000302|CBJO0010000000000131000302|4!a4!n18!c|^([A-Z]{4})(\d{4})([A-Za-z0-9]{18})$|26|JO94CBJO0010000000000131000302|JO2!n4!a4!n18!c|^JO(\d{2})([A-Z]{4})(\d{4})([A-Za-z0-9]{18})$|30|0|3|4|7|2014-06-05|0
-KZ|Kazakhstan|KZ86 125K ZT50 0410 0100|125KZT5004100100|3!n13!c|^(\d{3})([A-Za-z0-9]{13})$|16|KZ07|KZ2!n3!n13!c|^KZ(\d{2})(\d{3})([A-Za-z0-9]{13})$||0|2|||2014-06-05|0
-KW|Kuwait|CBKU0000000000001234560101|CBKU0000000000001234560101|4!a22!c|^([A-Z]{4})([A-Za-z0-9]{22})$|26|KW81CBKU0000000000001234560101|KW2!n4!a22!n|^KW(\d{2})([A-Z]{4})(\d{22})$|30|0|3|||2011-06-20|0
-LV|Latvia|BANK 0000 4351 9500 1|BANK0000435195001|4!a13!c|^([A-Z]{4})([A-Za-z0-9]{13})$|17|LV80BANK0000435195001|LV2!n4!a13!c|^LV(\d{2})([A-Z]{4})([A-Za-z0-9]{13})$|21|0|3|||2011-06-20|1
-LB|Lebanon|01 001 901229114|0999 0000 0001 0019 0122 9114|4!n20!c|^(\d{4})([A-Za-z0-9]{20})$|24|LB62099900000001001901229114|LB2!n4!n20!c|^LB(\d{2})(\d{4})([A-Za-z0-9]{20})$|28|0|3|||2011-06-20|0
-LI|Liechtenstein|8810 2324013AA|088100002324013AA|5!n12!c|^(\d{5})([A-Za-z0-9]{12})$|19|LI21088100002324013AA|LI2!n5!n12!c|^LI(\d{2})(\d{5})([A-Za-z0-9]{12})$|21|0|4|||2012-05-29|1
-LT|Lithuania|1000 0111 0100 1000|10000011101001000|5!n11!n|^(\d{5})(\d{11})$|16|LT121000011101001000|LT2!n5!n11!n|^LT(\d{2})(\d{5})(\d{11})$|20|0|4|||2011-06-20|1
-LU|Luxembourg|0019 4006 4475 0000|0019400644750000|3!n13!c|^(\d{3})([A-Za-z0-9]{13})$|16|LU280019400644750000|LU2!n3!n13!c|^LU(\d{2})(\d{3})([A-Za-z0-9]{13})$|20|0|2|||2011-06-20|1
-MK|Macedonia|300 0000000424 25|250120000058984|3!n10!c2!n|^(\d{3})([A-Za-z0-9]{10})(\d{2})$|15|MK07250120000058984|MK2!n3!n10!c2!n|^MK(\d{2})(\d{3})([A-Za-z0-9]{10})(\d{2})$|19|0|2|||2012-05-29|0
-MT|Malta|12345MTLCAST001S|MALT011000012345MTLCAST001S|4!a5!n18!c|^([A-Z]{4})(\d{5})([A-Za-z0-9]{18})$|27|MT84MALT011000012345MTLCAST001S|MT2!n4!a5!n18!c|^MT(\d{2})([A-Z]{4})(\d{5})([A-Za-z0-9]{18})$|31|0|3|4|8|2011-06-20|1
-MR|Mauritania|00020 00101 00001234567 53|00020001010000123456753|5!n5!n11!n2!n|^(\d{5})(\d{5})(\d{11})(\d{2})$|23|MR1300020001010000123456753|MR135!n5!n11!n2!n|^MR13(\d{5})(\d{5})(\d{11})(\d{2})$|27|0|4|5|9|2011-06-20|0
-MU|Mauritius|BOMM 0101 1010 3030 0200 000M UR|BOMM0101101030300200000MUR|4!a2!n2!n12!n3!n3!a|^([A-Z]{4})(\d{2})(\d{2})(\d{12})(\d{3})([A-Z]{3})$|26|MU17BOMM0101101030300200000MUR|MU2!n4!a2!n2!n12!n3!n3!a|^MU(\d{2})([A-Z]{4})(\d{2})(\d{2})(\d{12})(\d{3})([A-Z]{3})$|30|0|5|6|7|2011-06-20|0
-MD|Moldova|00225100013104168|AG000225100013104168|2!c18!c|^([A-Za-z0-9]{2})([A-Za-z0-9]{18})$|20|MD24AG000225100013104168|MD2!n20!c|^MD(\d{2})([A-Za-z0-9]{20})$|24|0|1|||2012-09-09|0
-MC|Monaco|0011111000h|11222 00001 01234567890 30|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|MC5811222000010123456789030|MC2!n5!n5!n11!c2!n|^MC(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|1
-ME|Montenegro|505 0000123456789 51|505000012345678951|3!n13!n2!n|^(\d{3})(\d{13})(\d{2})$|18|ME25505000012345678951|ME2!n3!n13!n2!n|^ME(\d{2})(\d{3})(\d{13})(\d{2})$|22|0|2|||2011-06-20|0
-NL|The Netherlands|041 71 64 300|ABNA0417164300|4!a10!n|^([A-Z]{4})(\d{10})$|14|NL91ABNA0417164300|NL2!n4!a10!n|^NL(\d{2})([A-Z]{4})(\d{10})$|18|0|3|4|3|2013-06-20|1
-NO|Norway|8601 11 17947|86011117947|4!n6!n1!n|^(\d{4})(\d{6})(\d{1})$|11|NO9386011117947|NO2!n4!n6!n1!n|^NO(\d{2})(\d{4})(\d{6})(\d{1})$|15|0|3|||2011-06-20|1
-PK|Pakistan|00260101036360|SCBL0000001123456702|4!a16!c|^([A-Z]{4})([A-Za-z0-9]{16})$|20|PK36SCBL0000001123456702|PK2!n4!a16!c|^PK(\d{2})([A-Z]{4})([A-Za-z0-9]{16})$|24|0|3|||2012-05-29|0
-PL|Poland|61 1090 1014 0000 0712 1981 2874|109010140000071219812874|8!n16!n|^(\d{8})(\d{16})$|24|PL61109010140000071219812874|PL2!n8!n16n|^PL(\d{2})(\d{8})(\d{1,16})$|28|0|7|||2011-06-20|1
-PS|Palestine|400123456702|PALS000000000400123456702|4!a21!c|^([A-Z]{4})([A-Za-z0-9]{21})$|25|PS92PALS000000000400123456702|PS2!n4!a21!c|^PS(\d{2})([A-Z]{4})([A-Za-z0-9]{21})$|29|0|3|||2013-09-05|0
-PT|Portugal|0002.0123.12345678901.54|000201231234567890154|4!n4!n11!n2!n|^(\d{4})(\d{4})(\d{11})(\d{2})$|21|PT50000201231234567890154|PT2!n4!n4!n11!n2!n|^PT(\d{2})(\d{4})(\d{4})(\d{11})(\d{2})$|25|0|3|4|7|2013-09-05|1
-QA|Qatar|QA58DOHB00001234567890ABCDEFG|DOHB00001234567890ABCDEFG|4!a4!n17!c|^([A-Z]{4})(\d{4})([A-Za-z0-9]{17})$|29|QA58DOHB00001234567890ABCDEFG|QA2!n4!a4!n17!c|^QA(\d{2})([A-Z]{4})(\d{4})([A-Za-z0-9]{17})$|29|0|3|4|7|2014-06-05|0
-RO|Romania|AAAA 1B31 0075 9384 0000|AAAA1B31007593840000|4!a16!c|^([A-Z]{4})([A-Za-z0-9]{16})$|20|RO49AAAA1B31007593840000|RO2!n4!a16!c|^RO(\d{2})([A-Z]{4})([A-Za-z0-9]{16})$|24|0|3|||2011-06-20|1
-SM|San Marino|U032 2509 8000 0000 0270 100|U0322509800000000270100|1!a5!n5!n12!c|^([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$|23|SM86U0322509800000000270100|SM2!n1!a5!n5!n12!c|^SM(\d{2})([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$|27|0|5|6|10|2011-06-20|1
-SA|Saudi Arabia|608010167519|80000000608010167519|2!n18!c|^(\d{2})([A-Za-z0-9]{18})$|20|SA0380000000608010167519|SA2!n2!n18!c|^SA(\d{2})(\d{2})([A-Za-z0-9]{18})$|24|0|1|||2012-05-29|0
-RS|Serbia|260-0056010016113-79|260005601001611379|3!n13!n2!n|^(\d{3})(\d{13})(\d{2})$|18|RS35260005601001611379|RS2!n3!n13!n2!n|^RS(\d{2})(\d{3})(\d{13})(\d{2})$|22|0|2|||2011-06-20|0
-SK|Slovak Republic|19-8742637541/1200|12000000198742637541|4!n6!n10!n|^(\d{4})(\d{6})(\d{10})$|20|SK3112000000198742637541|SK2!n4!n6!n10!n|^SK(\d{2})(\d{4})(\d{6})(\d{10})$|24|0|3|4|9|2011-06-20|1
-SI|Slovenia|2633 0001 2039 086|263300012039086|5!n8!n2!n|^(\d{5})(\d{8})(\d{2})$|15|SI56191000000123438|SI2!n5!n8!n2!n|^SI(\d{2})(\d{5})(\d{8})(\d{2})$|19|0|1|2|4|2012-09-09|1
-ES|Spain|2100 0418 45 0200051332|21000418450200051332|4!n4!n1!n1!n10!n|^(\d{4})(\d{4})(\d{1})(\d{1})(\d{10})$|20|ES9121000418450200051332|ES2!n4!n4!n1!n1!n10!n|^ES(\d{2})(\d{4})(\d{4})(\d{1})(\d{1})(\d{10})$|24|0|3|4|7|2013-09-05|1
-SE|Sweden|1234 12 3456 1|5000 0000 0583 9825 7466|3!n16!n1!n|^(\d{3})(\d{16})(\d{1})$|20|SE4550000000058398257466|SE2!n3!n16!n1!n|^SE(\d{2})(\d{3})(\d{16})(\d{1})$|24|0|2|||2011-06-20|1
-CH|Switzerland|762 1162-3852.957|00762011623852957|5!n12!c|^(\d{5})([A-Za-z0-9]{12})$|17|CH9300762011623852957|CH2!n5!n12!c|^CH(\d{2})(\d{5})([A-Za-z0-9]{12})$|21|0|4|||2011-06-20|1
-TN|Tunisia|10 006 0351835984788 31|10006035183598478831|2!n3!n13!n2!n|^(\d{2})(\d{3})(\d{13})(\d{2})$|20|TN5910006035183598478831|TN592!n3!n13!n2!n|^TN59(\d{2})(\d{3})(\d{13})(\d{2})$|24|0|1|2|4|2011-06-20|0
-TR|Turkey|0061 01299 1234567890123456789|0006100519786457841326|5!n1!c16!c|^(\d{5})([A-Za-z0-9]{1})([A-Za-z0-9]{16})$|22|TR330006100519786457841326|TR2!n5!n1!c16!c|^TR(\d{2})(\d{5})([A-Za-z0-9]{1})([A-Za-z0-9]{16})$|26|0|4|||2011-06-20|0
-AE|United Arab Emirates|1234567890123456|0331234567890123456|3!n16!n|^(\d{3})(\d{16})$|19|AE070331234567890123456|AE2!n3!n16!n|^AE(\d{2})(\d{3})(\d{16})$|23|0|2|||2011-06-20|0
-GB|United Kingdom|60-16-13 31926819|NWBK60161331926819|4!a6!n8!n|^([A-Z]{4})(\d{6})(\d{8})$|18|GB29NWBK60161331926819|GB2!n4!a6!n8!n|^GB(\d{2})([A-Z]{4})(\d{6})(\d{8})$|22|0|3|4|9|2011-06-20|1
-VG|British Virgin Islands|00000 12 345 678 901|VPVG0000012345678901|4!a16!n|^([A-Z]{4})(\d{16})$|20|VG96VPVG0000012345678901|VG2!n4!a16!n|^VG(\d{2})([A-Z]{4})(\d{16})$|24|0|3|||2012-05-29|0
+country_code|country_name|domestic_example|bban_example|bban_format_swift|bban_format_regex|bban_length|iban_example|iban_format_swift|iban_format_regex|iban_length|bban_bankid_start_offset|bban_bankid_stop_offset|bban_branchid_start_offset|bban_branchid_stop_offset|registry_edition|country_sepa|swift_official|bban_checksum_start_offset|bban_checksum_stop_offset|country_code_iana|country_code_iso3166_1_alpha2|parent_registrar|currency_iso4217|central_bank_url|central_bank_name|membership
+AL|Albania|0000000235698741|212110090000000235698741|8!n16!c|^(\d{8})([A-Za-z0-9]{16})$|24|AL47212110090000000235698741|AL2!n8!n16!c|^AL(\d{2})(\d{8})([A-Za-z0-9]{16})$|28|0|2|3|6|2011-06-20|0|1|7|7|al|AL||ALL|www.bankofalbania.org|Bank of Albania|non_member
+DZ|Algeria|12341234123412341234|12341234123412341234|20!n|^[0-9]{20}$|20|DZ3512341234123412341234|DZ2!n20!n|^DZ(\d{2})(\d{20})$|24|||||2016-01-22|0|0|||dz|DZ||DZD|www.bank-of-algeria.dz|Bank of Algeria|non_member
+AD|Andorra|2030200359100100|00012030200359100100|4!n4!n12!c|^(\d{4})(\d{4})([A-Za-z0-9]{12})$|20|AD1200012030200359100100|AD2!n4!n4!n12!c|^AD(\d{2})(\d{4})(\d{4})([A-Za-z0-9]{12})$|24|0|3|4|7|2011-06-20|1|1|||ad|AD||EUR|www.inaf.ad|Institut Nacional Andorrà de Finances|other_member
+AO|Angola|123412341234123412341|123412341234123412341|21!n|^[0-9]{21}$|21|AO44123412341234123412341|AO2!n21!n|^AO(\d{2})(\d{21})$|25|||||2016-01-22|0|0|||ao|AO||AOA|www.bna.ao|National Bank of Angola|non_member
+AT|Austria|19043-234573201|1904300234573201|5!n11!n|^(\d{5})(\d{11})$|16|AT611904300234573201|AT2!n5!n11!n|^AT(\d{2})(\d{5})(\d{11})$|20|0|4|||2011-06-20|1|1|||at|AT||EUR|www.oenb.at|Austrian National Bank|eu_member
+AZ|Azerbaijan|NABZ00000000137010001944|NABZ00000000137010001944|4!a20!c|^([A-Z]{4})([A-Za-z0-9]{20})$|24|AZ21NABZ00000000137010001944|AZ2!n4!a20!c|^AZ(\d{2})([A-Z]{4})([A-Za-z0-9]{20})$|28|0|3|||2012-05-29|0|1|||az|AZ||AZN|www.cbar.az|The Central Bank of the Republic of Azerbaijan|non_member
+BH|Bahrain|00001299123456|BMAG00001299123456|4!a14!c|^([A-Z]{4})([A-Za-z0-9]{14})$|18|BH67BMAG00001299123456|BH2!n4!a14!c|^BH(\d{2})([A-Z]{4})([A-Za-z0-9]{14})$|22|0|3|||2012-05-29|0|1|||bh|BH||BHD|www.cbb.gov.bh|Central Bank of Bahrain|non_member
+BE|Belgium|539-0075470-34|539007547034|3!n7!n2!n|^(\d{3})(\d{7})(\d{2})$|12|BE68539007547034|BE2!n3!n7!n2!n|^BE(\d{2})(\d{3})(\d{7})(\d{2})$|16|0|2|||2011-06-20|1|1|10|11|be|BE||EUR|www.nbb.be|National Bank of Belgium|eu_member
+BJ|Benin|A12312341234123412341234|A12312341234123412341234|1!a23!n|^[A-Z]{1}[0-9]{23}$|24|BJ83A12312341234123412341234|BJ2!n1!a23!n|^BJ(\d{2})([A-Z]{1}[0-9]{23})$|28|||||2016-01-22|0|0|||bj|BJ||XOF|www.bceao.int|Central Bank of West African States (BCEAO)|non_member
+BA|Bosnia and Herzegovina|199-044-00012002-79|1990440001200279|3!n3!n8!n2!n|^(\d{3})(\d{3})(\d{8})(\d{2})$|16|BA391290079401028494|BA2!n3!n3!n8!n2!n|^BA(\d{2})(\d{3})(\d{3})(\d{8})(\d{2})$|20|0|2|3|5|2011-06-20|0|1|14|15|ba|BA||BAM|www.cbbh.ba|Central Bank of Bosnia and Herzegovina|non_member
+BR|Brazil|0009795493C1|00360305000010009795493P1|8!n5!n10!n1!a1!c|^(\d{8})(\d{5})(\d{10})([A-Z]{1})([A-Za-z0-9]{1})$|25|BR9700360305000010009795493P1|BR2!n8!n5!n10!n1!a1!c|^BR(\d{2})(\d{8})(\d{5})(\d{10})([A-Z]{1})([A-Za-z0-9]{1})$|29|0|7|8|12|2013-06-20|0|1|||br|BR||BRL|www.bcb.gov.br|Central Bank of Brazil|non_member
+VG|British Virgin Islands|00000 12 345 678 901|VPVG0000012345678901|4!a16!n|^([A-Z]{4})(\d{16})$|20|VG96VPVG0000012345678901|VG2!n4!a16!n|^VG(\d{2})([A-Z]{4})(\d{16})$|24|0|3|||2012-05-29|0|1|||vg|VG||USD|www.bvifsc.vg|The British Virgin Islands Financial Services Commission|non_member
+BG|Bulgaria|BNBG 9661 1020 3456 78|BNBG96611020345678|4!a4!n2!n8!c|^([A-Z]{4})(\d{4})(\d{2})([A-Za-z0-9]{8})$|18|BG80BNBG96611020345678|BG2!n4!a4!n2!n8!c|^BG(\d{2})([A-Z]{4})(\d{4})(\d{2})([A-Za-z0-9]{8})$|22|0|3|4|7|2011-06-20|1|1|||bg|BG||BGN|www.bnb.bg|Bulgarian National Bank|eu_member
+BF|Burkina Faso|12341234123412341234123|12341234123412341234123|23!n|^[0-9]{23}$|23|BF4512341234123412341234123|BF2!n23!n|^BF(\d{2})(\d{23})$|27|||||2016-01-22|0|0|||bf|BF||XOF|www.bceao.int|Central Bank of West African States (BCEAO)|non_member
+BI|Burundi|123412341234|123412341234|12!n|^[0-9]{12}$|12|BI33123412341234|BI2!n12!n|^BI(\d{2})(\d{12})$|16|||||2016-01-22|0|0|||bi|BI||BIF|www.brb.bi|Bank of the Republic of Burundi|non_member
+BY|Belarus|3600 0000 0000 0Z00 AB00|NBRB 3600 0000 0000 0Z00 AB00|4!c4!n16!c|^([A-Za-z0-9]{4})(\d{4})([A-Za-z0-9]{16})$|24|BY13NBRB3600900000002Z00AB00|BY2!n4!c4!n16!c|^BY(\d{2})([A-Za-z0-9]{4})(\d{4})([A-Za-z0-9]{16})$|28|0|3|||2017-08-03|0|1|||by|BY||BYN|www.nbrb.by|National Bank of the Republic of Belarus|non_member
+CM|Cameroon|12341234123412341234123|12341234123412341234123|23!n|^[0-9]{23}$|23|CM1512341234123412341234123|CM2!n23!n|^CM(\d{2})(\d{23})$|27|||||2016-01-22|0|0|||cm|CM||XAF|www.beac.int|Bank of Central African States|non_member
+CV|Cape Verde|12341234123412341|12341234123412341|21!n|^[0-9]{21}$|21|CV05123412341234123412341|CV2!n21!n|^CV(\d{2})(\d{21})$|25|||||2016-01-22|0|0|||cv|CV||CVE|www.bcv.cv|Bank of Cape Verde|non_member
+CF|Central African Republic|0140183240140|20001000010140183240140|5!n5!n11!n2!n|^(\d{5})(\d{5})(\d{11})(\d{2})$|23|CF4220001000010120069700160|CF2!n5!n5!n11!n2!n|^CF(\d{2})(\d{5})(\d{5})(\d{11})(\d{2})$|27|0|4|5|9|2017-08-03|0|0|21|23|cf|CF||XAF|www.beac.int|Bank of Central African States|non_member
+TD|Chad|37102538601 74|60003000203710253860174|5!n5!n11!n2!n|^(\d{5})(\d{5})(\d{11})(\d{2})$|23|TD8960003000203710253860174|TD2!n5!n5!n11!n2!n|^TD(\d{2})(\d{5})(\d{5})(\d{11})(\d{2})$|27|0|4|5|9|2017-08-03|0|0|21|23|cf|CF||XAF|www.beac.int|Bank of Central African States|non_member
+KM|Comoros|00109044001 37|00005000010010904400137|5!n5!n13!n2!n|^(\d{5})(\d{5})(\d{11})(\d{2})$|23|KM4600005000010010904400137|KM2!n5!n5!n13!n2!n|^KM(\d{2})(\d{5})(\d{5})(\d{11})(\d{2})$|27|0|4|5|9|2017-08-03|0|0|21|23|km|KM||LMF|www.banque-comores.km|Banque Centrale des Comores|non_member
+CG|Congo|10134513000|30011000101013451300019|5!n5!n11!n2!n|^(\d{5})(\d{5})(\d{11})(\d{2})$|23|CG3930013020003710721836132|CG2!n5!n5!n11!n2!n|^CG(\d{2})(\d{5})(\d{5})(\d{11})(\d{2})$|27|0|4|5|9|2017-08-01|0|1|21|23|cg|CG||CDF|www.bcc.cd|Central Bank of the Congo|non_member
+CR|Costa Rica|02001026284066|015202001026284066|4!n14!n|^(\d{4})(\d{14})$|18|CR05015202001026284066|CR2!n4!n14!n|^CR(\d{2})(\d{4})(\d{14})$|22|0|3|||2012-05-29|0|1|||cr|CR||CRC|www.bccr.fi.cr|Central Bank of Costa Rica|non_member
+CI|Côte d'Ivoire|A12312341234123412341234|A12312341234123412341234|1!a23!n|^[A-Z]{1}[0-9]{23}$|24|CI77A12312341234123412341234|CI2!n1!a23!n|^CI(\d{2})([A-Z]{1})(\d{23})$|28|||||2016-01-22|0|0|||ci|CI||XOF|www.bceao.int|Central Bank of West African States (BCEAO)|non_member
+HR|Croatia|1001005-1863000160|10010051863000160|7!n10!n|^(\d{7})(\d{10})$|17|HR1210010051863000160|HR2!n7!n10!n|^HR(\d{2})(\d{7})(\d{10})$|21|0|6|||2011-06-20|1|1|||hr|HR||HRK|www.hnb.hr|Croatian National Bank|eu_member
+CY|Cyprus|1200527600|002001280000001200527600|3!n5!n16!c|^(\d{3})(\d{5})([A-Za-z0-9]{16})$|24|CY17002001280000001200527600|CY2!n3!n5!n16!c|^CY(\d{2})(\d{3})(\d{5})([A-Za-z0-9]{16})$|28|0|2|3|7|2011-06-20|1|1|||cy|CY||EUR|www.centralbank.gov.cy|Central Bank of Cyprus|eu_member
+CZ|Czech Republic|19-2000145399/0800|08000000192000145399|4!n6!n10!n|^(\d{4})(\d{6})(\d{10})$|20|CZ6508000000192000145399|CZ2!n4!n6!n10!n|^CZ(\d{2})(\d{4})(\d{6})(\d{10})$|24|0|3|4|9|2011-06-20|1|1|||cz|CZ||CZK|www.cnb.cz|Czech National Bank|eu_member
+DK|Denmark|0040 0440116243, 6460 0001631634, 6471 0001000206|00400440116243, 64600001631634, 64710001000206|4!n9!n1!n|^(\d{4})(\d{9})(\d{1})$|14|DK5000400440116243|DK2!n4!n9!n1!n|^DK(\d{2})(\d{4})(\d{9})(\d{1})$|18|0|3|||2011-06-20|1|1|||dk|DK||DKK|www.nationalbanken.dk|National Bank of Denmark (Danmarks Nationalbank)||eu_member
+FO|Faroe Islands|0040 0440116243, 6460 0001631634, 6471 0001000206|00400440116243, 64600001631634, 64710001000206|4!n9!n1!n|^(\d{4})(\d{9})(\d{1})$|14|FO2000400440116243|FO2!n4!n9!n1!n|^FO(\d{2})(\d{4})(\d{9})(\d{1})$|18|0|3|||2011-06-20|0|1|13|13|fo|FO|DK|DKK|www.nationalbanken.dk|National Bank of Denmark (Danmarks Nationalbank)|non_member
+GL|Greenland|0040 0440116243, 6460 0001631634, 6471 0001000206|00400440116243, 64600001631634, 64710001000206|4!n9!n1!n|^(\d{4})(\d{9})(\d{1})$|14|GL2000400440116243|GL2!n4!n9!n1!n|^GL(\d{2})(\d{4})(\d{9})(\d{1})$|18|0|3|||2011-06-20|0|1|||gl|GL|DK|DKK|www.nationalbanken.dk|National Bank of Denmark (Danmarks Nationalbank)|non_member
+DJ|Djibouti|04099430200 08|10002010010409943020008|5!n5!n13!n2!n|^(\d{5})(\d{5})(\d{11})(\d{2})$|23|DJ2110002010010409943020008|DJ2!n5!n5!n13!n2!n|^DJ(\d{2})(\d{5})(\d{5})(\d{11})(\d{2})$|27|0|4|5|9|2017-08-03|0|0|21|23|dj|DJ||DJF|www.banque-centrale.dj|Central Bank of Djibouti|non_member
+DO|Dominican Republic|1212453611324|AGR00000001212453611324|4!c20!n|^([A-Za-z0-9]{4})(\d{20})$|24|DO28BAGR00000001212453611324|DO2!n4!c20!n|^DO(\d{2})([A-Za-z0-9]{4})(\d{20})$|28|0|3|||2011-06-20|0|1|||do|DO||DOP|www.bancentral.gov.do|Central Bank of the Dominican Republic|non_member
+EG|Egypt|000263180002|0019000500000000263180002|4!n4!n17!n|(\d{4})(\d{4})(\d{17})|25|EG380019000500000000263180002|EG2!n4!n4!n17!n|^EG(\d{2})(\d{4})(\d{4})(\d{17})$|29|0|4|5|9|2020-01-01|0|0|||eg|EG||EGP|www.cbe.org.eg|Central Bank of Egypt|non_member
+SV|El Salvador|00000000000000700025|CENR00000000000000700025|4!a20!n|^([A-Za-z0-9]{4})(\d{20})$|24|SV62CENR00000000000000700025|SV2!n4!a20!n|^SV(\d{2})([A-Za-z0-9]{4})(\d{20})$|28|0|3|||2017-08-03|0|1|||sv|SV||USD|www.bcr.gob.sv|Central Reserve Bank of El Salvador|non_member
+GQ|Equitorial Guinea|37152281901 96|50002001003715228190196|5!n5!n11!n2!n|^(\d{5})(\d{5})(\d{11})(\d{2})$|23|GQ7050002001003715228190196|GQ2!n5!n5!n11!n2!n|^GQ(\d{2})(\d{5})(\d{5})(\d{11})(\d{2})$|27|0|4|5|9|2017-08-03|0|0|21|23|gq|GQ||XAF|www.beac.int|Bank of Central African States|non_member
+EE|Estonia|221020145685|2200221020145685|2!n2!n11!n1!n|^(\d{2})(\d{2})(\d{11})(\d{1})$|16|EE382200221020145685|EE2!n2!n2!n11!n1!n|^EE(\d{2})(\d{2})(\d{2})(\d{11})(\d{1})$|20|0|1|||2011-06-20|1|1|15|15|ee|EE||EUR|www.eestipank.ee|Bank of Estonia|eu_member
+FI|Finland|123456-785|12345600000785|6!n7!n1!n|^(\d{6})(\d{7})(\d{1})$|14|FI2112345600000785|FI2!n6!n7!n1!n|^FI(\d{2})(\d{6})(\d{7})(\d{1})$|18|0|2|||2013-08-05|1|1|13|13|fi|FI||EUR|www.suomenpankki.fi|Bank of Finland|eu_member
+AX|Åland Islands|123456-785|12345600000785|6!n7!n1!n|^(\d{6})(\d{7})(\d{1})$|14|AX2112345600000785|AX2!n6!n7!n1!n|^AX(\d{2})(\d{6})(\d{7})(\d{1})$|18|0|2|||2013-09-05|1|1|||ax|AX|FI|EUR|www.suomenpankki.fi|Bank of Finland|eu_member
+FR|France|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|FR1420041010050500013M02606|FR2!n5!n5!n11!c2!n|^FR(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1|1|21|22|fr|FR||EUR|www.banque-france.fr|Bank of France (Banque de France)|eu_member
+GF|French Guiana|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|GF4120041010050500013M02606|GF2!n5!n5!n11!c2!n|^GF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1|1|21|22|gf|GF|FR|EUR|www.banque-france.fr|Bank of France (Banque de France)|eu_member
+PF|French Polynesia|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|PF5720041010050500013M02606|PF2!n5!n5!n11!c2!n|^PF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|0|1|21|22|pf|PF|FR|XPF|www.ieom.fr|Overseas Issuing Institute (Institut d'émission d'Outre-Mer)|other_member
+TF|French Southern Territories|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|TF2120041010050500013M02606|TF2!n5!n5!n11!c2!n|^TF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|0|1|21|22|tf|TF|FR|EUR|www.banque-france.fr|Bank of France (Banque de France)|other_member
+GP|Guadelope|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|GP1120041010050500013M02606|GP2!n5!n5!n11!c2!n|^GP(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1|1|21|22|gp|GP|FR|EUR|www.banque-france.fr|Bank of France (Banque de France)|eu_member
+MQ|Martinique|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|MQ5120041010050500013M02606|MQ2!n5!n5!n11!c2!n|^MQ(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1|1|21|22|mq|MQ|FR|EUR|www.banque-france.fr|Bank of France (Banque de France)|eu_member
+YT|Mayotte|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|YT3120041010050500013M02606|YT2!n5!n5!n11!c2!n|^YT(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1|1|21|22|yt|YT|FR|EUR|www.banque-france.fr|Bank of France (Banque de France)|eu_member
+NC|New Caledonia|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|NC8420041010050500013M02606|NC2!n5!n5!n11!c2!n|^NC(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|0|1|21|22|nc|NC|FR|XPF|www.ieom.fr|Overseas Issuing Institute (Institut d'émission d'Outre-Mer)|other_member
+RE|Réunion|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|RE4220041010050500013M02606|RE2!n5!n5!n11!c2!n|^RE(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1|1|21|22|re|RE|FR|EUR|www.banque-france.fr|Bank of France (Banque de France)|eu_member
+BL|Saint Barthélemy|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|BL6820041010050500013M02606|BL2!n5!n5!n11!c2!n|^BL(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-02-08|0|1|21|22||BL|FR|EUR|www.banque-france.fr|Bank of France (Banque de France)|other_member
+MF|Saint Martin (French Part)|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|MF8420041010050500013M02606|MF2!n5!n5!n11!c2!n|^MF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-02-08|0|1|21|22||MF|FR|EUR|www.banque-france.fr|Bank of France (Banque de France)|eu_member
+PM|Saint-Pierre and Miquelon|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|PM3620041010050500013M02606|PM2!n5!n5!n11!c2!n|^PM(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2013-08-28|1|1|21|22|pm|PM|FR|EUR|www.banque-france.fr|Bank of France (Banque de France)|other_member
+WF|Wallis and Futuna|20041 01005 0500013M026 06|20041010050500013M02606|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|WF9120041010050500013M02606|WF2!n5!n5!n11!c2!n|^WF(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|0|1|21|22|wf|WF|FR|XPF|www.ieom.fr|Overseas Issuing Institute (Institut d'émission d'Outre-Mer)|other_member
+GA|Gabon|15200001069 63|42001007341520000106963|5!n5!n11!n2!n|^(\d{5})(\d{5})(\d{11})(\d{2})$|23|GA2142001007341520000106963|GA2!n5!n5!n11!n2!n|^GA(\d{2})(\d{5})(\d{5})(\d{11})(\d{2})$|27|0|4|5|9|2017-08-03|0|0|21|23|ga|GA||XAF|www.beac.int|Bank of Central African States|non_member
+GE|Georgia|0000000101904917|NB0000000101904917|2!a16!n|^([A-Z]{2})(\d{16})$|18|GE29NB0000000101904917|GE2!n2!a16!n|^GE(\d{2})([A-Z]{2})(\d{16})$|22|0|1|||2011-06-20|0|1|||ge|GE||GEL|www.nbg.gov.ge|National Bank of Georgia|non_member
+DE|Germany|37040044-532013000|370400440532013000|8!n10!n|^(\d{8})(\d{10})$|18|DE89370400440532013000|DE2!n8!n10!n|^DE(\d{2})(\d{8})(\d{10})$|22|0|7|||2011-06-20|1|1|||de|DE||EUR|www.bundesbank.de|Deutsche Bundesbank|eu_member
+GI|Gibraltar|0000 00007099 453|NWBK000000007099453|4!a15!c|^([A-Z]{4})([A-Za-z0-9]{15})$|19|GI75NWBK000000007099453|GI2!n4!a15!c|^GI(\d{2})([A-Z]{4})([A-Za-z0-9]{15})$|23|0|3|||2011-06-20|1|1|||gi|GI||GIP|www.gibraltar.gov.gi|Government of Gibraltar|other_member
+GR|Greece|01250000000012300695|01101250000000012300695|3!n4!n16!c|^(\d{3})(\d{4})([A-Za-z0-9]{16})$|23|GR1601101250000000012300695|GR2!n3!n4!n16!c|^GR(\d{2})(\d{3})(\d{4})([A-Za-z0-9]{16})$|27|0|2|3|6|2011-06-20|1|1|||gr|GR||EUR|www.nbg.gr|National Bank of Greece|eu_member
+GT|Guatemala|01020000001210029690|TRAJ01020000001210029690|4!c20!c|^([A-Za-z0-9]{4})([A-Za-z0-9]{20})$|24|GT82TRAJ01020000001210029690|GT2!n4!c20!c|^GT(\d{2})([A-Za-z0-9]{4})([A-Za-z0-9]{20})$|28|0|3|||2012-05-29|0|1|||gt|GT||GTQ|www.banguat.gob.gt|Bank of Guatemala|non_member
+GW|Guinea-Bissau|0181800637601|GW1430010181800637601|2!c2!n4!n11!n2!n|^([A-Za-z0-9]{2}\d{2})(\d{4})(\d{11})(\d{2})$|21|GW04GW1430010181800637601|GW2!n2!c2!n4!n11!n2!n|^GW(\d{2})([A-Za-z0-9]{2}\d{2})(\d{4})(\d{11})(\d{2})$|25|0|3|4|7|2017-08-03|0|0|||gw|GW||XOF|www.bceao.int|Central Bank of West African States|non_member
+HN|Honduras|123124|PISA00000000000000123124|4!a20!n|^([A-Za-z]{4})(\d{20})$|24|HN54PISA00000000000000123124|HN2!n4!a20!n|^HN(\d{2})([A-Za-z]{4})(\d{20})$|28|0|3|||2017-08-03|0|0|||hn|HN||HNL|www.bch.hn|Central Bank of Honduras|non_member
+HU|Hungary|11773016-11111018-00000000|117730161111101800000000|3!n4!n1!n15!n1!n|^(\d{3})(\d{4})(\d{1})(\d{15})(\d{1})$|24|HU42117730161111101800000000|HU2!n3!n4!n1!n15!n1!n|^HU(\d{2})(\d{3})(\d{4})(\d{1})(\d{15})(\d{1})$|28|0|2|3|6|2011-06-20|1|1|23|23|hu|HU||HUF|english.mnb.hu|Magyar Nemzeti Bank (Central Bank of Hungary)|eu_member
+IS|Iceland|0159-26-007654-551073-0339|0159260076545510730339|4!n2!n6!n10!n|^(\d{4})(\d{2})(\d{6})(\d{10})$|22|IS140159260076545510730339|IS2!n4!n2!n6!n10!n|^IS(\d{2})(\d{4})(\d{2})(\d{6})(\d{10})$|26|0|3|6|11|2011-06-20|1|1|||is|IS||ISK|www.sedlabanki.is|Central Bank of Iceland|efta_member
+AA|IIBAN (Internet)|0011123Z5678|0011123Z5678|12!a|^[A-Z0-9]{12}$|12|AA110011123Z5678|AA2!n12!a|^AA(\d{2})([A-Z0-9]{12})$|16|0|3||||0|0|||||||||non_member
+IR|Iran|1234123412341234123412|123412341234123412|22!n|^[0-9]{22}$|22|IR081234123412341234123412|IR2!n22!n|^IR(\d{2})(\d{22})$|26|||||2016-01-22|0|0|||ir|IR||IRR|www.cbi.ir|The Central Bank of the Islamic Republic of Iran|non_member
+IQ|Iraq|123456789012|NBIQ850123456789012|4!a3!n12!n|^([A-Za-z]{4})(\d{3})(\d{12})$|19|IQ98NBIQ850123456789012|IQ2!n4!a3!n12!n|^IQ(\d{2})([A-Za-z]{4})(\d{3})(\d{12})$|23|0|3|4|6|2017-08-03|0|1|||iq|IQ||IQD|www.cbi.iq|Central Bank of Iraq|non_member
+IE|Ireland|93-11-52 12345678|AIBK93115212345678|4!a6!n8!n|^([A-Z]{4})(\d{6})(\d{8})$|18|IE29AIBK93115212345678|IE2!n4!a6!n8!n|^IE(\d{2})([A-Z]{4})(\d{6})(\d{8})$|22|0|3|4|9|2011-06-20|1|1|||ie|IE||EUR|www.centralbank.ie|Central Bank and Financial Services Authority of Ireland|eu_member
+IL|Israel|10-800-99999999|010800000099999999|3!n3!n13!n|^(\d{3})(\d{3})(\d{13})$|19|IL620108000000099999999|IL2!n3!n3!n13!n|^IL(\d{2})(\d{3})(\d{3})(\d{13})$|23|0|2|3|5|2011-06-20|0|1|||il|IL||ILS|www.bankisrael.org.il|Bank of Israel|non_member
+IT|Italy|X 05428 11101 000000123456|X0542811101000000123456|1!a5!n5!n12!c|^([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$|23|IT60X0542811101000000123456|IT2!n1!a5!n5!n12!c|^IT(\d{2})([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$|27|1|5|6|10|2011-06-20|1|1|0|0|it|IT||EUR|www.bancaditalia.it|Bank of Italy|eu_member
+JO|Jordan|1310000302|CBJO0010000000000131000302|4!a4!n18!c|^([A-Z]{4})(\d{4})([A-Za-z0-9]{18})$|26|JO94CBJO0010000000000131000302|JO2!n4!a4!n18!c|^JO(\d{2})([A-Z]{4})(\d{4})([A-Za-z0-9]{18})$|30|0|3|4|7|2014-06-05|0|1|||jo|JO||JOD|www.cbj.gov.jo|Central Bank of Jordan|non_member
+KZ|Kazakhstan|KZ86125KZT5004100100|125KZT5004100100|3!n13!c|^(\d{3})([A-Za-z0-9]{13})$|16|KZ86125KZT5004100100|KZ2!n3!n13!c|^KZ(\d{2})(\d{3})([A-Za-z0-9]{13})$|20|0|2|||2014-06-05|0|1|||kz|KZ||KZT|www.nationalbank.kz|National Bank of Kazakhstan|non_member
+XK|Kosovo|1212 0123456789 06|1212012345678906|4!n10!n2!n|^(\d{4})(\d{10})(\d{2})$|16|XK051212012345678906|XK2!n4!n10!n2!n|^XK(\d{2})(\d{4})(\d{10})(\d{2})$|20|0|1|2|3|2016-01-21|0|1||||||EUR|www.bqk-kos.org|Central Bank of the Republic of Kosovo (Banka Qendrore e Kosovës)|non_member
+KW|Kuwait|CBKU0000000000001234560101|CBKU0000000000001234560101|4!a22!c|^([A-Z]{4})([A-Za-z0-9]{22})$|26|KW81CBKU0000000000001234560101|KW2!n4!a22!c|^KW(\d{2})([A-Z]{4})([A-Za-z0-9]{22})$|30|0|3|||2016-01-21|0|1|||kw|KW||KWD|www.cbk.gov.kw|Central Bank of Kuwait|non_member
+LV|Latvia|BANK 0000 4351 9500 1|BANK0000435195001|4!a13!c|^([A-Z]{4})([A-Za-z0-9]{13})$|17|LV80BANK0000435195001|LV2!n4!a13!c|^LV(\d{2})([A-Z]{4})([A-Za-z0-9]{13})$|21|0|3|||2011-06-20|1|1|||lv|LV||EUR|www.bank.lv/lat/main/all|Bank of Latvia|eu_member
+LB|Lebanon|01 001 901229114|0999 0000 0001 0019 0122 9114|4!n20!c|^(\d{4})([A-Za-z0-9]{20})$|24|LB62099900000001001901229114|LB2!n4!n20!c|^LB(\d{2})(\d{4})([A-Za-z0-9]{20})$|28|0|3|||2011-06-20|0|1|||lb|LB||LBP|www.bdl.gov.lb|Central Bank of Lebanon|non_member
+LI|Liechtenstein|8810 2324013AA|088100002324013AA|5!n12!c|^(\d{5})([A-Za-z0-9]{12})$|17|LI21088100002324013AA|LI2!n5!n12!c|^LI(\d{2})(\d{5})([A-Za-z0-9]{12})$|21|0|4|||2012-05-29|1|1|||li|LI||CHF|www.llb.li|National Bank of Liechtenstein (Liechtensteinische Landesbank)|efta_member
+LT|Lithuania|1000 0111 0100 1000|10000011101001000|5!n11!n|^(\d{5})(\d{11})$|16|LT121000011101001000|LT2!n5!n11!n|^LT(\d{2})(\d{5})(\d{11})$|20|0|4|||2011-06-20|1|1|||lt|LT||EUR|www.lb.lt|Bank of Lithuania|eu_member
+LU|Luxembourg|0019 4006 4475 0000|0019400644750000|3!n13!c|^(\d{3})([A-Za-z0-9]{13})$|16|LU280019400644750000|LU2!n3!n13!c|^LU(\d{2})(\d{3})([A-Za-z0-9]{13})$|20|0|2|||2011-06-20|1|1|14|15|lu|LU||EUR|www.bcl.lu|Central Bank of Luxembourg|eu_member
+MK|Macedonia|300 0000000424 25|250120000058984|3!n10!c2!n|^(\d{3})([A-Za-z0-9]{10})(\d{2})$|15|MK07250120000058984|MK2!n3!n10!c2!n|^MK(\d{2})(\d{3})([A-Za-z0-9]{10})(\d{2})$|19|0|2|||2012-05-29|0|1|13|14|mk|MK||MKD|www.nbrm.mk|National Bank of the Republic of Macedonia|non_member
+MG|Madagascar|12341234123412341234123|12341234123412341234123|23!n|^[0-9]{23}$|23|MG4012341234123412341234123|MG2!n23!n|^MG(\d{2})(\d{23})$|27|||||2016-01-22|0|0|||mg|MG||MGA|www.banque-centrale.mg|Central Bank of Madagascar|non_member
+ML|Mali|A12312341234123412341234|A12312341234123412341234|1!a23!n|^[A-Z]{1}[0-9]{23}$|24|ML75A12312341234123412341234|ML2!n1!a23!n|^ML(\d{2})([A-Z]{1})(\d{23})$|28|||||2016-01-22|0|0|||ml|ML||XOF|www.bceao.int|Central Bank of West African States (BCEAO)|non_member
+MT|Malta|12345MTLCAST001S|MALT011000012345MTLCAST001S|4!a5!n18!c|^([A-Z]{4})(\d{5})([A-Za-z0-9]{18})$|27|MT84MALT011000012345MTLCAST001S|MT2!n4!a5!n18!c|^MT(\d{2})([A-Z]{4})(\d{5})([A-Za-z0-9]{18})$|31|0|3|4|8|2011-06-20|1|1|||mt|MT||EUR|www.centralbankmalta.org|Central Bank of Malta|eu_member
+MR|Mauritania|00020 00101 00001234567 53|00020001010000123456753|5!n5!n11!n2!n|^(\d{5})(\d{5})(\d{11})(\d{2})$|23|MR1300020001010000123456753|MR2!n5!n5!n11!n2!n|^MR(\d{2})(\d{5})(\d{5})(\d{11})(\d{2})$|27|0|4|5|9|2016-06-11|0|1|21|22|mr|MR||MRO|www.bcm.mr|Central Bank of Mauritania|non_member
+MU|Mauritius|BOMM 0101 1010 3030 0200 000M UR|BOMM0101101030300200000MUR|4!a2!n2!n12!n3!n3!a|^([A-Z]{4})(\d{2})(\d{2})(\d{12})(\d{3})([A-Z]{3})$|26|MU17BOMM0101101030300200000MUR|MU2!n4!a2!n2!n12!n3!n3!a|^MU(\d{2})([A-Z]{4})(\d{2})(\d{2})(\d{12})(\d{3})([A-Z]{3})$|30|0|5|6|7|2011-06-20|0|1|||mu|MU||MUR|www.bom.mu|Bank of Mauritius|non_member
+MD|Moldova|00225100013104168|AG000225100013104168|2!c18!c|^([A-Za-z0-9]{2})([A-Za-z0-9]{18})$|20|MD24AG000225100013104168|MD2!n2!c18!c|^MD(\d{2})([A-Za-z0-9]{20})$|24|0|1|||2012-09-09|0|1|||md|MD||MDL|www.bnm.org|National Bank of Moldova|non_member
+MC|Monaco|0011111000h|11222 00001 01234567890 30|5!n5!n11!c2!n|^(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|23|MC5811222000010123456789030|MC2!n5!n5!n11!c2!n|^MC(\d{2})(\d{5})(\d{5})([A-Za-z0-9]{11})(\d{2})$|27|0|4|5|9|2011-06-20|1|1|21|22|mc|MC||EUR|||other_member
+ME|Montenegro|505 0000123456789 51|505000012345678951|3!n13!n2!n|^(\d{3})(\d{13})(\d{2})$|18|ME25505000012345678951|ME2!n3!n13!n2!n|^ME(\d{2})(\d{3})(\d{13})(\d{2})$|22|0|2|||2011-06-20|0|1|16|17|me|ME||EUR|www.cb-mn.org|Central Bank of Montenegro|non_member
+MA|Morocco|00012050005349 21|011519000001205000534921|3!n5!n14!n2!n|^(\d{3})(\d{5})(\d{14})(\d{2})$|26|MA64011519000001205000534921|MA2!n3!n5!n14!n2!n|^MA(\d{2})(\d{3})(\d{5})(\d{14})(\d{2})$|28|0|2|3|7|2017-08-03|0|0|22|24|ma|MA||MAD|www.bkam.ma|Bank Al-Maghrib|non_member
+MZ|Mozambique|12341234123412341|12341234123412341|21!n|^[0-9]{21}$|21|MZ97123412341234123412341|MZ2!n21!n|^MZ(\d{2})(\d{21})$|25|||||2016-01-22|0|0|||mz|MZ||MZN|www.bancomoc.mz|Bank of Mozambique|non_member
+NL|Netherlands|041 71 64 300|ABNA0417164300|4!a10!n|^([A-Z]{4})(\d{10})$|14|NL91ABNA0417164300|NL2!n4!a10!n|^NL(\d{2})([A-Z]{4})(\d{10})$|18|0|3|4|3|2013-06-20|1|1|||nl|NL||EUR|www.dnb.nl|Netherlands Bank|eu_member
+NI|Nicaragua|3123123|BAMC000000000000000003123123|28!n|^([A-Za-z]{4})(\d{24})$|28|NI92BAMC000000000000000003123123|NI2!n4!a24!n|^NI(\d{2})([A-Za-z]{4})(\d{24})$|32|0|3|||2017-08-03|0|0|||ni|NI||NIO|www.bcn.gob.ni|Central Bank of Nicaragua|non_member
+NE|Niger|01303050002 68|NE0380100100130305000268|2!a3!n5!n12!n2!n|^([A-Za-z]{2}\d{3})(\d{5})(\d{12})(\d{2})$|23|NE58NE0380100100130305000268|NE2!n2!a3!n5!n12!n2!n|^NE(\d{2})([A-Za-z]{2}\d{3})(\d{5})(\d{12})(\d{2})$|28|0|4|5|9|2017-08-03|0|0|22|23|ne|NE||XOF|www.bceao.int|Central Bank of West African States (BCEAO)|non_member
+NO|Norway|8601 11 17947|86011117947|4!n6!n1!n|^(\d{4})(\d{6})(\d{1})$|11|NO9386011117947|NO2!n4!n6!n1!n|^NO(\d{2})(\d{4})(\d{6})(\d{1})$|15|0|3|||2011-06-20|1|1|10|10|no|NO||NOK|www.norges-bank.no|Central Bank of Norway (Norges Bank)|efta_member
+PK|Pakistan|00260101036360|SCBL0000001123456702|4!a16!c|^([A-Z]{4})([A-Za-z0-9]{16})$|20|PK36SCBL0000001123456702|PK2!n4!a16!c|^PK(\d{2})([A-Z]{4})([A-Za-z0-9]{16})$|24|0|3|||2012-05-29|0|1|||pk|PK||PKR|www.sbp.org.pk|State Bank of Pakistan|non_member
+PS|Palestine|400123456702|PALS000000000400123456702|4!a21!c|^([A-Z]{4})([A-Za-z0-9]{21})$|25|PS92PALS000000000400123456702|PS2!n4!a21!c|^PS(\d{2})([A-Z]{4})([A-Za-z0-9]{21})$|29|0|3|||2013-09-05|0|1|||ps|PS||ILS|www.pma.ps|Palestine Monetary Authority|non_member
+PL|Poland|61 1090 1014 0000 0712 1981 2874|109010140000071219812874|8!n16!n|^(\d{8})(\d{16})$|24|PL61109010140000071219812874|PL2!n8!n16!n|^PL(\d{2})(\d{8})(\d{16})$|28|0|7|||2011-06-20|1|1|7|7|pl|PL||PLN|www.nbp.pl|National Bank of Poland|eu_member
+PT|Portugal|0002.0123.12345678901.54|000201231234567890154|4!n4!n11!n2!n|^(\d{4})(\d{4})(\d{11})(\d{2})$|21|PT50000201231234567890154|PT2!n4!n4!n11!n2!n|^PT(\d{2})(\d{4})(\d{4})(\d{11})(\d{2})$|25|0|3|4|7|2013-09-05|1|1|19|20|pt|PT||EUR|www.bportugal.pt|Bank of Portugal|eu_member
+QA|Qatar|QA58DOHB00001234567890ABCDEFG|DOHB00001234567890ABCDEFG|4!a4!n17!c|^([A-Z]{4})(\d{4})([A-Za-z0-9]{17})$|25|QA58DOHB00001234567890ABCDEFG|QA2!n4!a4!n17!c|^QA(\d{2})([A-Z]{4})(\d{4})([A-Za-z0-9]{17})$|29|0|3|4|7|2014-06-05|0|1|||qa|QA||QAR|www.qcb.gov.qa|Qatar Central Bank|non_member
+RO|Romania|AAAA 1B31 0075 9384 0000|AAAA1B31007593840000|4!a16!c|^([A-Z]{4})([A-Za-z0-9]{16})$|20|RO49AAAA1B31007593840000|RO2!n4!a16!c|^RO(\d{2})([A-Z]{4})([A-Za-z0-9]{16})$|24|0|3|||2011-06-20|1|1|||ro|RO||RON|www.bnro.ro|National Bank of Romania|eu_member
+LC|Saint Lucia|0001 0001 0012 0012 0002 3015|HEMM000100010012001200023015|4!a24!c|^([A-Z]{4})([A-Za-z0-9]{24})$|28|LC55HEMM000100010012001200023015|LC2!n4!a24!c|^LC(\d{2})([A-Z]{4})([A-Za-z0-9]{24})$|32|0|3|||2016-04-15|0|1|||lc|LC||XCD|www.eccb-centralbank.org|Eastern Caribbean Central Bank|non_member
+SM|San Marino|U032 2509 8000 0000 0270 100|U0322509800000000270100|1!a5!n5!n12!c|^([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$|23|SM86U0322509800000000270100|SM2!n1!a5!n5!n12!c|^SM(\d{2})([A-Z]{1})(\d{5})(\d{5})([A-Za-z0-9]{12})$|27|1|5|6|10|2011-06-20|1|1|0|0|sm|SM||EUR|www.bcsm.sm|Central Bank of the Republic of San Marino|other_member
+ST|São Tomé and Príncipe|518453101|0001000100518453101|8!n11!n2!n|^(\d{8})(\d{11})(\d{2})$|21|ST68000100010051845310112|ST2!n8!n11!n2!n|^ST(\d{2})(\d{8})(\d{11})(\d{2})$|25|0|3|4|7|2016-01-21|0|1|||st|ST||STD|www.bcstp.st|Central Bank of São Tomé and Príncipe|non_member
+SA|Saudi Arabia|608010167519|80000000608010167519|2!n18!c|^(\d{2})([A-Za-z0-9]{18})$|20|SA0380000000608010167519|SA2!n2!n18!c|^SA(\d{2})(\d{2})([A-Za-z0-9]{18})$|24|0|1|||2012-05-29|0|1|||sa|SA||SAR|www.sama.gov.sa|Saudi Arabian Monetary Agency|non_member
+SN|Senegal|A12312341234123412341234|A12312341234123412341234|1!a23!n|^[A-Z]{1}[0-9]{23}$|24|SN15A12312341234123412341234|SN2!n1!a23!n|^SN(\d{2})([A-Z]{1})(\d{23})$|28|||||2016-01-22|0|0|||sn|SN||XOF|www.bceao.int|Central Bank of West African States (BCEAO)|non_member
+RS|Serbia|260-0056010016113-79|260005601001611379|3!n13!n2!n|^(\d{3})(\d{13})(\d{2})$|18|RS35260005601001611379|RS2!n3!n13!n2!n|^RS(\d{2})(\d{3})(\d{13})(\d{2})$|22|0|2|||2011-06-20|0|1|16|17|rs|RS||RSD|www.nbs.rs|National Bank of Serbia|non_member
+SC|Seychelles|0000000000001497|SSCB11010000000000001497USD|4!a2!n2!n16!n3!a|^([A-Z]{4})(\d{2})(\d{2})(\d{16})([A-Z]{3})$|27|SC18SSCB11010000000000001497USD|SC2!n4!a2!n2!n16!n3!a|^SC(\d{2})([A-Z]{4})(\d{2})(\d{2})(\d{16})([A-Z]{3})$|31|0|3|4|7|2020-01-01|0|1|||sc|SC||SCR|www.cbs.sc|Central Bank of Seychelles|non_member
+SK|Slovakia|19-8742637541/1200|12000000198742637541|4!n6!n10!n|^(\d{4})(\d{6})(\d{10})$|20|SK3112000000198742637541|SK2!n4!n6!n10!n|^SK(\d{2})(\d{4})(\d{6})(\d{10})$|24|0|3|4|9|2011-06-20|1|1|19|19|sk|SK||EUR|www.nbs.sk|National Bank of Slovakia|eu_member
+SI|Slovenia|2633 0001 2039 086|263300012039086|5!n8!n2!n|^(\d{5})(\d{8})(\d{2})$|15|SI56191000000123438|SI2!n5!n8!n2!n|^SI(\d{2})(\d{5})(\d{8})(\d{2})$|19|0|1|2|4|2012-09-09|1|1|13|14|si|SI||EUR|www.bsi.si|Bank of Slovenia|eu_member
+ES|Spain|2100 0418 45 0200051332|21000418450200051332|4!n4!n1!n1!n10!n|^(\d{4})(\d{4})(\d{1})(\d{1})(\d{10})$|20|ES9121000418450200051332|ES2!n4!n4!n1!n1!n10!n|^ES(\d{2})(\d{4})(\d{4})(\d{1})(\d{1})(\d{10})$|24|0|3|4|7|2013-09-05|1|1|8|9|es|ES||EUR|www.bde.es|Bank of Spain|eu_member
+SE|Sweden|1234 12 3456 1|5000 0000 0583 9825 7466|3!n16!n1!n|^(\d{3})(\d{16})(\d{1})$|20|SE4550000000058398257466|SE2!n3!n16!n1!n|^SE(\d{2})(\d{3})(\d{16})(\d{1})$|24|0|2|||2011-06-20|1|1|19|19|se|SE||SEK|www.riksbank.com|Bank of Sweden (Sveriges Riksbank)|eu_member
+CH|Switzerland|762 1162-3852.957|00762011623852957|5!n12!c|^(\d{5})([A-Za-z0-9]{12})$|17|CH9300762011623852957|CH2!n5!n12!c|^CH(\d{2})(\d{5})([A-Za-z0-9]{12})$|21|0|4|||2011-06-20|1|1|||ch|CH||CHF|www.snb.ch|Swiss National Bank|efta_member
+TL|Timor-Leste|008 00123456789101 57|0080012345678910157|3!n 14!n 2!n|^(\d{3})(\d{14})(\d{2})$|19|TL380080012345678910157|TL2!n3!n14!n2!n|^TL(\d{2})(\d{3})(\d{14})(\d{2})$|23|0|3|4|6|2016-01-21|0|1|17|18|tl|TL||USD|www.bancocentral.tl|Central Bank of Timor-Leste (Banco Central de Timor-Leste)|non_member
+TG|Togo|43103465004000 70|TG0090604310346500400070|2!a3!n5!n12!n2!n|^([A-Za-z]{2}\d{3})(\d{5})(\d{12})(\d{2})$|26|TG53TG0090604310346500400070|TG2!n2!a3!n5!n12!n2!n|^TG(\d{2})([A-Za-z]{2}\d{3})(\d{5})(\d{12})(\d{2})$|28|0|4|5|9|2017-08-03|0|0|22|24|tg|TG||XOF|www.bceao.int|Central Bank of West African States (BCEAO)|non_member
+TN|Tunisia|10 006 0351835984788 31|10006035183598478831|2!n3!n13!n2!n|^(\d{2})(\d{3})(\d{13})(\d{2})$|20|TN5910006035183598478831|TN2!n2!n3!n13!n2!n|^TN(\d{2})(\d{2})(\d{3})(\d{13})(\d{2})$|24|0|1|2|4|2011-06-20|0|1|18|19|tn|TN||TND|www.bct.gov.tn|Central Bank of Tunisia|non_member
+TR|Turkey|TR33 0006 1005 1978 6457 8413 26|0006100519786457841326|5!n1!n16!c|^(\d{5})(\d{1})([A-Za-z0-9]{16})$|22|TR330006100519786457841326|TR2!n5!n1!n16!c|^TR(\d{2})(\d{5})(\d{1})([A-Za-z0-9]{16})$|26|0|4|||2016-01-21|0|1|||tr|TR||TRY|www.tcmb.gov.tr|Central Bank of the Republic of Turkey|non_member
+UA|Ukraine|3996220000026007233566001|3996220000026007233566001|6!n19!c|^[0-9]{6}[A-Za-z0-9]{19}$|25|UA213996220000026007233566001|UA2!n6!n19!c|^UA(\d{2})(\d{6})([A-Za-z0-9]{19})$|29|0|5|||2016-01-22|0|0|||ua|UA||UAH|www.bank.gov.ua|National Bank of Ukraine|non_member
+AE|United Arab Emirates|1234567890123456|0331234567890123456|3!n16!n|^(\d{3})(\d{16})$|19|AE070331234567890123456|AE2!n3!n16!n|^AE(\d{2})(\d{3})(\d{16})$|23|0|2|||2011-06-20|0|1|||ae|AE||AED|www.centralbank.ae|Central Bank of the United Arab Emirates|non_member
+GB|United Kingdom|60-16-13 31926819|NWBK60161331926819|4!a6!n8!n|^([A-Z]{4})(\d{6})(\d{8})$|18|GB29NWBK60161331926819|GB2!n4!a6!n8!n|^GB(\d{2})([A-Z]{4})(\d{6})(\d{8})$|22|0|3|4|9|2011-06-20|1|1|||uk|GB||GBP|www.bankofengland.co.uk|Bank of England|other_member

+ 2 - 2
htdocs/societe/paymentmodes.php

@@ -1624,7 +1624,7 @@ if ($socid && $action == 'edit' && $permissiontoaddupdatepaymentinformation) {
 	print '</table>';
 	print '</div>';
 
-	if ($conf->prelevement->enabled) {
+	if (isModEnabled('prelevement')) {
 		print '<br>';
 
 		print '<div class="div-table-responsive-no-min">';
@@ -1785,7 +1785,7 @@ if ($socid && $action == 'create' && $permissiontoaddupdatepaymentinformation) {
 
 	print '</table>';
 
-	if ($conf->prelevement->enabled) {
+	if (isModEnabled('prelevement')) {
 		print '<br>';
 
 		print '<table class="border centpercent">';

+ 14 - 0
test/phpunit/BankAccountTest.php

@@ -28,6 +28,7 @@ global $conf,$user,$langs,$db;
 //require_once 'PHPUnit/Autoload.php';
 require_once dirname(__FILE__).'/../../htdocs/master.inc.php';
 require_once dirname(__FILE__).'/../../htdocs/compta/bank/class/account.class.php';
+require_once dirname(__FILE__).'/../../htdocs/core/lib/bank.lib.php';
 
 if (empty($user->id)) {
 	print "Load permissions for admin user nb 1\n";
@@ -205,6 +206,19 @@ class BankAccountTest extends PHPUnit\Framework\TestCase
 		//print __METHOD__." localobject->date_creation=".$localobject->date_creation."\n";
 		$this->assertEquals(1, $result);
 
+		// Test checkIbanForAccount for FR account
+		$result = checkIbanForAccount($localobject);
+		print __METHOD__." checkIbanForAccount(".$localobject->iban.") = ".$result."\n";
+		$this->assertTrue($result);
+
+		// Test checkIbanForAccount for CI account
+		$localobject2=new Account($this->savdb);
+		$localobject2->country = 'CI';
+		$localobject2->iban = 'CI77A12312341234123412341234';
+		$result = checkIbanForAccount($localobject2);
+		print __METHOD__." checkIbanForAccount(".$localobject2->iban.") = ".$result."\n";
+		$this->assertTrue($result);
+
 		return $localobject->id;
 	}