aboutsummaryrefslogtreecommitdiff
path: root/src/util/payto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/payto.c')
-rw-r--r--src/util/payto.c302
1 files changed, 1 insertions, 301 deletions
diff --git a/src/util/payto.c b/src/util/payto.c
index 9a04f4c3c..58f1bf635 100644
--- a/src/util/payto.c
+++ b/src/util/payto.c
@@ -147,306 +147,6 @@ TALER_xtalerbank_account_from_payto (const char *payto)
147} 147}
148 148
149 149
150/* Country table taken from GNU gettext */
151
152/**
153 * Entry in the country table.
154 */
155struct CountryTableEntry
156{
157 /**
158 * 2-Character international country code.
159 */
160 const char *code;
161
162 /**
163 * Long English name of the country.
164 */
165 const char *english;
166};
167
168
169/* Keep the following table in sync with gettext.
170 WARNING: the entries should stay sorted according to the code */
171/**
172 * List of country codes.
173 */
174static const struct CountryTableEntry country_table[] = {
175 { "AE", "U.A.E." },
176 { "AF", "Afghanistan" },
177 { "AL", "Albania" },
178 { "AM", "Armenia" },
179 { "AN", "Netherlands Antilles" },
180 { "AR", "Argentina" },
181 { "AT", "Austria" },
182 { "AU", "Australia" },
183 { "AZ", "Azerbaijan" },
184 { "BA", "Bosnia and Herzegovina" },
185 { "BD", "Bangladesh" },
186 { "BE", "Belgium" },
187 { "BG", "Bulgaria" },
188 { "BH", "Bahrain" },
189 { "BN", "Brunei Darussalam" },
190 { "BO", "Bolivia" },
191 { "BR", "Brazil" },
192 { "BT", "Bhutan" },
193 { "BY", "Belarus" },
194 { "BZ", "Belize" },
195 { "CA", "Canada" },
196 { "CG", "Congo" },
197 { "CH", "Switzerland" },
198 { "CI", "Cote d'Ivoire" },
199 { "CL", "Chile" },
200 { "CM", "Cameroon" },
201 { "CN", "People's Republic of China" },
202 { "CO", "Colombia" },
203 { "CR", "Costa Rica" },
204 { "CS", "Serbia and Montenegro" },
205 { "CZ", "Czech Republic" },
206 { "DE", "Germany" },
207 { "DK", "Denmark" },
208 { "DO", "Dominican Republic" },
209 { "DZ", "Algeria" },
210 { "EC", "Ecuador" },
211 { "EE", "Estonia" },
212 { "EG", "Egypt" },
213 { "ER", "Eritrea" },
214 { "ES", "Spain" },
215 { "ET", "Ethiopia" },
216 { "FI", "Finland" },
217 { "FO", "Faroe Islands" },
218 { "FR", "France" },
219 { "GB", "United Kingdom" },
220 { "GD", "Caribbean" },
221 { "GE", "Georgia" },
222 { "GL", "Greenland" },
223 { "GR", "Greece" },
224 { "GT", "Guatemala" },
225 { "HK", "Hong Kong" },
226 { "HK", "Hong Kong S.A.R." },
227 { "HN", "Honduras" },
228 { "HR", "Croatia" },
229 { "HT", "Haiti" },
230 { "HU", "Hungary" },
231 { "ID", "Indonesia" },
232 { "IE", "Ireland" },
233 { "IL", "Israel" },
234 { "IN", "India" },
235 { "IQ", "Iraq" },
236 { "IR", "Iran" },
237 { "IS", "Iceland" },
238 { "IT", "Italy" },
239 { "JM", "Jamaica" },
240 { "JO", "Jordan" },
241 { "JP", "Japan" },
242 { "KE", "Kenya" },
243 { "KG", "Kyrgyzstan" },
244 { "KH", "Cambodia" },
245 { "KR", "South Korea" },
246 { "KW", "Kuwait" },
247 { "KZ", "Kazakhstan" },
248 { "LA", "Laos" },
249 { "LB", "Lebanon" },
250 { "LI", "Liechtenstein" },
251 { "LK", "Sri Lanka" },
252 { "LT", "Lithuania" },
253 { "LU", "Luxembourg" },
254 { "LV", "Latvia" },
255 { "LY", "Libya" },
256 { "MA", "Morocco" },
257 { "MC", "Principality of Monaco" },
258 { "MD", "Moldava" },
259 { "MD", "Moldova" },
260 { "ME", "Montenegro" },
261 { "MK", "Former Yugoslav Republic of Macedonia" },
262 { "ML", "Mali" },
263 { "MM", "Myanmar" },
264 { "MN", "Mongolia" },
265 { "MO", "Macau S.A.R." },
266 { "MT", "Malta" },
267 { "MV", "Maldives" },
268 { "MX", "Mexico" },
269 { "MY", "Malaysia" },
270 { "NG", "Nigeria" },
271 { "NI", "Nicaragua" },
272 { "NL", "Netherlands" },
273 { "NO", "Norway" },
274 { "NP", "Nepal" },
275 { "NZ", "New Zealand" },
276 { "OM", "Oman" },
277 { "PA", "Panama" },
278 { "PE", "Peru" },
279 { "PH", "Philippines" },
280 { "PK", "Islamic Republic of Pakistan" },
281 { "PL", "Poland" },
282 { "PR", "Puerto Rico" },
283 { "PT", "Portugal" },
284 { "PY", "Paraguay" },
285 { "QA", "Qatar" },
286 { "RE", "Reunion" },
287 { "RO", "Romania" },
288 { "RS", "Serbia" },
289 { "RU", "Russia" },
290 { "RW", "Rwanda" },
291 { "SA", "Saudi Arabia" },
292 { "SE", "Sweden" },
293 { "SG", "Singapore" },
294 { "SI", "Slovenia" },
295 { "SK", "Slovak" },
296 { "SN", "Senegal" },
297 { "SO", "Somalia" },
298 { "SR", "Suriname" },
299 { "SV", "El Salvador" },
300 { "SY", "Syria" },
301 { "TH", "Thailand" },
302 { "TJ", "Tajikistan" },
303 { "TM", "Turkmenistan" },
304 { "TN", "Tunisia" },
305 { "TR", "Turkey" },
306 { "TT", "Trinidad and Tobago" },
307 { "TW", "Taiwan" },
308 { "TZ", "Tanzania" },
309 { "UA", "Ukraine" },
310 { "US", "United States" },
311 { "UY", "Uruguay" },
312 { "VA", "Vatican" },
313 { "VE", "Venezuela" },
314 { "VN", "Viet Nam" },
315 { "YE", "Yemen" },
316 { "ZA", "South Africa" },
317 { "ZW", "Zimbabwe" }
318};
319
320
321/**
322 * Country code comparator function, for binary search with bsearch().
323 *
324 * @param ptr1 pointer to a `struct table_entry`
325 * @param ptr2 pointer to a `struct table_entry`
326 * @return result of memcmp()'ing the 2-digit country codes of the entries
327 */
328static int
329cmp_country_code (const void *ptr1,
330 const void *ptr2)
331{
332 const struct CountryTableEntry *cc1 = ptr1;
333 const struct CountryTableEntry *cc2 = ptr2;
334
335 return memcmp (cc1->code,
336 cc2->code,
337 2);
338}
339
340
341/**
342 * Validates given IBAN according to the European Banking Standards. See:
343 * http://www.europeanpaymentscouncil.eu/documents/ECBS%20IBAN%20standard%20EBS204_V3.2.pdf
344 *
345 * @param iban the IBAN number to validate
346 * @return NULL if correctly formatted; error message if not
347 */
348static char *
349validate_iban (const char *iban)
350{
351 char cc[2];
352 char ibancpy[35];
353 struct CountryTableEntry cc_entry;
354 unsigned int len;
355 char *nbuf;
356 unsigned long long dividend;
357 unsigned long long remainder;
358 unsigned int i;
359 unsigned int j;
360
361 len = strlen (iban);
362 if (len < 4)
363 return GNUNET_strdup ("IBAN number too short to be valid");
364 if (len > 34)
365 return GNUNET_strdup ("IBAN number too long to be valid");
366 memcpy (cc, iban, 2);
367 memcpy (ibancpy, iban + 4, len - 4);
368 memcpy (ibancpy + len - 4, iban, 4);
369 ibancpy[len] = '\0';
370 cc_entry.code = cc;
371 cc_entry.english = NULL;
372 if (NULL ==
373 bsearch (&cc_entry,
374 country_table,
375 sizeof (country_table) / sizeof (struct CountryTableEntry),
376 sizeof (struct CountryTableEntry),
377 &cmp_country_code))
378 {
379 char *msg;
380
381 GNUNET_asprintf (&msg,
382 "Country code `%c%c' not supported\n",
383 cc[0],
384 cc[1]);
385 return msg;
386 }
387 nbuf = GNUNET_malloc ((len * 2) + 1);
388 for (i = 0, j = 0; i < len; i++)
389 {
390 if (isalpha ((unsigned char) ibancpy[i]))
391 {
392 if (2 != snprintf (&nbuf[j],
393 3,
394 "%2u",
395 (ibancpy[i] - 'A' + 10)))
396 {
397 GNUNET_break (0);
398 return GNUNET_strdup ("internal invariant violation");
399 }
400 j += 2;
401 continue;
402 }
403 nbuf[j] = ibancpy[i];
404 j++;
405 }
406 for (j = 0; '\0' != nbuf[j]; j++)
407 {
408 if (! isdigit ( (unsigned char) nbuf[j]))
409 {
410 char *msg;
411
412 GNUNET_asprintf (&msg,
413 "digit expected at `%s'",
414 &nbuf[j]);
415 GNUNET_free (nbuf);
416 return msg;
417 }
418 }
419 GNUNET_assert (sizeof(dividend) >= 8);
420 remainder = 0;
421 for (unsigned int i = 0; i<j; i += 16)
422 {
423 int nread;
424
425 if (1 !=
426 sscanf (&nbuf[i],
427 "%16llu %n",
428 &dividend,
429 &nread))
430 {
431 char *msg;
432
433 GNUNET_asprintf (&msg,
434 "wrong input for checksum calculation at `%s'",
435 &nbuf[i]);
436 GNUNET_free (nbuf);
437 return msg;
438 }
439 if (0 != remainder)
440 dividend += remainder * (pow (10, nread));
441 remainder = dividend % 97;
442 }
443 GNUNET_free (nbuf);
444 if (1 != remainder)
445 return GNUNET_strdup ("IBAN checksum is wrong");
446 return NULL;
447}
448
449
450/** 150/**
451 * Validate payto://iban/ account URL (only account information, 151 * Validate payto://iban/ account URL (only account information,
452 * wire subject and amount are ignored). 152 * wire subject and amount are ignored).
@@ -483,7 +183,7 @@ validate_payto_iban (const char *account_url)
483 result = GNUNET_strdup (iban); 183 result = GNUNET_strdup (iban);
484 } 184 }
485 if (NULL != 185 if (NULL !=
486 (err = validate_iban (result))) 186 (err = TALER_iban_validate (result)))
487 { 187 {
488 GNUNET_free (result); 188 GNUNET_free (result);
489 return err; 189 return err;