Subversion Repositories oidconverter

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*###################################################################
  2. ###                                                               ###
  3. ### Object ID converter. Matthias Gaertner, 06/1999               ###
  4. ### Converted to plain 'C' 07/2001                                ###
  5. ###                                                               ###
  6. ### Enhanced version by Daniel Marschall, ViaThinkSoft 06/2011    ###
  7. ### -- NEW 1.2: 2.48 can also be encoded!                         ###
  8. ### -- NEW 1.2: UUIDs (128-bit) are now supported!                ###
  9. ###             (requires GMPLib)                                 ###
  10. ### -- NEW 1.3: Length can now have more than 1 byte              ###
  11. ### -- NEW 1.4: No command line limitation anymore.               ###
  12. ### -- AS WELL AS SEVERAL BUG FIXES                               ###
  13. ###                                                               ###
  14. ### To compile with gcc simply use:                               ###
  15. ###   gcc -O2 -o oid oid.c -lgmp -lm                              ###
  16. ###                                                               ###
  17. ### To compile using cl, use:                                     ###
  18. ###   cl -DWIN32 -O1 oid.c (+ include gmp library)                ###
  19. ###                                                               ###
  20. ### Freeware - do with it whatever you want.                      ###
  21. ### Use at your own risk. No warranty of any kind.                ###
  22. ###                                                               ###
  23. ###################################################################*/
  24. /* $Version: 1.4$ */
  25.  
  26. // MINOR PROBLEMS:
  27. // - A wrong error message is shown when trying to encode "-0.0" or "x"
  28.  
  29. // NICE TO HAVE:
  30. // - makefile / linuxpackage
  31. // - better make functions instead of putting everything in main() with fprintf...
  32.  
  33. // NICE TO HAVE (INFINITY-IDEA - NOT IMPORTANT):
  34. // - Is it possible to detect integer overflows and therefore output errors?
  35.  
  36. // -------------------------------------------------------
  37.  
  38. // Allows OIDs which are bigger than "long"
  39. // Compile with "gcc oid.c -lgmp -lm"
  40. #define is_gmp
  41.  
  42. #include <stdio.h>
  43. #include <string.h>
  44. #include <stdlib.h>
  45.  
  46. #ifdef is_gmp
  47. #include <gmp.h>
  48. #endif
  49.  
  50. #include <stdbool.h>
  51.  
  52. #ifndef __STRNICMP_LOCAL
  53. #ifdef WIN32
  54. #define __STRNICMP_LOCAL strnicmp
  55. #else
  56. #define __STRNICMP_LOCAL strncasecmp
  57. #endif
  58. #endif
  59.  
  60. // char abCommandLine[4096];
  61. const unsigned int CLI_INITIAL_SIZE = 1024;
  62. const unsigned int CLI_EXPANSION_SIZE = 1024;
  63. unsigned int cli_size;
  64. char * abCommandLine;
  65.  
  66. // unsigned char abBinary[128];
  67. const unsigned int ABB_INITIAL_SIZE = 1024;
  68. const unsigned int ABB_EXPANSION_SIZE = 1024;
  69. unsigned int abb_size;
  70. unsigned char * abBinary;
  71.  
  72. unsigned int    nBinary = 0;
  73.  
  74.  
  75. #ifdef is_gmp
  76. static void MakeBase128( mpz_t l, int first ) {
  77.         if ( mpz_cmp_si(l, 127) > 0 ) {
  78.                 mpz_t l2;
  79.                 mpz_init(l2);
  80.                 mpz_div_ui(l2, l, 128);
  81.                 MakeBase128( l2 , 0 );
  82.         }
  83.         mpz_mod_ui(l, l, 128);
  84.  
  85.         if (nBinary+1 >= abb_size) {
  86.                 abb_size += ABB_EXPANSION_SIZE;
  87.                 abBinary = (unsigned char*) realloc(abBinary, abb_size);
  88.                 if (abBinary == NULL) {
  89.                         fprintf(stderr, "Memory reallocation failure!\n");
  90.                         exit(EXIT_FAILURE);
  91.                 }
  92.         }
  93.  
  94.         if ( first ) {
  95.                 abBinary[nBinary++] = mpz_get_ui(l);
  96.         } else {
  97.                 abBinary[nBinary++] = 0x80 | mpz_get_ui(l);
  98.         }
  99. }
  100. #else
  101. static void MakeBase128( unsigned long l, int first ) {
  102.         if ( l > 127 ) {
  103.                 MakeBase128( l / 128, 0 );
  104.         }
  105.         l %= 128;
  106.  
  107.         if (nBinary+1 >= abb_size) {
  108.                 abb_size += ABB_EXPANSION_SIZE;
  109.                 abBinary = (unsigned char*) realloc(abBinary, abb_size);
  110.                 if (abBinary == NULL) {
  111.                         fprintf(stderr, "Memory reallocation failure!\n");
  112.                         exit(EXIT_FAILURE);
  113.                 }
  114.         }
  115.  
  116.         if ( first ) {
  117.                 abBinary[nBinary++] = (unsigned char)l;
  118.         } else {
  119.                 abBinary[nBinary++] = 0x80 | (unsigned char)l;
  120.         }
  121. }
  122. #endif
  123.  
  124. int main( int argc, char **argv ) {
  125.         cli_size = CLI_INITIAL_SIZE;
  126.         abCommandLine  = (char*) malloc(cli_size * sizeof(char*));
  127.         if (abCommandLine == NULL) {
  128.                 fprintf(stderr, "Memory allocation failure!\n");
  129.                 return EXIT_FAILURE;
  130.         }
  131.  
  132.         abb_size = ABB_INITIAL_SIZE;
  133.         abBinary  = (unsigned char*) malloc(abb_size * sizeof(unsigned char*));
  134.         if (abBinary == NULL) {
  135.                 fprintf(stderr, "Memory allocation failure!\n");
  136.                 return EXIT_FAILURE;
  137.         }
  138.  
  139.  
  140.         char *fOutName = NULL;
  141.         char *fInName = NULL;
  142.         FILE *fOut = NULL;
  143.  
  144.         int n = 1;
  145.         int nMode = 0;  /* dotted->hex */
  146.         int nCHex = 0;
  147.         int nAfterOption = 0;
  148.  
  149.         if ( argc == 1 ) {
  150.                 fprintf( stderr,
  151.                 "OID encoder/decoder 1.4 - Matthias Gaertner 1999/2001, Daniel Marschall 2011 - Freeware\n"
  152.                 #ifdef is_gmp
  153.                 "GMP Edition\n"
  154.                 #endif
  155.                 "\nUsage:\n"
  156.                 " OID [-C] [-o<outfile>] {-i<infile>|2.999.1}\n"
  157.                 "   converts dotted form to ASCII HEX DER output.\n"
  158.                 " OID -x [-o<outfile>] {-i<infile>|hex-digits}\n"
  159.                 "   decodes ASCII HEX DER and gives dotted form.\n" );
  160.                 return 1;
  161.         }
  162.  
  163.         while ( n < argc ) {
  164.                 if ( !nAfterOption && argv[n][0] == '-' ) {
  165.                         if ( argv[n][1] == 'x' ) {
  166.                                 nMode = 1;      /* hex->dotted */
  167.                                 if ( argv[n][2] != '\0' ) {
  168.                                         argv[n--] += 2;
  169.                                         nAfterOption = 1;
  170.                                 }
  171.                         } else if ( argv[n][1] == 'C' ) {
  172.                                 nMode = 0;
  173.                                 nCHex = 1;
  174.  
  175.                                 if ( argv[n][2] != '\0' ) {
  176.                                         argv[n--] += 2;
  177.                                         nAfterOption = 1;
  178.                                 }
  179.                         } else if ( argv[n][1] == 'o' ) {
  180.                                 if ( argv[n][2] != '\0' ) {
  181.                                         fOutName = &argv[n][2];
  182.                                 } else if ( n < argc-1 ) {
  183.                                         fOutName = argv[++n];
  184.                                 } else {
  185.                                         fprintf(stderr,"Incomplete command line.\n");
  186.                                 }
  187.                         } else if ( argv[n][1] == 'i' ) {
  188.                                 if ( argv[n][2] != '\0' ) {
  189.                                         fInName = &argv[n][2];
  190.                                 } else if ( n < argc-1 ) {
  191.                                         fInName = argv[++n];
  192.                                 } else {
  193.                                         fprintf(stderr,"Incomplete command line.\n");
  194.                                 }
  195.                         }
  196.                 } else {
  197.                         if ( fInName != NULL ) {
  198.                                 break;
  199.                         }
  200.  
  201.                         nAfterOption = 1;
  202.                         if ( strlen( argv[n] ) + strlen( abCommandLine ) >= sizeof(abCommandLine)-2 ) {
  203.                                 // fprintf(stderr,"Command line too long.\n");
  204.                                 // return 2;
  205.  
  206.                                 cli_size += CLI_EXPANSION_SIZE + strlen( argv[n] ) + 1; // 1 = "."
  207.                                 abCommandLine = (char*) realloc(abCommandLine, cli_size);
  208.                                 if (abCommandLine == NULL) {
  209.                                         fprintf(stderr, "Memory reallocation failure!\n");
  210.                                         return EXIT_FAILURE;
  211.                                 }
  212.                                 // TODO: (Unklar) Wer garantiert, dass es mit "\0" abschließt?
  213.                         }
  214.                         strcat( abCommandLine, argv[n] );
  215.                         if ( n != argc - 1 && nMode != 1 ) {
  216.                                 strcat( abCommandLine, "." );
  217.                         }
  218.                 }
  219.                 n++;
  220.         }
  221.  
  222.         if ( fInName != NULL && nMode == 1 ) {
  223.                 FILE *fIn = fopen( fInName, "rb" );
  224.                 size_t nRead = 0;
  225.                 if ( fIn == NULL ) {
  226.                         fprintf(stderr,"Unable to open input file %s.\n", fInName );
  227.                         return 11;
  228.                 }
  229.                 nRead = fread( abCommandLine, 1, sizeof(abCommandLine), fIn );
  230.                 abCommandLine[nRead] = '\0';
  231.                 fclose( fIn );
  232.         } else if ( fInName != NULL && nMode == 0 ) {
  233.                 FILE *fIn = fopen( fInName, "rt" );
  234.                 if ( fIn == NULL ) {
  235.                         fprintf(stderr,"Unable to open input file %s.\n", fInName );
  236.                         return 11;
  237.                 }
  238.                 fgets( abCommandLine, sizeof(abCommandLine), fIn );
  239.                 fclose( fIn );
  240.         }
  241.  
  242.         while ( nMode == 1 )    /* better if */
  243.         {
  244.                 /* hex->dotted */
  245.                 /*printf("Hex-In: %s\n", abCommandLine );*/
  246.  
  247.                 char *p = abCommandLine;
  248.                 char *q = p;
  249.  
  250.                 unsigned char *pb = NULL;
  251.                 unsigned int nn = 0;
  252.                 #ifdef is_gmp
  253.                 mpz_t ll;
  254.                 mpz_init(ll);
  255.                 #else
  256.                 unsigned long ll = 0;
  257.                 #endif
  258.                 bool fOK = false;
  259.                 int fSub = 0; // Subtract value from next number output. Used when encoding {2 48} and up
  260.  
  261.                 while ( *p ) {
  262.                         if ( *p != '.' && *p != '\r' && *p != '\n' && *p != '\x20' && *p != '\t') {
  263.                                 *q++ = *p;
  264.                         }
  265.                         p++;
  266.                 }
  267.                 *q = '\0';
  268.  
  269.                 if ( strlen( abCommandLine ) % 2 != 0 ) {
  270.                         fprintf(stderr, "Encoded OID must have even number of hex digits!\n" );
  271.                         return 2;
  272.                 }
  273.  
  274.                 if ( strlen( abCommandLine ) < 3 ) {
  275.                         fprintf(stderr, "Encoded OID must have at least three bytes!\n" );
  276.                         return 2;
  277.                 }
  278.  
  279.                 nBinary = 0;
  280.                 p = abCommandLine;
  281.  
  282.                 while ( *p ) {
  283.                         unsigned char b;
  284.  
  285.                         // Interpret upper nibble
  286.                         if ( p[0] >= 'A' && p[0] <= 'F' ) {
  287.                                 b = (p[0] - 'A' + 10) * 16;
  288.                         } else if ( p[0] >= 'a' && p[0] <= 'f' ) {
  289.                                 b = (p[0] - 'a' + 10) * 16;
  290.                         } else if ( p[0] >= '0' && p[0] <= '9' ) {
  291.                                 b = (p[0] - '0') * 16;
  292.                         } else {
  293.                                 fprintf(stderr, "Must have hex digits only!\n" );
  294.                                 return 2;
  295.                         }
  296.  
  297.                         // Interpret lower nibble
  298.                         if ( p[1] >= 'A' && p[1] <= 'F' ) {
  299.                                 b += (p[1] - 'A' + 10);
  300.                         } else if ( p[1] >= 'a' && p[1] <= 'f' ) {
  301.                                 b += (p[1] - 'a' + 10);
  302.                         } else if ( p[1] >= '0' && p[1] <= '9' ) {
  303.                                 b += (p[1] - '0');
  304.                         } else {
  305.                                 fprintf(stderr, "Must have hex digits only!\n" );
  306.                                 return 2;
  307.                         }
  308.  
  309.                         if (nBinary+1 >= abb_size) {
  310.                                 abb_size += ABB_EXPANSION_SIZE;
  311.                                 abBinary = (unsigned char*) realloc(abBinary, abb_size);
  312.                                 if (abBinary == NULL) {
  313.                                         fprintf(stderr, "Memory reallocation failure!\n");
  314.                                         return EXIT_FAILURE;
  315.                                 }
  316.                         }
  317.  
  318.                         abBinary[nBinary++] = b;
  319.                         p += 2;
  320.                 }
  321.  
  322.                 /*printf("Hex-In: %s\n", abCommandLine );*/
  323.  
  324.                 if ( fOutName != NULL ) {
  325.                         fOut = fopen( fOutName, "wt" );
  326.                         if ( fOut == NULL ) {
  327.                                 fprintf(stderr,"Unable to open output file %s\n", fOutName );
  328.                                 return 33;
  329.                         }
  330.                 } else {
  331.                         fOut = stdout;
  332.                 }
  333.  
  334.                 pb = abBinary;
  335.                 nn = 0;
  336.                 #ifdef is_gmp
  337.                 mpz_init(ll);
  338.                 #else
  339.                 ll = 0;
  340.                 #endif
  341.                 fOK = false;
  342.                 fSub = 0;
  343.  
  344.                 // 0 = Universal Class Identifier Tag
  345.                 // 1 = Length part (may have more than 1 byte!)
  346.                 // 2 = First two arc encoding
  347.                 // 3 = Encoding of arc three and higher
  348.                 unsigned char part = 0;
  349.  
  350.                 unsigned char lengthbyte_count = 0;
  351.                 unsigned char lengthbyte_pos = 0;
  352.                 bool lengthfinished = false;
  353.  
  354.                 while ( nn < nBinary ) {
  355.                         if ( part == 0 ) { // Class Tag
  356.                                 unsigned char cl = ((*pb & 0xC0) >> 6) & 0x03;
  357.                                 switch ( cl ) {
  358.                                         default:
  359.                                         case 0: fprintf(fOut,"UNIVERSAL"); break;
  360.                                         case 1: fprintf(fOut,"APPLICATION"); break;
  361.                                         case 2: fprintf(fOut,"CONTEXT"); break;
  362.                                         case 3: fprintf(fOut,"PRIVATE"); break;
  363.                                 }
  364.                                 fprintf(fOut," OID");
  365.                                 part++;
  366.                         } else if ( part == 1 ) { // Length
  367.  
  368.                                 // Find out the length and save it into ll
  369.  
  370.                                 // 2nd Byte
  371.                                 // 0x00 .. 0x7F => The actual length
  372.                                 // 0x80 + n => The length is spread over the following 'n' bytes
  373.                                 // (Unknown: Is 'n' limited or can it be until 0xFF is reached?)
  374.                                 // (Unknown: How is length=0x80 (=0 following bytes define the length) defined? Is it the same as 0x00?)
  375.  
  376.                                 if (nn == 1) { // The first length byte
  377.                                         lengthbyte_pos = 0;
  378.                                         if ( (*pb & 0x80) != 0 ) {
  379.                                                 // 0x80 + n => The length is spread over the following 'n' bytes
  380.                                                 lengthfinished = false;
  381.                                                 lengthbyte_count = *pb & 0x7F;
  382.                                                 fOK = false;
  383.                                         } else {
  384.                                                 // 0x00 .. 0x7F => The actual length
  385.                                                 #ifdef is_gmp
  386.                                                 mpz_set_ui(ll, *pb);
  387.                                                 #else
  388.                                                 ll = *pb;
  389.                                                 #endif
  390.                                                 lengthfinished = true;
  391.                                                 lengthbyte_count = 0;
  392.                                                 fOK = true;
  393.                                         }
  394.                                 } else {
  395.                                         if (lengthbyte_count > lengthbyte_pos) {
  396.                                                 #ifdef is_gmp
  397.                                                 mpz_mul_ui(ll, ll, 0x100);
  398.                                                 mpz_add_ui(ll, ll, *pb);
  399.                                                 #else
  400.                                                 ll *= 0x100;
  401.                                                 ll += *pb;
  402.                                                 #endif
  403.                                                 lengthbyte_pos++;
  404.                                         }
  405.  
  406.                                         if (lengthbyte_count == lengthbyte_pos) {
  407.                                                 lengthfinished = true;
  408.                                                 fOK = true;
  409.                                         }
  410.                                 }
  411.  
  412.                                 if (lengthfinished) { // The length is now in ll
  413.                                         #ifdef is_gmp
  414.                                         if ( mpz_cmp_ui(ll,  nBinary - 2 - lengthbyte_count) != 0 ) {
  415.                                                 fprintf(fOut,"\n");
  416.                                                 if ( fOut != stdout ) {
  417.                                                         fclose( fOut );
  418.                                                 }
  419.                                                 fprintf(stderr,"\nInvalid length (%d entered, but %s expected)\n", nBinary - 2, mpz_get_str(NULL, 10, ll) );
  420.                                                 return 3;
  421.                                         }
  422.                                         mpz_set_ui(ll, 0); // reset for later usage
  423.                                         #else
  424.                                         if ( ll != nBinary - 2 - lengthbyte_count ) {
  425.                                                 fprintf(fOut,"\n");
  426.                                                 if ( fOut != stdout ) {
  427.                                                         fclose( fOut );
  428.                                                 }
  429.                                                 fprintf(stderr,"\nInvalid length (%d entered, but %d expected)\n", nBinary - 2, ll );
  430.                                                 return 3;
  431.                                         }
  432.                                         ll = 0; // reset for later usage
  433.                                         #endif
  434.                                         fOK = true;
  435.                                         part++;
  436.                                 }
  437.                         } else if ( part == 2 ) { // First two arcs
  438.                                 int first = *pb / 40;
  439.                                 int second = *pb % 40;
  440.                                 if (first > 2) {
  441.                                         first = 2;
  442.                                         fprintf(fOut,".%d", first );
  443.  
  444.                                         if ( (*pb & 0x80) != 0 ) {
  445.                                                 // 2.48 and up => 2+ octets
  446.                                                 #ifdef is_gmp
  447.                                                 mpz_add_ui(ll, ll, (*pb & 0x7F));
  448.                                                 #else
  449.                                                 ll += (*pb & 0x7F);
  450.                                                 #endif
  451.                                                 fSub = 80;
  452.                                                 fOK = false;
  453.                                         } else {
  454.                                                 // 2.0 till 2.47 => 1 octet
  455.                                                 second = *pb - 80;
  456.                                                 fprintf(fOut,".%d",second);
  457.                                                 fOK = true;
  458.                                                 #ifdef is_gmp
  459.                                                 mpz_set_ui(ll, 0);
  460.                                                 #else
  461.                                                 ll = 0;
  462.                                                 #endif
  463.                                         }
  464.                                 } else {
  465.                                         // 0.0 till 0.37 => 1 octet
  466.                                         // 1.0 till 1.37 => 1 octet
  467.                                         fprintf(fOut,".%d.%d", first, second );
  468.                                         fOK = true;
  469.                                         #ifdef is_gmp
  470.                                         mpz_set_ui(ll, 0);
  471.                                         #else
  472.                                         ll = 0;
  473.                                         #endif
  474.                                 }
  475.                                 part++;
  476.                         } else if ( part == 3 ) { // Arc three and higher
  477.                                 if ( (*pb & 0x80) != 0 ) {
  478.                                         #ifdef is_gmp
  479.                                         mpz_mul_ui(ll, ll, 128);
  480.                                         mpz_add_ui(ll, ll, (*pb & 0x7F));
  481.                                         #else
  482.                                         ll *= 128;
  483.                                         ll += (*pb & 0x7F);
  484.                                         #endif
  485.                                         fOK = false;
  486.                                 } else {
  487.                                         #ifdef is_gmp
  488.                                         mpz_mul_ui(ll, ll, 128);
  489.                                         mpz_add_ui(ll, ll, *pb);
  490.                                         mpz_sub_ui(ll, ll, fSub);
  491.                                         fprintf(fOut,".%s", mpz_get_str(NULL, 10, ll) );
  492.                                         mpz_set_ui(ll, 0);
  493.                                         #else
  494.                                         ll *= 128;
  495.                                         ll += *pb;
  496.                                         ll -= fSub;
  497.                                         fprintf(fOut,".%lu", ll );
  498.                                         ll = 0;
  499.                                         #endif
  500.                                         fSub = 0;
  501.                                         fOK = true;
  502.                                 }
  503.                         }
  504.  
  505.                         pb++;
  506.                         nn++;
  507.                 }
  508.  
  509.                 if ( !fOK ) {
  510.                         fprintf(fOut,"\n");
  511.                         if ( fOut != stdout ) {
  512.                                 fclose( fOut );
  513.                         }
  514.                         fprintf(stderr,"\nEncoding error. The OID is not constructed properly.\n");
  515.                         return 4;
  516.                 } else {
  517.                         fprintf(fOut,"\n");
  518.                 }
  519.  
  520.                 if ( fOut != stdout ) {
  521.                         fclose( fOut );
  522.                 }
  523.                 break;
  524.         };
  525.  
  526.         while ( nMode == 0 )    /* better if */
  527.         {
  528.                 /* dotted->hex */
  529.                 /* printf("OID.%s\n", abCommandLine ); */
  530.  
  531.                 char *p = abCommandLine;
  532.                 unsigned char cl = 0x00;
  533.                 char *q = NULL;
  534.                 int nPieces = 1;
  535.                 int n = 0;
  536.                 unsigned char b = 0;
  537.                 unsigned int nn = 0;
  538.                 #ifdef is_gmp
  539.                 mpz_t l;
  540.                 #else
  541.                 unsigned long l = 0;
  542.                 #endif
  543.                 bool isjoint = false;
  544.  
  545.                 if ( __STRNICMP_LOCAL( p, "UNIVERSAL.", 10 ) == 0 ) {
  546.                         p+=10;
  547.                 } else if ( __STRNICMP_LOCAL( p, "APPLICATION.", 12 ) == 0 ) {
  548.                         cl = 0x40;
  549.                         p+=12;
  550.                 } else if ( __STRNICMP_LOCAL( p, "CONTEXT.", 8 ) == 0 ) {
  551.                         cl = 0x80;
  552.                         p+=8;
  553.                 } else if ( __STRNICMP_LOCAL( p, "PRIVATE.", 8 ) == 0 ) {
  554.                         cl = 0xC0;
  555.                         p+=8;
  556.                 }
  557.  
  558.                 if ( __STRNICMP_LOCAL( p, "OID.", 4 ) == 0 ) {
  559.                         p+=4;
  560.                 }
  561.  
  562.                 q = p;
  563.                 nPieces = 1;
  564.                 while ( *p ) {
  565.                         if ( *p == '.' ) {
  566.                                 nPieces++;
  567.                         }
  568.                         p++;
  569.                 }
  570.  
  571.                 n = 0;
  572.                 b = 0;
  573.                 p = q;
  574.                 while ( n < nPieces ) {
  575.                         q = p;
  576.                         while ( *p ) {
  577.                                 if ( *p == '.' ) {
  578.                                         break;
  579.                                 }
  580.                                 p++;
  581.                         }
  582.  
  583.                         #ifdef is_gmp
  584.                         mpz_init(l);
  585.                         #else
  586.                         l = 0;
  587.                         #endif
  588.                         if ( *p == '.' ) {
  589.                                 *p = 0;
  590.                                 #ifdef is_gmp
  591.                                 mpz_set_str(l, q, 10);
  592.                                 #else
  593.                                 l = (unsigned long) atoi( q );
  594.                                 #endif
  595.                                 q = p+1;
  596.                                 p = q;
  597.                         } else {
  598.                                 #ifdef is_gmp
  599.                                 mpz_set_str(l, q, 10);
  600.                                 #else
  601.                                 l = (unsigned long) atoi( q );
  602.                                 #endif
  603.                                 q = p;
  604.                         }
  605.  
  606.                         /* Digit is in l. */
  607.                         if ( n == 0 ) {
  608.                                 #ifdef is_gmp
  609.                                 if (mpz_cmp_ui(l, 2) > 0) {
  610.                                 #else
  611.                                 if (l > 2) {
  612.                                 #endif
  613.                                         fprintf(stderr,"\nEncoding error. The top arc is limited to 0, 1 and 2.\n");
  614.                                         return 5;
  615.                                 }
  616.                                 #ifdef is_gmp
  617.                                 b += 40 * mpz_get_ui(l);
  618.                                 isjoint = mpz_cmp_ui(l, 2) == 0;
  619.                                 #else
  620.                                 b = 40 * ((unsigned char)l);
  621.                                 isjoint = l == 2;
  622.                                 #endif
  623.                         } else if ( n == 1 ) {
  624.                                 #ifdef is_gmp
  625.                                 if ((mpz_cmp_ui(l, 39) > 0) && (!isjoint)) {
  626.                                 #else
  627.                                 if ((l > 39) && (!isjoint)) {
  628.                                 #endif
  629.                                         fprintf(stderr,"\nEncoding error. The second level is limited to 0..39 for top level arcs 0 and 1.\n");
  630.                                         return 5;
  631.                                 }
  632.  
  633.                                 #ifdef is_gmp
  634.                                 if (mpz_cmp_ui(l, 47) > 0) {
  635.                                         mpz_add_ui(l, l, 80);
  636.                                         MakeBase128( l, 1 );
  637.                                 } else {
  638.                                         b += mpz_get_ui(l);
  639.                                         if (nBinary+1 >= abb_size) {
  640.                                                 abb_size += ABB_EXPANSION_SIZE;
  641.                                                 abBinary = (unsigned char*) realloc(abBinary, abb_size);
  642.                                                 if (abBinary == NULL) {
  643.                                                         fprintf(stderr, "Memory reallocation failure!\n");
  644.                                                         return EXIT_FAILURE;
  645.                                                 }
  646.                                         }
  647.                                         abBinary[nBinary++] = b;
  648.                                 }
  649.                                 #else
  650.                                 if (l > 47) {
  651.                                         l += 80;
  652.                                         MakeBase128( l, 1 );
  653.                                 } else {
  654.                                         b += ((unsigned char) l);
  655.                                         if (nBinary+1 >= abb_size) {
  656.                                                 abb_size += ABB_EXPANSION_SIZE;
  657.                                                 abBinary = (unsigned char*) realloc(abBinary, abb_size);
  658.                                                 if (abBinary == NULL) {
  659.                                                         fprintf(stderr, "Memory reallocation failure!\n");
  660.                                                         return EXIT_FAILURE;
  661.                                                 }
  662.                                         }
  663.                                         abBinary[nBinary++] = b;
  664.                                 }
  665.                                 #endif
  666.                         } else {
  667.                                 MakeBase128( l, 1 );
  668.                         }
  669.                         n++;
  670.                 }
  671.  
  672.                 if (n < 2) {
  673.                         fprintf(stderr,"\nEncoding error. The minimum depth of an encodeable OID is 2. (e.g. 2.999)\n");
  674.                         return 5;
  675.                 }
  676.  
  677.                 if ( fOutName != NULL ) {
  678.                         fOut = fopen( fOutName, "wt" );
  679.                         if ( fOut == NULL ) {
  680.                                 fprintf(stderr,"Unable to open output file %s\n", fOutName );
  681.                                 return 33;
  682.                         }
  683.                 } else {
  684.                         fOut = stdout;
  685.                 }
  686.  
  687.                 if ( nCHex ) {
  688.                         fprintf(fOut,"\"\\x%02X\\x%02X", cl | 6, nBinary );
  689.                 } else {
  690.                         fprintf(fOut,"%02X %02X ", cl | 6, nBinary );
  691.                 }
  692.                 nn = 0;
  693.                 while ( nn < nBinary ) {
  694.                         unsigned char b = abBinary[nn++];
  695.                         if ( nn == nBinary ) {
  696.                                 if ( nCHex ) {
  697.                                         fprintf(fOut,"\\x%02X\"\n", b );
  698.                                 } else {
  699.                                         fprintf(fOut,"%02X\n", b );
  700.                                 }
  701.                         } else {
  702.                                 if ( nCHex ) {
  703.                                         fprintf(fOut,"\\x%02X", b );
  704.                                 } else {
  705.                                         fprintf(fOut,"%02X ", b );
  706.                                 }
  707.                         }
  708.                 }
  709.                 if ( fOut != stdout ) {
  710.                         fclose( fOut );
  711.                 }
  712.                 break;
  713.         }
  714.  
  715.         free(abCommandLine);
  716.         free(abBinary);
  717.  
  718.         return 0;
  719. }
  720.  
  721. /* */
  722.  
  723.