checkiban.c - randomcrap - random crap programs of varying quality
(HTM) git clone git://git.codemadness.org/randomcrap
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
checkiban.c (2398B)
---
1 /* Simple IBAN number checker */
2 #include <stdio.h>
3 #include <string.h>
4
5 #if 0
6 /* modulo large number */
7 int
8 mod(const char *s, int a)
9 {
10 int i, r = 0;
11
12 for (i = 0; s[i]; i++)
13 r = (r * 10 + (int)s[i] - '0') % a;
14
15 return r;
16 }
17 #endif
18
19 /* filter and fixup some characters from user input */
20 int
21 filter(const char *s, char *buf, size_t bufsiz)
22 {
23 size_t i, j;
24
25 if (bufsiz <= strlen(s))
26 return 0;
27
28 for (i = 0, j = 0; s[i]; i++) {
29 if (s[i] == '.' || s[i] == ' ')
30 ; /* skip */
31 else if ((s[i] >= 'a' && s[i] <= 'z'))
32 buf[j++] = (s[i] - 'a') + 'A'; /* uppercase */
33 else
34 buf[j++] = s[i];
35 }
36 buf[j] = '\0';
37
38 return 1;
39 }
40
41 /* general check if its a valid format, returns 1 if OK otherwise 0 */
42 int
43 isvalid(const char *s)
44 {
45 size_t i;
46
47 for (i = 0; s[i]; i++) {
48 if (!(s[i] >= 'A' && s[i] <= 'Z') &&
49 !(s[i] >= '0' && s[i] <= '9'))
50 return 0;
51 }
52 /* general length check */
53 if (i < 16 || i >= 34)
54 return 0;
55
56 /* general country code prefix check */
57 if (!(s[0] >= 'A' && s[0] <= 'Z') ||
58 !(s[1] >= 'A' && s[1] <= 'Z'))
59 return 0;
60
61 /* checksum prefix */
62 if (!(s[2] >= '0' && s[2] <= '9') ||
63 !(s[3] >= '0' && s[3] <= '9'))
64 return 0;
65
66 /* checksum range */
67 i = ((s[2] - '0') * 10) + (s[3] - '0');
68 if (!(i >= 2 && i <= 98))
69 return 0;
70
71 return 1;
72 }
73
74 /* assumes valid IBAN input, returns 1 if OK, otherwise 0 */
75 int
76 check(const char *s)
77 {
78 int i, n, mod = 0;
79
80 for (i = 4; s[i]; i++) {
81 if (s[i] >= 'A' && s[i] <= 'Z') {
82 n = (s[i] - 'A' + 10);
83 mod = ((mod * 10) + (n / 10)) % 97;
84 mod = ((mod * 10) + (n % 10)) % 97;
85 } else if (s[i] >= '0' && s[i] <= '9') {
86 mod = ((mod * 10) + (s[i] - '0')) % 97;
87 }
88 }
89 for (i = 0; i < 4 && s[i]; i++) {
90 if (s[i] >= 'A' && s[i] <= 'Z') {
91 n = (s[i] - 'A' + 10);
92 mod = ((mod * 10) + (n / 10)) % 97;
93 mod = ((mod * 10) + (n % 10)) % 97;
94 } else if (s[i] >= '0' && s[i] <= '9') {
95 mod = ((mod * 10) + (s[i] - '0')) % 97;
96 }
97 }
98 return mod == 1;
99 }
100
101 int
102 main(int argc, char *argv[])
103 {
104 char buf[36];
105 int r;
106
107 if (argc != 2) {
108 fprintf(stderr, "usage: %s <IBAN>\n", argv[0]);
109 return 2;
110 }
111
112 if (!filter(argv[1], buf, sizeof(buf))) {
113 fprintf(stderr, "invalid format\n");
114 return 1;
115 }
116 if (!isvalid(buf)) {
117 fprintf(stderr, "invalid format\n");
118 return 1;
119 }
120
121 r = check(buf);
122 fprintf(stderr, "%s %svalid\n", buf, r ? "" : "in");
123
124 /* exitcode 0 if valid, 1 on invalid, 2 on usage */
125 return !r;
126 }