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 }