Browse code

Erste Version des SEPA-Mandat-Webinterface

Bernd Wurst authored on 20/12/2013 19:13:16
Showing 23 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+1.4.0
0 2
new file mode 100644
... ...
@@ -0,0 +1,35 @@
1
+This file lists specific errors observed in the official IBAN specification.
2
+
3
+In addition to the specific errors, there persist basic outstanding
4
+matters that cause issue for implementers:
5
+ - Non 1:1 mapping of records to countries (eg: French territories, etc.)
6
+ - Mixing of free text and hard data in specification fields
7
+ - Lack of validation of information in fields prior to publishing
8
+ - Lack of synchronisation between TXT and PDF versions of the registry
9
+
10
+2011-07-16
11
+----------
12
+ - No information for Kuwait past sixth column
13
+ - Total absence of information regarding Kazakhstan
14
+ - '1.00001E+15' instead of a valid BBAN example for Lithuania
15
+ - Repeated IBAN example in human format instead of IBAN format-
16
+   specification for UAE
17
+ - Incorrect domestic example for Bulgaria, Kazakhstan, Latvia,
18
+   Lithuania, Luxembourg, Macedonia, Mauritius, Romania, San Marino
19
+   (complete, human-format IBAN instead of domestic example)
20
+
21
+Early 2012
22
+----------
23
+ - Inconsistent record ordering (KW, KZ)
24
+ - Inconsistent capitalization (DK)
25
+ - Continued presence of incorrect domestic examples
26
+
27
+February 2013
28
+-------------
29
+ - Deployment of unparseable special values such as "Not in use" (FI).
30
+ - Still(!) missing a registry entry for 2010's 'new' entry of Khazakstan
31
+
32
+September 2013
33
+--------------
34
+ - Azerbaijan, Brazil, Costa Rica, Palestine, Virgin Islands 'SEPA 
35
+   Country' field in PDF (yes/no) is completely blank
0 36
new file mode 100644
1 37
Binary files /dev/null and b/external/php-iban/docs/ECBS standard implementation guidelines SIG203V3.2.pdf differ
2 38
new file mode 100644
... ...
@@ -0,0 +1,63 @@
1
+By unix tradition, this file outlines information that may be useful to
2
+people who wish to modify the php-iban project. It outlines some basic
3
+information around design decisions and other considerations.
4
+
5
+ Procedural style
6
+ ----------------
7
+   The code is written in PHP's original procedural style, and does
8
+   not require or assume any OO model. This is unix tradition and
9
+   should ease any integration pains due to objectspace mismatches.
10
+   In addition, it should make it easy for users both within an OO
11
+   or a procedural codebase to make use of the library. An OO wrapper
12
+   has been supplied to make things more familiar for those who are
13
+   only exposed to OO PHP: please try to keep it in synch with the
14
+   procedural (main) library where possible.
15
+
16
+ Registry maintenance
17
+ --------------------
18
+   The 'convert-registry.php' tool found in the 'utils/' subdirectory
19
+   is intended to assist with the automatic conversion of the SWIFT-
20
+   provided 'IBAN Registry' text files to the format required to
21
+   support php-iban execution. Why is there a new format, and why is it
22
+   distributed with php-iban instead of being generated on the fly
23
+   from SWIFT-provided data files? There are a few reasons:
24
+
25
+    - Error correction
26
+      If errors are discovered in the official specification then they
27
+      can be resolved by us. There are (or have been) known errors
28
+      with the official IBAN Registry. (See COMEDY-OF-ERRORS)
29
+
30
+    - Exclusion correction
31
+      If exclusions are discovered in the official specification then
32
+      they can be resolved by us. There are (or have been) known 
33
+      exclusions from the official IBAN Registry. (See COMEDY-OF-ERRORS)
34
+
35
+    - Efficiency
36
+      Because pattern matching is a core part of the functionality of
37
+      php-iban, and the pattern algorithms distributed by SWIFT are
38
+      (rather strangely) not in regular expression format, using their
39
+      files directly would result in a fairly significant startup
40
+      penalty as pattern conversion would be required (at each
41
+      invocation!) unless a caching strategy were deployed, which would
42
+      create additional complexity and sources of bugs (in addition,
43
+      due to the previous two points automatic conversion is not
44
+      presently possible ... and may never be!)
45
+
46
+    - Maintainability
47
+      Distribution of a modified registry along with php-iban places
48
+      the burden of registry maintenance on with the package 
49
+      maintainer(s) rather than with the user. This is better for
50
+      users who, if they really want, can still hack their local copy.
51
+
52
+   Note that due to points one and two, the 'convert-registry.php' tool
53
+   is insufficient to produce a correct 'registry.txt' file.  (You may
54
+   wish to review the differences between your newly generated file
55
+   and the original with the 'diff' tool in order to ascertain what
56
+   has changed.)
57
+
58
+   A closing point on the registry: obviously, if any new fields are
59
+   added, then it is best to append them to the end of the registry
60
+   (rightmost, new field) in order to preserve backwards compatibility
61
+   instead of re-ordering the fields which would break older installs.
62
+   (The internal '_iban_load_registry()' function re-orders these fields
63
+   at load time in order to simplify runtime debugging, anyway.)
0 64
new file mode 100644
1 65
Binary files /dev/null and b/external/php-iban/docs/ISO13616.pdf differ
2 66
new file mode 100644
... ...
@@ -0,0 +1,165 @@
1
+		   GNU LESSER GENERAL PUBLIC LICENSE
2
+                       Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+  This version of the GNU Lesser General Public License incorporates
10
+the terms and conditions of version 3 of the GNU General Public
11
+License, supplemented by the additional permissions listed below.
12
+
13
+  0. Additional Definitions. 
14
+
15
+  As used herein, "this License" refers to version 3 of the GNU Lesser
16
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+General Public License.
18
+
19
+  "The Library" refers to a covered work governed by this License,
20
+other than an Application or a Combined Work as defined below.
21
+
22
+  An "Application" is any work that makes use of an interface provided
23
+by the Library, but which is not otherwise based on the Library.
24
+Defining a subclass of a class defined by the Library is deemed a mode
25
+of using an interface provided by the Library.
26
+
27
+  A "Combined Work" is a work produced by combining or linking an
28
+Application with the Library.  The particular version of the Library
29
+with which the Combined Work was made is also called the "Linked
30
+Version".
31
+
32
+  The "Minimal Corresponding Source" for a Combined Work means the
33
+Corresponding Source for the Combined Work, excluding any source code
34
+for portions of the Combined Work that, considered in isolation, are
35
+based on the Application, and not on the Linked Version.
36
+
37
+  The "Corresponding Application Code" for a Combined Work means the
38
+object code and/or source code for the Application, including any data
39
+and utility programs needed for reproducing the Combined Work from the
40
+Application, but excluding the System Libraries of the Combined Work.
41
+
42
+  1. Exception to Section 3 of the GNU GPL.
43
+
44
+  You may convey a covered work under sections 3 and 4 of this License
45
+without being bound by section 3 of the GNU GPL.
46
+
47
+  2. Conveying Modified Versions.
48
+
49
+  If you modify a copy of the Library, and, in your modifications, a
50
+facility refers to a function or data to be supplied by an Application
51
+that uses the facility (other than as an argument passed when the
52
+facility is invoked), then you may convey a copy of the modified
53
+version:
54
+
55
+   a) under this License, provided that you make a good faith effort to
56
+   ensure that, in the event an Application does not supply the
57
+   function or data, the facility still operates, and performs
58
+   whatever part of its purpose remains meaningful, or
59
+
60
+   b) under the GNU GPL, with none of the additional permissions of
61
+   this License applicable to that copy.
62
+
63
+  3. Object Code Incorporating Material from Library Header Files.
64
+
65
+  The object code form of an Application may incorporate material from
66
+a header file that is part of the Library.  You may convey such object
67
+code under terms of your choice, provided that, if the incorporated
68
+material is not limited to numerical parameters, data structure
69
+layouts and accessors, or small macros, inline functions and templates
70
+(ten or fewer lines in length), you do both of the following:
71
+
72
+   a) Give prominent notice with each copy of the object code that the
73
+   Library is used in it and that the Library and its use are
74
+   covered by this License.
75
+
76
+   b) Accompany the object code with a copy of the GNU GPL and this license
77
+   document.
78
+
79
+  4. Combined Works.
80
+
81
+  You may convey a Combined Work under terms of your choice that,
82
+taken together, effectively do not restrict modification of the
83
+portions of the Library contained in the Combined Work and reverse
84
+engineering for debugging such modifications, if you also do each of
85
+the following:
86
+
87
+   a) Give prominent notice with each copy of the Combined Work that
88
+   the Library is used in it and that the Library and its use are
89
+   covered by this License.
90
+
91
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+   document.
93
+
94
+   c) For a Combined Work that displays copyright notices during
95
+   execution, include the copyright notice for the Library among
96
+   these notices, as well as a reference directing the user to the
97
+   copies of the GNU GPL and this license document.
98
+
99
+   d) Do one of the following:
100
+
101
+       0) Convey the Minimal Corresponding Source under the terms of this
102
+       License, and the Corresponding Application Code in a form
103
+       suitable for, and under terms that permit, the user to
104
+       recombine or relink the Application with a modified version of
105
+       the Linked Version to produce a modified Combined Work, in the
106
+       manner specified by section 6 of the GNU GPL for conveying
107
+       Corresponding Source.
108
+
109
+       1) Use a suitable shared library mechanism for linking with the
110
+       Library.  A suitable mechanism is one that (a) uses at run time
111
+       a copy of the Library already present on the user's computer
112
+       system, and (b) will operate properly with a modified version
113
+       of the Library that is interface-compatible with the Linked
114
+       Version. 
115
+
116
+   e) Provide Installation Information, but only if you would otherwise
117
+   be required to provide such information under section 6 of the
118
+   GNU GPL, and only to the extent that such information is
119
+   necessary to install and execute a modified version of the
120
+   Combined Work produced by recombining or relinking the
121
+   Application with a modified version of the Linked Version. (If
122
+   you use option 4d0, the Installation Information must accompany
123
+   the Minimal Corresponding Source and Corresponding Application
124
+   Code. If you use option 4d1, you must provide the Installation
125
+   Information in the manner specified by section 6 of the GNU GPL
126
+   for conveying Corresponding Source.)
127
+
128
+  5. Combined Libraries.
129
+
130
+  You may place library facilities that are a work based on the
131
+Library side by side in a single library together with other library
132
+facilities that are not Applications and are not covered by this
133
+License, and convey such a combined library under terms of your
134
+choice, if you do both of the following:
135
+
136
+   a) Accompany the combined library with a copy of the same work based
137
+   on the Library, uncombined with any other library facilities,
138
+   conveyed under the terms of this License.
139
+
140
+   b) Give prominent notice with the combined library that part of it
141
+   is a work based on the Library, and explaining where to find the
142
+   accompanying uncombined form of the same work.
143
+
144
+  6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+  The Free Software Foundation may publish revised and/or new versions
147
+of the GNU Lesser General Public License from time to time. Such new
148
+versions will be similar in spirit to the present version, but may
149
+differ in detail to address new problems or concerns.
150
+
151
+  Each version is given a distinguishing version number. If the
152
+Library as you received it specifies that a certain numbered version
153
+of the GNU Lesser General Public License "or any later version"
154
+applies to it, you have the option of following the terms and
155
+conditions either of that published version or of any later version
156
+published by the Free Software Foundation. If the Library as you
157
+received it does not specify a version number of the GNU Lesser
158
+General Public License, you may choose any version of the GNU Lesser
159
+General Public License ever published by the Free Software Foundation.
160
+
161
+  If the Library as you received it specifies that a proxy can decide
162
+whether future versions of the GNU Lesser General Public License shall
163
+apply, that proxy's public statement of acceptance of any version is
164
+permanent authorization for you to choose that version for the
165
+Library.
0 166
new file mode 100644
... ...
@@ -0,0 +1,207 @@
1
+php-iban README
2
+---------------
3
+
4
+php-iban is a library for parsing and validating International Bank
5
+Account Number (IBAN) information in PHP.
6
+
7
+It also validates Internet International Bank Account Number
8
+(IIBAN) as specified at http://tools.ietf.org/html/draft-iiban-01
9
+(see also http://www.ifex-project.org/our-proposals/iiban)
10
+
11
+php-iban lives at http://code.google.com/p/php-iban
12
+
13
+  What is an IBAN?
14
+  ----------------
15
+    An IBAN is basically a standardised way of explaining a bank
16
+    account number that works across borders.  Its structure is:
17
+
18
+     <Two Letter ISO Country Code> + <Two Digit Checksum] + <BBAN>
19
+    
20
+    BBAN is the term used to describe the national-level format
21
+    for a bank account number, which varies between countries
22
+    (and was sometimes created just to get IBAN connectivity!).
23
+    Note that a BBAN may have its own checksum algorithm.
24
+
25
+    IBAN provides basic protection, using the checksum, against
26
+    transcription (ie: human copying) errors. It also provides
27
+    a registry of valid destination countries and their BBAN
28
+    formats. Thus, when you ask php-iban to 'validate' an IBAN
29
+    it ensures that these checks are passed. However, it cannot
30
+    ensure that a bank account actually exists - the only party
31
+    who can do that is the receiving bank or country.
32
+
33
+    IBAN was invented in Europe, however its usage is growing
34
+    rapidly to other parts of the world. Thus, the future of
35
+    this library looks pretty good.
36
+
37
+    For further information, please see 'docs/ISO13616.pdf' or
38
+    visit Wikipedia at http://en.wikipedia.org/wiki/IBAN
39
+
40
+  What is an IIBAN?
41
+  -----------------
42
+   An Internet IBAN (IIBAN) identifies an internet-based financial
43
+   endpoint in a manner that is superset-compatible with the existing
44
+   European Committee for Banking Standards (ECBS) International Bank
45
+   Account Number (IBAN) standard [ISO13616].
46
+
47
+   For more information see http://tools.ietf.org/html/draft-iiban-00
48
+   and http://www.ifex-project.org/our-proposals/iiban
49
+
50
+   To disable IIBAN support from your installation, simply remove
51
+   the second ('AA|...') line from the top of the registry.txt file.
52
+
53
+  Execution environment
54
+  ---------------------
55
+    At present the library merely requires a PHP engine to be present
56
+    and has no external dependencies.  It is recommended that your
57
+    PHP engine is configured to disable verbose warnings for events
58
+    such as access of unknown array indexes, though this should be
59
+    standard on almost any PHP deployment today. Any PHP engine
60
+    in use today should be compatible, though PHP3 or PHP4 execution
61
+    environments may require minor modifications (specifically,
62
+    some string functions may have changed).
63
+
64
+  Installation
65
+  ------------
66
+    Simply copy 'php-iban.php' and 'registry.txt' to an appropriate
67
+    location for your project. The location of the files will affect
68
+    the 'require_once()' line used to load the library from your
69
+    codebase, and may have relevance security (see 'Security' below).
70
+    Note that 'php-iban.php' expects to find 'registry.txt' in the
71
+    same directory as itself.
72
+
73
+  Security
74
+  --------
75
+    Following best practice for library files, the location chosen 
76
+    for the php-iban.php and registry.txt files should ideally be 
77
+    outside of any web-accessible directories. Thus, if your 
78
+    web project lives in /var/www/myproject/htdocs/ then it would
79
+    be preferably to place php-iban in /var/www/myproject or some
80
+    other directory that is not visible to regular web users.
81
+    
82
+    Secondly, neither file should be writable by the web server
83
+    itself in order to prevent compromise of the execution path
84
+    (ie: getting hacked). So, for example if your web server runs
85
+    as user 'www', group 'www', you can ensure that the web server
86
+    has minimal required privileges against the files as follows
87
+    (note that you will need to be root to execute these commands):
88
+
89
+     # chown <myuser> php-iban registry.txt  # where <myuser> is a
90
+                                             # non-root user that
91
+                                             # is not 'www'.
92
+     # chgrp www php-iban registry.txt       # set group to 'www'
93
+     # chmod ugo-rwx php-iban registry.txt   # remove privileges
94
+     # chmod g+r php-iban registry.txt       # allow 'www' group
95
+                                             # to read the files
96
+
97
+    Obviously the above do not apply if you are using PHP in a 
98
+    non web-oriented project (eg: a cronjob or daemon), a usage
99
+    of the language that is apparently growing - but limited.
100
+
101
+  Using the library
102
+  -----------------
103
+    Basic invocation is as follows:
104
+
105
+      # include the library
106
+      require_once('/path/to/php-iban.php'); # /path/to/ is optional
107
+
108
+      # use some library function or other...
109
+      if(!verify_iban($iban_to_verify)) {
110
+       # blame the user...
111
+      }
112
+
113
+    Note that because the library is designed in a procedural manner
114
+    rather than an object-oriented manner it should be easy to 
115
+    integrate with a wide variety of established codebases and 
116
+    PHP interpreter versions.
117
+
118
+  Using the library's OO wrapper
119
+  ------------------------------
120
+    Because many new PHP programmers seems to learn the language via
121
+    books that only teach OO based programming and are thus unfamiliar
122
+    with procedural PHP (and often relatively inexperienced as 
123
+    programmers, too) an OO wrapper-library has been provided.
124
+
125
+    ======================= READ THIS =================================
126
+    However *you should avoid excessive use of OO*. For some thought
127
+    provoking discussions of the negative aspects of overusing OO,
128
+    please refer to 'Coders at Work' and 'The Art of UNIX Programming'.
129
+    (OO is great for some problems, but simply pointless for most.)
130
+    ===================================================================
131
+
132
+    Anyway, to use the OO wrapper supplied, invocation is as follows:
133
+
134
+      # include the OO wrapper to the library
135
+      require_once('/path/to/oophp-iban.php'); # /path/to is optional
136
+
137
+      # instantiate an IBAN object
138
+      $myIban = new IBAN('AZ12345678901234');
139
+      if(!$myIban->Verify()) {
140
+       # blame the user...
141
+      }
142
+
143
+  Documentation
144
+  -------------
145
+    There are three types of functions provided by the library:
146
+
147
+     - IBAN-level functions
148
+
149
+         These are functions that operate on an IBAN. All of these
150
+         functions accept either machine format or human format
151
+         IBANs as input. Typically they return facts about an IBAN
152
+         as their output (for example whether it is valid or not,
153
+         or the BBAN (national-level) portion of the IBAN), though
154
+         some of them may perform other functions (eg: fixing a
155
+         broken IBAN checksum). These functions are named 'iban_*'
156
+         with the exception of the most commonly used function,
157
+         'verify_iban()', and excepting the country-level functions.
158
+
159
+         (Regarding the object oriented wrapper - all of these
160
+          functions are implemented as methods on IBAN objects)
161
+
162
+     - IBAN country-level functions
163
+         These functions return information about countries that are
164
+         part of the IBAN standard. They each take the two letter 
165
+         ISO country code at the beginning of an IBAN as their
166
+         argument. They are named 'iban_country_*', with the 
167
+         exception of 'iban_countries()' which returns a list of
168
+         the known IBAN countries. (For example, functions that 
169
+         return an example IBAN or BBAN for the country, or the 
170
+         name of the country.)
171
+
172
+         (Regarding the object oriented wrapper - all of these
173
+          functions are implemented as methods on IBANCountry
174
+          objects, except for 'iban_countries()' which is 
175
+          implemented as the Countries() method on the IBAN class)
176
+
177
+     - Internal functions
178
+         These functions begin with '_iban_*' and can be ignored.
179
+
180
+         (Regarding the object oriented wrapper - these functions
181
+          are not present)
182
+
183
+    Please refer to either http://code.google.com/p/php-iban or the
184
+    commented source code of php-iban itself for the complete list of
185
+    which functions are available. Of course, in unix style one could
186
+    achieve the same in a pinch as follows (instant documentation!):
187
+     $ grep function php-iban.php
188
+     $ egrep '(Class|function)' oophp-iban.php
189
+
190
+  Community
191
+  ---------
192
+    You are encouraged to contribute bugs, feedback and suggestions 
193
+    through the project's website.
194
+
195
+    Particularly if you deploy php-iban in a commercial setting, you are
196
+    STRONGLY encouraged to join the project's mailing list, which can
197
+    be found via the website. Joining the mailing list ensures that you
198
+    can be made aware of important updates. Important updates include:
199
+     - Updates to new registry editions (support new countries that have
200
+       been added to the IBAN system)
201
+     - Bug fixes 
202
+     - Security updates
203
+
204
+    The email list receives almost no traffic and as a 'Google Group' is
205
+    well protected from spam, so don't worry about junk in your inbox.
206
+
207
+Thanks for choosing php-iban! You have excellent taste in software ;)
0 208
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+To get the latest ISO13616 IBAN registry as a .txt file
2
+for parsing, go to:
3
+ http://www.swift.com/solutions/messaging/information_products/directory_products/iban_format_registry/index.page?lang=en
4
+... then follow the '.txt format' link.
5
+
6
+Unfortunately, it has been noticed in 2011 that the official .txt file is
7
+not an accurate representation of the PDF format specification, and lacks
8
+some information. It is hoped that in future SWIFT will be more careful to
9
+publish only correct standards information.
10
+
11
+(For more information on this subject, see the HACKING file)
0 12
new file mode 100644
... ...
@@ -0,0 +1,9 @@
1
+Interpreting the SEPA Field
2
+===========================
3
+
4
+Note that some IIBAN providers may in fact provide SEPA connectivity.
5
+
6
+Thus, implementers are reminded to consider the reported SEPA status
7
+of a country within the registry as confirming rather than negating
8
+the potential SEPA status of a potential financial institution who
9
+may be party to a proposed transaction.
0 10
new file mode 100644
... ...
@@ -0,0 +1,21 @@
1
+TODO
2
+----
3
+
4
+ - Finnish record suggests position at which to pad domestic account
5
+   numbers in order to reach a BBAN / IBAN, this data could be of
6
+   some use for certain applications and would be nice to include
7
+ - Addition of information regarding preferred human-level formatting
8
+   for each country's BBAN - worthwhile?
9
+ - Addition of 'date effective' information for records such as BH
10
+   and the UAE that published data in advance of deployment
11
+ - Support for calculating or validating any known national (sub-
12
+   BBAN-level) checksum algorithms?
13
+ - URLs to national-level BBAN format specifications
14
+ - Consider adding a library of localised forms and abbreviations
15
+   for account number portions, for example Austria and Germany seem
16
+   to have 'Kontonummer' (KTO) for account number, and 'Bankleitzah'
17
+   (BLZ) for bank identifier. This could assist greatly with 
18
+   deployments requiring international and/or constrained input.
19
+ - Consider building a library of national-level bank or payment
20
+   institution identifier codes. This would be rather large and an
21
+   optional extension.
0 22
new file mode 100644
... ...
@@ -0,0 +1,49 @@
1
+ ; formalities
2
+ input-roman = number / letter
3
+ number      = c-0 / c-1 / c-2 / c-3 / c-4 / c-5 / c-6 / c-7 / c-8 / c-9
4
+ letter      = c-a / c-b / c-c / c-d / c-e / c-f / c-g / c-h / c-i / c-j
5
+                   / c-k / c-l / c-m / c-n / c-o / c-p / c-q / c-r / c-s
6
+                   / c-t / c-u / c-v / c-w / c-x / c-y / c-z
7
+
8
+ ; possible sources of mistranscribed numbers
9
+ c-0 = "O" / "6" / "D" / "G"
10
+ c-1 = "I" / "L" / "7" / "2" / "Z"
11
+ c-2 = "Z" / "7" / "P" / "E" / "1"
12
+ c-3 = "8" / "B"
13
+ c-4 = "G" / "U"
14
+ c-5 = "S" / "7"
15
+ c-6 = "0" / "O" / "8" / "G" / "C" / "B" / "D"
16
+ c-7 = "J" / "I" / "1" / "L"
17
+ c-8 = "B" / "3" / "6"
18
+ c-9 = "G" / "Y" / "O" / "0" / "D"
19
+
20
+ ; possible sources of mistranscribed letters
21
+ c-a = "G" / "Q" / "O" / "0"
22
+ c-b = "6" / "3" / "8" / "P" / "0" / "O"
23
+ c-c = "R" / "6" / "I" / "L" / "O" / "0"
24
+ c-d = "0" / "O" / "9" / "Q" / "G" / "6" / "A"
25
+ c-e = "F" / "G" / "0" / "2" / "K" / "Z" / "S" / "O"
26
+ c-f = "E" / "K" / "T" / "P" / "Y" / "4" / "B" / "7" / "1"
27
+ c-g = "9" / "Q" / "8" / "6" / "0" / "C" / "4" / "O"
28
+ c-h = "B" / "N" / "A" / "4" / "6" / "M" / "W" / "F" / "R" / "T" / "X"
29
+ c-i = "1" / "L" / "7" / "J" / "2" / "T" / "Z"
30
+ c-j = "I" / "7" / "2" / "9" / "1" / "U" / "T" / "Q" / "P" / "Y" / "Z"
31
+           / "L" / "S"
32
+ c-k = "F" / "X" / "H" / "R" 
33
+ c-l = "1" / "2" / "7" / "C" / "I" / "J" / "R" / "T" / "Y" / "Z"
34
+ c-m = "H" / "8" / "E" / "3" / "N" / "V" / "W" 
35
+ c-n = "H" / "R" / "C" / "2" / "4" / "M" / "O" / "P" / "K" / "T" / "Z"
36
+ c-o = "0" / "6" / "9" / "A" / "D" / "G" / "C" / "E" / "B" / "N" / "P"
37
+           / "Q" / "R"
38
+ c-p = "F" / "4" / "8" / "2" / "B" / "J" / "R" / "N" / "O" / "T" / "Y"
39
+ c-q = "O" / "G" / "9" / "Y" / "1" / "7" / "L"
40
+ c-r = "K" / "B" / "V" / "C" / "1" / "L" / "2"
41
+ c-s = "5" / "6" / "9" / "B" / "G" / "Q" / "A" / "Y"
42
+ c-t = "1" / "4" / "7" / "F" / "I" / "J" / "L" / "P" / "X" / "Y"
43
+ c-u = "V" / "N" / "A" / "4" / "9" / "W" / "Y"
44
+ c-v = "U" / "R" / "N"
45
+ c-w = "M" / "N" / "U" / "V"
46
+ c-x = "K" / "F" / "4" / "T" / "V" / "Y"
47
+ c-y = "G" / "V" / "J" / "I" / "4" / "9" / "T" / "F" / "Q" / "1"
48
+ c-z = "2" / "1" / "L" / "R" / "I" / "7" / "V" / "3" / "4"
49
+
0 50
new file mode 100644
... ...
@@ -0,0 +1,157 @@
1
+<?php
2
+
3
+# OO wrapper for 'php-iban.php'
4
+Class IBAN {
5
+
6
+ function __construct($iban = '') {
7
+  require_once('php-iban.php'); # load the procedural codebase
8
+  $this->iban = $iban;
9
+ }
10
+
11
+ public function Verify($iban='') {
12
+  if($iban!='') { return verify_iban($iban); }
13
+  return verify_iban($this->iban);
14
+  # we could throw exceptions of various types, but why - does it really
15
+  # add anything? possibly some slightly better user feedback potential.
16
+  # however, this can be written by hand by performing individual checks
17
+  # ala the code in verify_iban() itself where required, which is likely
18
+  # almost never. for the increased complexity and
19
+  # maintenance/documentation cost, i say, therefore: no. no exceptions.
20
+ }
21
+
22
+ public function MistranscriptionSuggestions() {
23
+  return iban_mistranscription_suggestions($this->iban);
24
+ }
25
+
26
+ public function MachineFormat() {
27
+  return iban_to_machine_format($this->iban);
28
+ }
29
+
30
+ public function HumanFormat() {
31
+  return iban_to_human_format($this->iban);
32
+ }
33
+
34
+ public function Country($iban='') {
35
+  return iban_get_country_part($this->iban);
36
+ }
37
+
38
+ public function Checksum($iban='') {
39
+  return iban_get_checksum_part($this->iban);
40
+ }
41
+
42
+ public function BBAN() {
43
+  return iban_get_bban_part($this->iban);
44
+ }
45
+
46
+ public function VerifyChecksum() {
47
+  return iban_verify_checksum($this->iban);
48
+ }
49
+
50
+ public function FindChecksum() {
51
+  return iban_find_checksum($this->iban);
52
+ }
53
+
54
+ public function SetChecksum() {
55
+  $this->iban = iban_set_checksum($this->iban);
56
+ }
57
+
58
+ public function ChecksumStringReplace() {
59
+  return iban_checksum_string_replace($this->iban);
60
+ }
61
+
62
+ public function Parts() {
63
+  return iban_get_parts($this->iban);
64
+ }
65
+
66
+ public function Bank() {
67
+  return iban_get_bank_part($this->iban);
68
+ }
69
+
70
+ public function Branch() {
71
+  return iban_get_branch_part($this->iban);
72
+ }
73
+
74
+ public function Account() {
75
+  return iban_get_account_part($this->iban);
76
+ }
77
+
78
+ public function Countries() {
79
+  return iban_countries();
80
+ }
81
+}
82
+
83
+# IBANCountry
84
+Class IBANCountry {
85
+
86
+ # constructor with code
87
+ function __construct($code = '') {
88
+  $this->code = $code;
89
+ }
90
+
91
+ public function Name() {
92
+  return iban_country_get_country_name($this->code);
93
+ }
94
+
95
+ public function DomesticExample() {
96
+  return iban_country_get_domestic_example($this->code);
97
+ }
98
+
99
+ public function BBANExample() {
100
+  return iban_country_get_bban_example($this->code);
101
+ }
102
+
103
+ public function BBANFormatSWIFT() {
104
+  return iban_country_get_bban_format_swift($this->code);
105
+ }
106
+
107
+ public function BBANFormatRegex() {
108
+  return iban_country_get_bban_format_regex($this->code);
109
+ }
110
+
111
+ public function BBANLength() {
112
+  return iban_country_get_bban_length($this->code);
113
+ }
114
+
115
+ public function IBANExample() {
116
+  return iban_country_get_iban_example($this->code);
117
+ }
118
+
119
+ public function IBANFormatSWIFT() {
120
+  return iban_country_get_iban_format_swift($this->code);
121
+ }
122
+
123
+ public function IBANFormatRegex() {
124
+  return iban_country_get_iban_format_regex($this->code);
125
+ }
126
+
127
+ public function IBANLength() {
128
+  return iban_country_get_iban_length($this->code);
129
+ }
130
+
131
+ public function BankIDStartOffset() {
132
+  return iban_country_get_bankid_start_offset($this->code);
133
+ }
134
+
135
+ public function BankIDStopOffset() {
136
+  return iban_country_get_bankid_stop_offset($this->code);
137
+ }
138
+
139
+ public function BranchIDStartOffset() {
140
+  return iban_country_get_branchid_start_offset($this->code);
141
+ }
142
+
143
+ public function BranchIDStopOffset() {
144
+  return iban_country_get_branchid_stop_offset($this->code);
145
+ }
146
+
147
+ public function RegistryEdition() {
148
+  return iban_country_get_registry_edition($this->code);
149
+ }
150
+
151
+ public function IsSEPA() {
152
+  return iban_country_is_sepa($this->code);
153
+ }
154
+
155
+}
156
+
157
+?>
0 158
new file mode 100644
... ...
@@ -0,0 +1,486 @@
1
+<?php
2
+
3
+# PHP IBAN - http://code.google.com/p/php-iban - LGPLv3
4
+
5
+# Global flag by request
6
+$__disable_iiban_gmp_extension=false;
7
+
8
+# Verify an IBAN number.  Returns true or false.
9
+#  NOTE: Input can be printed 'IIBAN xx xx xx...' or 'IBAN xx xx xx...' or machine 'xxxxx' format.
10
+function verify_iban($iban) {
11
+
12
+ # First convert to machine format.
13
+ $iban = iban_to_machine_format($iban);
14
+
15
+ # Get country of IBAN
16
+ $country = iban_get_country_part($iban);
17
+
18
+ # Test length of IBAN
19
+ if(strlen($iban)!=iban_country_get_iban_length($country)) { return false; }
20
+
21
+ # Get checksum of IBAN
22
+ $checksum = iban_get_checksum_part($iban);
23
+
24
+ # Get country-specific IBAN format regex
25
+ $regex = '/'.iban_country_get_iban_format_regex($country).'/';
26
+
27
+ # Check regex
28
+ if(preg_match($regex,$iban)) {
29
+  # Regex passed, check checksum
30
+  if(!iban_verify_checksum($iban)) { 
31
+   return false;
32
+  }
33
+ }
34
+ else {
35
+  return false;
36
+ }
37
+
38
+ # Otherwise it 'could' exist
39
+ return true;
40
+}
41
+
42
+# Convert an IBAN to machine format.  To do this, we
43
+# remove IBAN from the start, if present, and remove
44
+# non basic roman letter / digit characters
45
+function iban_to_machine_format($iban) {
46
+ # Uppercase and trim spaces from left
47
+ $iban = ltrim(strtoupper($iban));
48
+ # Remove IIBAN or IBAN from start of string, if present
49
+ $iban = preg_replace('/^I?IBAN/','',$iban);
50
+ # Remove all non basic roman letter / digit characters
51
+ $iban = preg_replace('/[^a-zA-Z0-9]/','',$iban);
52
+ return $iban;
53
+}
54
+
55
+# Convert an IBAN to human format. To do this, we
56
+# simply insert spaces right now, as per the ECBS
57
+# (European Committee for Banking Standards) 
58
+# recommendations available at:
59
+# http://www.europeanpaymentscouncil.eu/knowledge_bank_download.cfm?file=ECBS%20standard%20implementation%20guidelines%20SIG203V3.2.pdf 
60
+function iban_to_human_format($iban) {
61
+ # First verify validity, or return
62
+ if(!verify_iban($iban)) { return false; }
63
+ # Add spaces every four characters
64
+ $human_iban = '';
65
+ for($i=0;$i<strlen($iban);$i++) {
66
+  $human_iban .= substr($iban,$i,1);
67
+  if(($i>0) && (($i+1)%4==0)) { $human_iban .= ' '; }
68
+ }
69
+ return $human_iban;
70
+}
71
+
72
+# Get the country part from an IBAN
73
+function iban_get_country_part($iban) {
74
+ $iban = iban_to_machine_format($iban);
75
+ return substr($iban,0,2);
76
+}
77
+
78
+# Get the checksum part from an IBAN
79
+function iban_get_checksum_part($iban) {
80
+ $iban = iban_to_machine_format($iban);
81
+ return substr($iban,2,2);
82
+}
83
+
84
+# Get the BBAN part from an IBAN
85
+function iban_get_bban_part($iban) {
86
+ $iban = iban_to_machine_format($iban);
87
+ return substr($iban,4);
88
+}
89
+
90
+# Check the checksum of an IBAN - code modified from Validate_Finance PEAR class
91
+function iban_verify_checksum($iban) {
92
+ # convert to machine format
93
+ $iban = iban_to_machine_format($iban);
94
+ # move first 4 chars (countrycode and checksum) to the end of the string
95
+ $tempiban = substr($iban, 4).substr($iban, 0, 4);
96
+ # subsitutute chars
97
+ $tempiban = iban_checksum_string_replace($tempiban);
98
+ # mod97-10
99
+ $result = iban_mod97_10($tempiban);
100
+ # checkvalue of 1 indicates correct IBAN checksum
101
+ if ($result != 1) {
102
+  return false;
103
+ }
104
+ return true;
105
+}
106
+
107
+# Find the correct checksum for an IBAN
108
+#  $iban  The IBAN whose checksum should be calculated
109
+function iban_find_checksum($iban) {
110
+ $iban = iban_to_machine_format($iban);
111
+ # move first 4 chars to right
112
+ $left = substr($iban,0,2) . '00'; # but set right-most 2 (checksum) to '00'
113
+ $right = substr($iban,4);
114
+ # glue back together
115
+ $tmp = $right . $left;
116
+ # convert letters using conversion table
117
+ $tmp = iban_checksum_string_replace($tmp);
118
+ # get mod97-10 output
119
+ $checksum = iban_mod97_10_checksum($tmp);
120
+ # return 98 minus the mod97-10 output, left zero padded to two digits
121
+ return str_pad((98-$checksum),2,'0',STR_PAD_LEFT);
122
+}
123
+
124
+# Set the correct checksum for an IBAN
125
+#  $iban  IBAN whose checksum should be set
126
+function iban_set_checksum($iban) {
127
+ $iban = iban_to_machine_format($iban);
128
+ return substr($iban,0,2) . iban_find_checksum($iban) . substr($iban,4);
129
+}
130
+
131
+# Character substitution required for IBAN MOD97-10 checksum validation/generation
132
+#  $s  Input string (IBAN)
133
+function iban_checksum_string_replace($s) {
134
+ $iban_replace_chars = range('A','Z');
135
+ foreach (range(10,35) as $tempvalue) { $iban_replace_values[]=strval($tempvalue); }
136
+ return str_replace($iban_replace_chars,$iban_replace_values,$s);
137
+}
138
+
139
+# Same as below but actually returns resulting checksum
140
+function iban_mod97_10_checksum($numeric_representation) {
141
+ $checksum = intval(substr($numeric_representation, 0, 1));
142
+ for ($position = 1; $position < strlen($numeric_representation); $position++) {
143
+  $checksum *= 10;
144
+  $checksum += intval(substr($numeric_representation,$position,1));
145
+  $checksum %= 97;
146
+ }
147
+ return $checksum;
148
+}
149
+
150
+# Perform MOD97-10 checksum calculation ('Germanic-level effiency' version - thanks Chris!)
151
+function iban_mod97_10($numeric_representation) {
152
+ global $__disable_iiban_gmp_extension;
153
+ # prefer php5 gmp extension if available
154
+ if(!($__disable_iiban_gmp_extension) && function_exists('gmp_intval')) { return gmp_intval(gmp_mod(gmp_init($numeric_representation, 10),'97')) === 1; }
155
+
156
+/*
157
+ # old manual processing (~16x slower)
158
+ $checksum = intval(substr($numeric_representation, 0, 1));
159
+ for ($position = 1; $position < strlen($numeric_representation); $position++) {
160
+  $checksum *= 10;
161
+  $checksum += intval(substr($numeric_representation,$position,1));
162
+  $checksum %= 97;
163
+ }
164
+ return $checksum;
165
+ */
166
+
167
+ # new manual processing (~3x slower)
168
+ $length = strlen($numeric_representation);
169
+ $rest = "";
170
+ $position = 0;
171
+ while ($position < $length) {
172
+        $value = 9-strlen($rest);
173
+        $n = $rest . substr($numeric_representation,$position,$value);
174
+        $rest = $n % 97;
175
+        $position = $position + $value;
176
+ }
177
+ return ($rest === 1);
178
+}
179
+
180
+# Get an array of all the parts from an IBAN
181
+function iban_get_parts($iban) {
182
+ return array(
183
+         'country'	=>      iban_get_country_part($iban),
184
+ 	 'checksum'	=>	iban_get_checksum_part($iban),
185
+	 'bban'		=>	iban_get_bban_part($iban),
186
+ 	 'bank'		=>	iban_get_bank_part($iban),
187
+	 'country'	=>	iban_get_country_part($iban),
188
+	 'branch'	=>	iban_get_branch_part($iban),
189
+	 'account'	=>	iban_get_account_part($iban)
190
+        );
191
+}
192
+
193
+# Get the Bank ID (institution code) from an IBAN
194
+function iban_get_bank_part($iban) {
195
+ $iban = iban_to_machine_format($iban);
196
+ $country = iban_get_country_part($iban);
197
+ $start = iban_country_get_bankid_start_offset($country);
198
+ $stop = iban_country_get_bankid_stop_offset($country);
199
+ if($start!=''&&$stop!='') {
200
+  $bban = iban_get_bban_part($iban);
201
+  return substr($bban,$start,($stop-$start+1));
202
+ }
203
+ return '';
204
+}
205
+
206
+# Get the Branch ID (sort code) from an IBAN
207
+function iban_get_branch_part($iban) {
208
+ $iban = iban_to_machine_format($iban);
209
+ $country = iban_get_country_part($iban);
210
+ $start = iban_country_get_branchid_start_offset($country);
211
+ $stop = iban_country_get_branchid_stop_offset($country);
212
+ if($start!=''&&$stop!='') {
213
+  $bban = iban_get_bban_part($iban);
214
+  return substr($bban,$start,($stop-$start+1));
215
+ }
216
+ return '';
217
+}
218
+
219
+# Get the (branch-local) account ID from an IBAN
220
+function iban_get_account_part($iban) {
221
+ $iban = iban_to_machine_format($iban);
222
+ $country = iban_get_country_part($iban);
223
+ $start = iban_country_get_branchid_stop_offset($country);
224
+ if($start=='') {
225
+  $start = iban_country_get_bankid_stop_offset($country);
226
+ }
227
+ if($start!='') {
228
+  $bban = iban_get_bban_part($iban);
229
+  return substr($bban,$start+1);
230
+ }
231
+ return '';
232
+}
233
+
234
+# Get the name of an IBAN country
235
+function iban_country_get_country_name($iban_country) {
236
+ return _iban_country_get_info($iban_country,'country_name');
237
+}
238
+
239
+# Get the domestic example for an IBAN country
240
+function iban_country_get_domestic_example($iban_country) {
241
+ return _iban_country_get_info($iban_country,'domestic_example');
242
+}
243
+
244
+# Get the BBAN example for an IBAN country
245
+function iban_country_get_bban_example($iban_country) {
246
+ return _iban_country_get_info($iban_country,'bban_example');
247
+}
248
+
249
+# Get the BBAN format (in SWIFT format) for an IBAN country
250
+function iban_country_get_bban_format_swift($iban_country) {
251
+ return _iban_country_get_info($iban_country,'bban_format_swift');
252
+}
253
+
254
+# Get the BBAN format (as a regular expression) for an IBAN country
255
+function iban_country_get_bban_format_regex($iban_country) {
256
+ return _iban_country_get_info($iban_country,'bban_format_regex');
257
+}
258
+
259
+# Get the BBAN length for an IBAN country
260
+function iban_country_get_bban_length($iban_country) {
261
+ return _iban_country_get_info($iban_country,'bban_length');
262
+}
263
+
264
+# Get the IBAN example for an IBAN country
265
+function iban_country_get_iban_example($iban_country) {
266
+ return _iban_country_get_info($iban_country,'iban_example');
267
+}
268
+
269
+# Get the IBAN format (in SWIFT format) for an IBAN country
270
+function iban_country_get_iban_format_swift($iban_country) {
271
+ return _iban_country_get_info($iban_country,'iban_format_swift');
272
+}
273
+
274
+# Get the IBAN format (as a regular expression) for an IBAN country
275
+function iban_country_get_iban_format_regex($iban_country) {
276
+ return _iban_country_get_info($iban_country,'iban_format_regex');
277
+}
278
+
279
+# Get the IBAN length for an IBAN country
280
+function iban_country_get_iban_length($iban_country) {
281
+ return _iban_country_get_info($iban_country,'iban_length');
282
+}
283
+
284
+# Get the BBAN Bank ID start offset for an IBAN country
285
+function iban_country_get_bankid_start_offset($iban_country) {
286
+ return _iban_country_get_info($iban_country,'bban_bankid_start_offset');
287
+}
288
+
289
+# Get the BBAN Bank ID stop offset for an IBAN country
290
+function iban_country_get_bankid_stop_offset($iban_country) {
291
+ return _iban_country_get_info($iban_country,'bban_bankid_stop_offset');
292
+}
293
+
294
+# Get the BBAN Branch ID start offset for an IBAN country
295
+function iban_country_get_branchid_start_offset($iban_country) {
296
+ return _iban_country_get_info($iban_country,'bban_branchid_start_offset');
297
+}
298
+
299
+# Get the BBAN Branch ID stop offset for an IBAN country
300
+function iban_country_get_branchid_stop_offset($iban_country) {
301
+ return _iban_country_get_info($iban_country,'bban_branchid_stop_offset');
302
+}
303
+
304
+# Get the registry edition for an IBAN country
305
+function iban_country_get_registry_edition($iban_country) {
306
+ return _iban_country_get_info($iban_country,'registry_edition');
307
+}
308
+
309
+# Is the IBAN country a SEPA member?
310
+function iban_country_is_sepa($iban_country) {
311
+ return _iban_country_get_info($iban_country,'country_sepa');
312
+}
313
+
314
+# Get the list of all IBAN countries
315
+function iban_countries() {
316
+ global $_iban_registry;
317
+ return array_keys($_iban_registry);
318
+}
319
+
320
+# Given an incorrect IBAN, return an array of zero or more checksum-valid
321
+# suggestions for what the user might have meant, based upon common
322
+# mistranscriptions.
323
+function iban_mistranscription_suggestions($incorrect_iban) {
324
+ 
325
+ # abort on ridiculous length input (but be liberal)
326
+ $length = strlen($incorrect_iban);
327
+ if($length<5 || $length>34) { return array('(length bad)'); }
328
+
329
+ # abort if mistranscriptions data is unable to load
330
+ if(!_iban_load_mistranscriptions()) { return array('(failed to load)'); }
331
+
332
+ # init
333
+ global $_iban_mistranscriptions;
334
+ $suggestions = array();
335
+
336
+ # we have a string of approximately IBAN-like length.
337
+ # ... now let's make suggestions.
338
+ $numbers = array('0','1','2','3','4','5','6','7','8','9');
339
+ for($i=0;$i<$length;$i++) {
340
+  # get the character at this position
341
+  $character = substr($incorrect_iban,$i,1);
342
+  # for each known transcription error resulting in this character
343
+  foreach($_iban_mistranscriptions[$character] as $possible_origin) {
344
+   # if we're:
345
+   #  - in the first 2 characters (country) and the possible replacement
346
+   #    is a letter
347
+   #  - in the 3rd or 4th characters (checksum) and the possible
348
+   #    replacement is a number
349
+   #  - later in the string
350
+   if(($i<2 && !in_array($possible_origin,$numbers)) ||
351
+      ($i>=2 && $i<=3 && in_array($possible_origin,$numbers)) ||
352
+      $i>3) {
353
+    # construct a possible IBAN using this possible origin for the
354
+    # mistranscribed character, replaced at this position only
355
+    $possible_iban = substr($incorrect_iban,0,$i) . $possible_origin .  substr($incorrect_iban,$i+1);
356
+    # if the checksum passes, return it as a possibility
357
+    if(verify_iban($possible_iban)) {
358
+     array_push($suggestions,$possible_iban);
359
+    }
360
+   }
361
+  }
362
+ }
363
+
364
+ # now we check for the type of mistransposition case where all of
365
+ # the characters of a certain type within a string were mistransposed.
366
+ #  - first generate a character frequency table
367
+ $char_freqs = array();
368
+ for($i=0;$i<strlen($incorrect_iban);$i++) {
369
+  if(!isset($char_freqs[substr($incorrect_iban,$i,1)])) {
370
+   $char_freqs[substr($incorrect_iban,$i,1)] = 1;
371
+  }
372
+  else {
373
+   $char_freqs[substr($incorrect_iban,$i,1)]++;
374
+  }
375
+ }
376
+ #  - now, for each of the characters in the string...
377
+ foreach($char_freqs as $char=>$freq) {
378
+  # if the character occurs more than once
379
+  if($freq>1) {
380
+   # check the 'all occurrences of <char> were mistranscribed' case
381
+   foreach($_iban_mistranscriptions[$char] as $possible_origin) {
382
+    $possible_iban = str_replace($char,$possible_origin,$incorrect_iban);
383
+    if(verify_iban($possible_iban)) {
384
+     array_push($suggestions,$possible_iban);
385
+    }
386
+   }
387
+  }
388
+ }
389
+
390
+ return $suggestions;
391
+}
392
+
393
+
394
+##### internal use functions - safe to ignore ######
395
+
396
+# Load the IBAN registry from disk.
397
+global $_iban_registry;
398
+$_iban_registry = array();
399
+_iban_load_registry();
400
+function _iban_load_registry() {
401
+ global $_iban_registry;
402
+ # if the registry is not yet loaded, or has been corrupted, reload
403
+ if(!is_array($_iban_registry) || count($_iban_registry)<1) {
404
+  $data = file_get_contents(dirname(__FILE__) . '/registry.txt');
405
+  $lines = explode("\n",$data);
406
+  array_shift($lines); # drop leading description line
407
+  # loop through lines
408
+  foreach($lines as $line) {
409
+   if($line!='') {
410
+    # split to fields
411
+    $old_display_errors_value = ini_get('display_errors');
412
+    ini_set('display_errors',false);
413
+    $old_error_reporting_value = ini_get('error_reporting');
414
+    ini_set('error_reporting',false);
415
+    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);
416
+    ini_set('display_errors',$old_display_errors_value);
417
+    ini_set('error_reporting',$old_error_reporting_value);
418
+    # assign to registry
419
+    $_iban_registry[$country] = array(
420
+                                'country'			=>	$country,
421
+ 				'country_name'			=>	$country_name,
422
+				'country_sepa'			=>	$country_sepa,
423
+ 				'domestic_example'		=>	$domestic_example,
424
+				'bban_example'			=>	$bban_example,
425
+				'bban_format_swift'		=>	$bban_format_swift,
426
+				'bban_format_regex'		=>	$bban_format_regex,
427
+				'bban_length'			=>	$bban_length,
428
+				'iban_example'			=>	$iban_example,
429
+				'iban_format_swift'		=>	$iban_format_swift,
430
+				'iban_format_regex'		=>	$iban_format_regex,
431
+				'iban_length'			=>	$iban_length,
432
+				'bban_bankid_start_offset'	=>	$bban_bankid_start_offset,
433
+				'bban_bankid_stop_offset'	=>	$bban_bankid_stop_offset,
434
+				'bban_branchid_start_offset'	=>	$bban_branchid_start_offset,
435
+				'bban_branchid_stop_offset'	=>	$bban_branchid_stop_offset,
436
+				'registry_edition'		=>	$registry_edition
437
+                               );
438
+   }
439
+  }
440
+ }
441
+}
442
+
443
+# Get information from the IBAN registry by example IBAN / code combination
444
+function _iban_get_info($iban,$code) {
445
+ $country = iban_get_country_part($iban);
446
+ return _iban_country_get_info($country,$code);
447
+}
448
+
449
+# Get information from the IBAN registry by country / code combination
450
+function _iban_country_get_info($country,$code) {
451
+ global $_iban_registry;
452
+ $country = strtoupper($country);
453
+ $code = strtolower($code);
454
+ if(array_key_exists($country,$_iban_registry)) {
455
+  if(array_key_exists($code,$_iban_registry[$country])) {
456
+   return $_iban_registry[$country][$code];
457
+  }
458
+ }
459
+ return false;
460
+}
461
+
462
+# Load common mistranscriptions from disk.
463
+function _iban_load_mistranscriptions() {
464
+ global $_iban_mistranscriptions;
465
+ # do not reload if already present
466
+ if(is_array($_iban_mistranscriptions) && count($_iban_mistranscriptions) == 36) { return true; }
467
+ $_iban_mistranscriptions = array();
468
+ $file = dirname(__FILE__) . '/mistranscriptions.txt';
469
+ if(!file_exists($file) || !is_readable($file)) { return false; }
470
+ $data = file_get_contents($file);
471
+ $lines = explode("\n",$data);
472
+ foreach($lines as $line) {
473
+  # match lines with ' c-<x> = <something>' where x is a word-like character
474
+  if(preg_match('/^ *c-(\w) = (.*?)$/',$line,$matches)) {
475
+   # normalize the character to upper case
476
+   $character = strtoupper($matches[1]);
477
+   # break the possible origins list at '/', strip quotes & spaces
478
+   $chars = explode(' ',str_replace('"','',preg_replace('/ *?\/ *?/','',$matches[2])));
479
+   # assign as possible mistranscriptions for that character
480
+   $_iban_mistranscriptions[$character] = $chars;
481
+  }
482
+ }
483
+ return true;
484
+}
485
+
486
+?>
0 487
new file mode 100644
... ...
@@ -0,0 +1,79 @@
1
+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
2
+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
3
+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
4
+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
5
+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
6
+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
7
+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
8
+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
9
+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
10
+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
11
+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
12
+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
13
+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
14
+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|0
15
+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
16
+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
17
+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
18
+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|1
19
+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|1
20
+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
21
+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
22
+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
23
+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
24
+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
25
+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
26
+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
27
+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
28
+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
29
+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
30
+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
31
+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
32
+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
33
+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
34
+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
35
+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
36
+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
37
+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
38
+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
39
+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
40
+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
41
+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
42
+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
43
+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
44
+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
45
+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
46
+KZ|Kazakhstan|125K ZT50 0410 0100|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|||2011-06-20|0
47
+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
48
+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
49
+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
50
+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
51
+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
52
+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
53
+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
54
+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
55
+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
56
+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
57
+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
58
+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
59
+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
60
+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
61
+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
62
+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
63
+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
64
+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
65
+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
66
+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
67
+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|0
68
+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
69
+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
70
+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
71
+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
72
+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
73
+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
74
+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
75
+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
76
+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
77
+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
78
+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
79
+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
0 80
new file mode 100755
... ...
@@ -0,0 +1,268 @@
1
+<?php
2
+
3
+# this script converts the IBAN_registry.txt file's entries to registry.txt format (php-iban's required internal format).
4
+
5
+# init
6
+require_once(dirname(dirname(__FILE__)) . '/php-iban.php');
7
+date_default_timezone_set('UTC'); # mutes a warning
8
+
9
+# read registry
10
+$data = file_get_contents('IBAN_Registry.txt');
11
+if($data == '') { die("Couldn't read IBAN_Registry.txt - try downloading from the location described in the REGISTRY-URL file."); }
12
+
13
+# print header line
14
+print "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\n";
15
+
16
+# break in to lines
17
+$lines = preg_split('/[\r\n]+/',$data);
18
+
19
+# display
20
+foreach($lines as $line) {
21
+ # if it's not a blank line, and it's not the header row
22
+ if($line != '' && !preg_match('/SEPA Country/',$line)) {
23
+  # extract individual tab-separated fields
24
+  $bits = explode("\t",$line);
25
+  # remove quotes and superfluous whitespace on fields that have them.
26
+  for($i=0;$i<count($bits);$i++) {
27
+   $bits[$i] = preg_replace('/^"(.*)"$/','$1',$bits[$i]);
28
+   $bits[$i] = preg_replace('/^ */','',$bits[$i]);
29
+   $bits[$i] = preg_replace('/ *$/','',$bits[$i]);
30
+  }
31
+  # assigned fields to named variables
32
+  list($country_name,$country_code,$domestic_example,$bban,$bban_structure,$bban_length,$bban_bi_position,$bban_bi_length,$bban_bi_example,$bban_example,$iban,$iban_structure,$iban_length,$iban_electronic_example,$iban_print_example,$country_sepa,$contact_details) = $bits;
33
+  # sanitise
34
+  $country_code = strtoupper(substr($country_code,0,2));       # sanitise comments away
35
+  $bban_structure = preg_replace('/[:;]/','',$bban_structure); # errors seen in Germany, Hungary entries
36
+  $iban_structure = preg_replace('/, .*$/','',$iban_structure); # duplicates for FO, GL seen in DK
37
+  $iban_electronic_example = preg_replace('/, .*$/','',$iban_electronic_example); # duplicates for FO, GL seen in DK
38
+  if($country_code=='MU') {
39
+   $iban_electronic_example = str_replace(' ','',$iban_electronic_example); # MU example has a spurious space
40
+  }
41
+  if($country_code=='CZ') {
42
+   $iban_electronic_example = preg_replace('/ \w{10,}+$/','',$iban_electronic_example); # extra example for CZ
43
+   $iban_print_example = preg_replace('/^(CZ.. .... .... .... .... ....).*$/','$1',$iban_print_example); # extra example
44
+  }
45
+  if($country_code=='FI') {
46
+   # remove additional example
47
+   $iban_electronic_example = preg_replace('/ or .*$/','',$iban_electronic_example);
48
+   # fix bban example to remove verbosity and match domestic example
49
+   $bban = '12345600000785';
50
+  }
51
+  $iban_print_example = preg_replace('/, .*$/','',$iban_print_example); # DK includes FO and GL examples in one record
52
+
53
+ # debugging
54
+ if(false) {
<