home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Programming / ICU / src / icu / source / samples / XMLConverter / XMLConverter.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-19  |  30.9 KB  |  1,056 lines

  1. /*
  2. *******************************************************************************
  3. *                                                                             *
  4. * COPYRIGHT:                                                                  *
  5. *   (C) Copyright International Business Machines Corporation, 1998, 1999     *
  6. *   Licensed Material - Program-Property of IBM - All Rights Reserved.        *
  7. *   US Government Users Restricted Rights - Use, duplication, or disclosure   *
  8. *   restricted by GSA ADP Schedule Contract with IBM Corp.                    *
  9. *                                                                             *
  10. *******************************************************************************
  11. *
  12. */
  13. // XMLConverter.cpp
  14. // To convert one encoded XML file to another
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <assert.h>
  20.  
  21. #ifdef _WIN32
  22. #  include <windows.h>
  23. #endif
  24.  
  25. #include "utypes.h"
  26. #include "ustring.h"
  27. #include "ucnv.h"
  28. #include "ucnv_err.h"
  29. #include "uloc.h"
  30. #include "uchar.h"
  31.  
  32. #define MAXFILENAMELEN  1024
  33. #define RAWBUFSIZE       4096
  34. #define ENCODINGCOUNT   5
  35. #define FIRSTLINEBUF    256
  36. typedef unsigned char  BYTE;
  37.  
  38.  
  39. char firstLine[128];
  40. char encodingNameInFile[256];
  41. bool verbose = false;
  42.  
  43. extern void convertFile(char*, char*, char*, UConverter*);
  44. extern void usage();
  45. extern void printChars(unsigned char*, int);
  46. extern int getInputEncodingType(const BYTE* rawBuffer, 
  47.                                 unsigned long byteCount);
  48. extern long convertFirstLine(FILE* inF, 
  49.                              char* inEncName, 
  50.                              FILE* outF, 
  51.                              char* outEncName, 
  52.                              char* ptrBuf, 
  53.                              unsigned long toRead, 
  54.                              UChar* uBuf);
  55. extern void catString(char* thisString, bool quote);
  56. extern int32_t  XMLUConvert( UConverter* inConverter,
  57.                       UConverter* outConverter,
  58.                       const char* inBuffer, 
  59.                       int32_t* inBufSize, 
  60.                       char* outBuffer, 
  61.                       int32_t outBufCapacity, 
  62.                       bool_t flush,
  63.                       UErrorCode* err);
  64. extern void XMLU_fromCodepageToCodepage(    UConverter*    outConverter,
  65.                         UConverter*    inConverter,
  66.                         char**         target,
  67.                         const char*        targetLimit,
  68.                         const char**        source,
  69.                         const char*        sourceLimit,
  70.                         int32_t*        offsets,
  71.                         bool_t            flush,
  72.                         UErrorCode*        err);
  73.  
  74. static const BYTE    gEBCDICPre[]    = { 0x4C, 0x6F, 0xA7, 0x94 };
  75. #if 0
  76. //not supported encodings
  77. static const BYTE    gUCS4BPre[]     = { 0x00, 0x00, 0x00, 0x3C };
  78. static const BYTE    gUCS4LPre[]     = { 0x3C, 0x00, 0x00, 0x00 };
  79. #endif 
  80. static const BYTE    gUTF16BPre[]    = { 0x00, 0x3C, 0x00, 0x3F };
  81. static const BYTE    gUTF16LPre[]    = { 0x3C, 0x00, 0x3F, 0x00 };
  82. static const char    gXMLDecl_ASCII[]= { 0x3C, 0x3F, 0x78, 0x6D, 0x6C };
  83.  
  84. enum Encodings
  85.     {
  86.         EBCDIC          = 0,
  87.         UCS_4B          = 1,
  88.         UCS_4L          = 2,
  89.         US_ASCII        = 3,
  90.         UTF_8           = 4,
  91.         UTF_16B         = 5,
  92.         UTF_16L         = 6,
  93.  
  94.         Encodings_Count = ENCODINGCOUNT,
  95.         Encodings_Min   = EBCDIC,
  96.         Encodings_Max   = UTF_16L,
  97.  
  98.         OtherEncoding   = 999
  99.     };
  100.  
  101.  
  102. void usage(char *  exeName)
  103. {
  104.     fprintf(stdout, "\n USAGE: \n \t%s [-h] [-v] -e trgEncName inputFile outputFile \n\n", exeName);
  105.     fprintf(stdout, " %s    = Exe name \n ", exeName);
  106.     fprintf(stdout, "-h     \t= to get help (this information!) \n ");
  107.     fprintf(stdout, "-v     \t= set verbose on; \n \t\t  to get more information about the conversion process \n ");
  108.     fprintf(stdout, "-e     \t= This is a mandatory option and follows with the targetEncName");
  109.     fprintf(stdout, "       \t\t  E.g., output encoding can be like : \n \t\t  ascii, utf8, utf-16be, utf-16le, ebcdic-cp-us \n");
  110.     fprintf(stdout, "trgEncName  \t= The output encoding type needed. \n \t\t  It always should follow the -e switch\n");
  111.     fprintf(stdout, "inputFile     \t= The input XML file name \n");
  112.     fprintf(stdout, "outputFile    \t= The output XML file name \n");
  113.     fprintf(stdout, " \n For example: \n ");
  114.     fprintf(stdout, " \t %s -e utf8 pr-utf-16.xml pr-utf-8.xml \n\n\n ", exeName);
  115. }
  116.  
  117.  
  118.  
  119. int main(int argc, char** argv)
  120. {
  121.     UErrorCode err = U_ZERO_ERROR;
  122.     char* inFileName; 
  123.     char* outFileName;
  124.     char * encName = NULL;
  125.  
  126.     UConverter*  conv = NULL;
  127.  
  128.     for (int i=0; i< argc; i++)
  129.     {
  130.         if (!strcmp( argv[i], "-h") || (argc < 5) )
  131.         {
  132.             usage(argv[0]);
  133.             exit(1);
  134.         }
  135.         if (!strcmp( argv[i], "-v"))
  136.             verbose = true;
  137.         if (!strcmp( argv[i], "-e"))
  138.         {
  139.             if ( argc == i+4)
  140.             {
  141.                 encName = new char[strlen(argv[i+1]) +1];
  142.                 strcpy(encName, argv[i+1]);
  143.                 inFileName = new char[strlen(argv[i+2]) +1];
  144.                 strcpy(inFileName, argv[i+2]);
  145.                 outFileName = new char[strlen(argv[i+3]) +1];
  146.                 strcpy(outFileName, argv[i+3]);
  147.                 break;
  148.             }
  149.             else
  150.             {
  151.                 usage(argv[0]);
  152.                 exit(1);
  153.             }
  154.         }
  155.     }
  156.  
  157.     conv = ucnv_open(encName, &err);
  158.     if (U_FAILURE(err))
  159.     {
  160.         if (verbose)
  161.         {
  162.             fprintf(stderr, "Could not create converter to: %s\n", encName);
  163. #if defined(_DEBUG) && defined(XP_CPLUSPLUS)
  164.             fprintf (stderr,"FAILURE! (%s) (%d)\n", errorName(err), err);
  165. #endif
  166.         }
  167.         ucnv_close(conv);
  168.         exit(1);
  169.     }
  170.     
  171.     fprintf(stdout, "Converting %s to %s...\n", inFileName, outFileName);
  172.     convertFile(encName, inFileName, outFileName, conv);
  173.     fprintf(stdout, "Finished transcoding file: %s\n", inFileName);
  174.     
  175.     ucnv_close(conv);
  176.     if (encName)
  177.         delete encName;
  178.     return 0;
  179. }
  180.  
  181. void convertFile(char* encName, char* iFN, char* oFN, UConverter* outConvrtr)
  182. {
  183.     //Read the input file
  184.     //
  185.     FILE* inFile = fopen( iFN, "rb");
  186.     if (inFile == NULL) {
  187.         if (verbose)
  188.             fprintf(stderr, "Could not open input file - %s for reading \n", iFN);
  189.         exit(1);
  190.     }
  191.  
  192.     FILE*   outFile = fopen(oFN, "wb");
  193.     if (outFile == NULL)
  194.     {
  195.         if (verbose)
  196.             fprintf(stderr, "Could not open output file - %s for writing \n", oFN);
  197.         fclose(inFile);
  198.         return;
  199.     }
  200.  
  201.     char            rawBuf[RAWBUFSIZE];
  202.     char*           pRawBuf     = NULL;
  203.     unsigned long   bytesRead   = 0;
  204.     UErrorCode       err         = U_ZERO_ERROR;
  205.     
  206.     //get the file size
  207.     //
  208.     unsigned int    curPos      = ftell(inFile);
  209.  
  210.     if(verbose)
  211.       fprintf(stderr, "curPos = %d\n", curPos);
  212.  
  213.     if (curPos == 0xFFFFFFFF)
  214.     {
  215.         fprintf(stderr, "fileSize - Could not save current pos \n");
  216.         exit(1);
  217.     }
  218.  
  219.     // Seek to the end and save that value for return
  220.     //
  221.     if ( fseek(inFile, 0 , SEEK_END) )
  222.     {
  223.         fprintf(stderr, "fileSize - Could not seek to end \n");
  224.         exit(1);
  225.     }
  226.  
  227.     const unsigned int endPos = ftell(inFile);
  228.     if (endPos == 0xFFFFFFFF)
  229.     {
  230.         fprintf(stderr, "fileSize - Could not get the end pos \n");
  231.         exit(1);
  232.     }
  233.  
  234.     // And put the pointer back
  235.     //
  236.     if (fseek(inFile, curPos, SEEK_SET))
  237.     {
  238.         fprintf(stderr, "fileSize - Could not seek back to original pos \n");
  239.         exit(1);
  240.     }
  241.  
  242.     if (curPos >= endPos) 
  243.     {
  244.         fprintf(stderr,"Reached end of input file while reading \n");
  245.         exit(1);
  246.     } 
  247.     
  248.     unsigned int    bytesLeft   = endPos - curPos; 
  249.     if (verbose)
  250.         fprintf(stdout,"Input file size is %d \n", bytesLeft);
  251.     
  252.     unsigned int toRead = (RAWBUFSIZE > bytesLeft) ? bytesLeft : RAWBUFSIZE;
  253.     
  254.     //Read the infile    
  255.     //
  256.     bytesRead = fread( (void*)rawBuf, 1, toRead, inFile);
  257.     if (ferror(inFile)) 
  258.     {
  259.         fprintf(stderr," couldnot read file for input encoding \n");
  260.         exit(1);
  261.     }
  262.     
  263.     if (bytesRead ==  0) 
  264.     {
  265.         fprintf(stderr," couldnot fill raw buffer \n");
  266.         exit(1);
  267.     }
  268.     pRawBuf = rawBuf;
  269.  
  270.     // get the input encoding type
  271.     int inputEnc = getInputEncodingType((const BYTE*)rawBuf, bytesRead); 
  272.     if (inputEnc == OtherEncoding)
  273.     {
  274.         fprintf(stderr, " Unknown encoded input file. \n Only input encodings supported in the first line are \n");
  275.         fprintf(stderr, " ascii, ebcdic-cp-us, utf8, utf-16be, utf-16le \n");
  276.         exit(1);
  277.     }
  278.     
  279.     //transcoding the first line from inEncodName to ascii and then replacing
  280.     //the encoding=inEncodingName to encoding=outEncodingName
  281.     //
  282.     
  283.     UChar          ucBuf[RAWBUFSIZE];
  284.     char * inEncodName;
  285.     char* tmpPtr = (char*) rawBuf;
  286.     
  287.     //get the input encoding name
  288.     //
  289.     switch (inputEnc)
  290.     {
  291.     case 0 : 
  292.         inEncodName = new char[strlen("ebcdic-cp-us") +1];
  293.         strcpy(inEncodName, "ebcdic-cp-us");
  294.         break;
  295.     case 3 :
  296.         inEncodName = new char[strlen("ascii") +1];
  297.         strcpy(inEncodName, "ascii");
  298.         break;
  299.     case 4 :
  300.         inEncodName = new char[strlen("utf8") +1];
  301.         strcpy(inEncodName, "utf8");
  302.         break;
  303.     case 5 :
  304.         inEncodName = new char[strlen("utf-16be") +1];
  305.         strcpy(inEncodName, "utf-16be");
  306.         break;
  307.     case 6 :
  308.         inEncodName = new char[strlen("utf-16le") +1];
  309.         strcpy(inEncodName, "utf-16le");
  310.         break;
  311.     default :
  312.         break;
  313.     };
  314.  
  315.     if(verbose)
  316.       {
  317.     fprintf(stderr, "inConverter = %s\n", inEncodName);
  318.       }
  319.     
  320.     UConverter* inConvrtr = ucnv_open(inEncodName, &err);
  321.     //now read and transcode the input to output file
  322.     //Process the firstline separately
  323.     //
  324.     long afterFirstLine = convertFirstLine(inFile, inEncodName, outFile, encName, 
  325.                        pRawBuf, toRead, (UChar*)ucBuf);
  326.     
  327.     //move the pointer after the first line
  328.     //
  329.     if (fseek(inFile, (unsigned long) afterFirstLine, SEEK_SET))
  330.     {
  331.         fprintf(stderr, "fileSize - Could not set the cursor to %d after the first line \n", afterFirstLine);
  332.         exit(1);
  333.     }
  334.     else
  335.       if(verbose)
  336.     fprintf(stderr,"Seeked to %d OK \n", afterFirstLine);
  337.     bytesLeft = endPos - afterFirstLine;
  338.     toRead = (RAWBUFSIZE > bytesLeft) ? bytesLeft : RAWBUFSIZE;
  339.     
  340.     //  read the rest of the input file
  341.     //
  342.     if (verbose)
  343.         fprintf(stdout,"The first line consists of %d bytes \n", afterFirstLine);
  344.     if (encodingNameInFile !=NULL) 
  345.     {
  346.         if (inEncodName)
  347.             delete inEncodName;
  348.         inEncodName = new char[strlen(encodingNameInFile)+1];
  349.         strcpy(inEncodName, encodingNameInFile);
  350.         ucnv_close(inConvrtr);
  351.         inConvrtr = ucnv_open(inEncodName, &err);
  352.     }
  353.     if (verbose)
  354.         fprintf(stdout, "Input Encoding type = %s,  Output Encoding type = %s \n", inEncodName, encName);
  355.     
  356.     char *outBuf = new char[RAWBUFSIZE];
  357.     int  outBufSize = RAWBUFSIZE;
  358.     bool tFlush = false;
  359.     err = U_ZERO_ERROR;
  360.    
  361.     if (verbose)
  362.         fprintf(stdout, "processing the rest of the file \n");
  363.     while( (bytesRead = fread((void *) rawBuf, 1, toRead, inFile)) > 0 || !tFlush)
  364.     {
  365.          int32_t  bytesNeeded = XMLUConvert( inConvrtr,
  366.                       outConvrtr,
  367.                       pRawBuf, 
  368.                       (int32_t*)&bytesRead, 
  369.                       outBuf, 
  370.                       outBufSize, 
  371.                       tFlush,
  372.                       &err);
  373.          if (bytesNeeded > 0)
  374.          {
  375.              long bout =
  376.                  fwrite((void *) outBuf, 1, bytesNeeded, outFile);
  377.              if (bout != bytesNeeded)
  378.              {
  379.                  fprintf(stderr, "Wrote only %d bytes.\n", bout);
  380.                  fclose(inFile);
  381.                  fclose(outFile);
  382.              }
  383.          }
  384.  
  385.         if ((err != U_BUFFER_OVERFLOW_ERROR) && U_FAILURE(err) )
  386.         {
  387. #if defined(_DEBUG)
  388.             fprintf (stderr, "Error transcoding rest of the file: (%s) %d\n", errorName(err), err);
  389. #endif
  390.             fclose(inFile);
  391.             fclose(outFile);
  392.             exit(1);
  393.         }
  394.         if ((bytesRead > 0) && (err !=U_ZERO_ERROR))
  395.         {
  396.       if(verbose)
  397.         fprintf(stderr, "err=%d * read %d bytes\n", err,bytesRead);
  398.  
  399.             if (fseek(inFile, (curPos+bytesRead), SEEK_SET))
  400.             {
  401.                 fprintf(stderr, "fileSize - Could not set the input cursor to %d (curpos=%d, bytesRead=%d)\n", curPos+bytesRead,curPos,bytesRead);
  402.                 exit(1);
  403.             }
  404.             curPos = ftell(inFile);
  405.             bytesLeft = endPos - curPos;
  406.         }
  407.         else 
  408.         {
  409.             curPos = ftell(inFile);
  410.             bytesLeft = endPos - curPos;
  411.         }
  412.         toRead = (RAWBUFSIZE > bytesLeft) ? bytesLeft : RAWBUFSIZE;
  413.         if (toRead < RAWBUFSIZE) tFlush = true;
  414.         if (err == U_BUFFER_OVERFLOW_ERROR)
  415.             err = U_ZERO_ERROR;
  416.     }
  417.     ucnv_close(inConvrtr);
  418.     delete inEncodName;
  419.     fclose(inFile);
  420.     fclose(outFile);
  421. };
  422.  
  423.  
  424.  
  425. int getInputEncodingType(const BYTE* rawBuffer, unsigned long byteCount)
  426. {
  427.     //match the first four bytes of the input buffer with the encoding types available
  428.     //checking for ASCII
  429.     //
  430.     if (byteCount > 5)  
  431.     {
  432.         if (!memcmp(rawBuffer, gXMLDecl_ASCII, 5))
  433.         return US_ASCII;
  434.     }
  435.      
  436.     //  If the count of raw bytes is less than 2, it cannot be anything
  437.     //  we understand, so return UTF-8 as a fallback.
  438.     //
  439.     if (byteCount < 2)
  440.         return  UTF_8;
  441.  
  442.     //  We know its at least two bytes, so lets check for a UTF-16 BOM. 
  443.     //
  444.     if ((rawBuffer[0] == 0xFE) && (rawBuffer[1] == 0xFF))
  445.         return UTF_16B;
  446.     else if ((rawBuffer[0] == 0xFF) && (rawBuffer[1] == 0xFE))
  447.         return UTF_16L;
  448.     
  449.     //  Oh well, not one of those. So now lets see if we have at least 4
  450.     //  bytes. If not, then we are out of ideas and can return UTF-8 as the
  451.     //  fallback.
  452.     //
  453.     if (byteCount < 4)
  454.         return OtherEncoding;
  455.     
  456.     //  We have at least 4 bytes. So lets check the 4 byte sequences that
  457.     //  indicate other UTF-16 encodings.
  458.     //
  459.     if ((rawBuffer[0] == 0x00) || (rawBuffer[0] == 0x3C))
  460.     {
  461. #if 0
  462.         //not supported encodings
  463.         if (!memcmp(rawBuffer, gUCS4BPre, 4))
  464.             return UCS_4B;
  465.         else if (!memcmp(rawBuffer, gUCS4LPre, 4))
  466.             return UCS_4L;
  467.         else 
  468. #endif
  469.             if (!memcmp(rawBuffer, gUTF16BPre, 4))
  470.             return UTF_16B;
  471.         else if (!memcmp(rawBuffer, gUTF16LPre, 4))
  472.             return UTF_16L;
  473.     }
  474.     
  475.     //  See if we have enough bytes to possibly match the EBCDIC prefix.
  476.     //  If so, try it.
  477.     //
  478.     if (!memcmp(rawBuffer, gEBCDICPre, 4))
  479.          return EBCDIC;
  480.  
  481.     //  Does not seem to be anything we know, so go with UTF-8 to get at
  482.     //  least through the first line and see what it really is.
  483.     //
  484.     return OtherEncoding;
  485. }
  486.  
  487.  
  488. long convertFirstLine( FILE* inF, char* inEncName, 
  489.                        FILE* outF, char* outEncName, 
  490.                        char* ptrBuf, unsigned long toRead, 
  491.                        UChar* uBuf)
  492. {
  493.     //Here we read the inputFile with the specified buffer size.
  494.     //Then convert this to ascii. then read the first line and convert to 
  495.     //output and input encoding types and return for rest of the conversion
  496.     //
  497.  
  498.     if (fseek(inF, 0, SEEK_SET))
  499.     {
  500.         fprintf(stderr, "file - Could not seek the begin pos \n");
  501.         exit(1);
  502.     }
  503.  
  504.     unsigned long bytesRead = fread( (void*)ptrBuf, 1, toRead, inF);
  505.  
  506.     char            tempBuf[RAWBUFSIZE];
  507.     int             bufLength       = 0;
  508.     long            bytesNeeded     = 0;
  509.     UErrorCode      err             = U_ZERO_ERROR;
  510.  
  511.     bytesNeeded = ucnv_convert("ascii",
  512.             inEncName,
  513.             (char*) tempBuf,
  514.             0,
  515.             (const char*) ptrBuf,
  516.             bytesRead,
  517.             &err);
  518.     
  519.     if (err == U_BUFFER_OVERFLOW_ERROR)
  520.     {
  521.         err = U_ZERO_ERROR;
  522.     }
  523.     else if (U_FAILURE(err))
  524.     {
  525. #if defined(_DEBUG)
  526.         printf ("Error transcoding first line of input file: (%s) %d\n", errorName(err), err);
  527. #endif
  528.         fclose(inF);
  529.         fclose(outF);
  530.         exit(1);
  531.     }
  532.  
  533.     ucnv_convert("ascii",
  534.             inEncName,
  535.             (char*) tempBuf,
  536.             bytesNeeded,
  537.             (const char*) ptrBuf,
  538.             bytesRead,
  539.             &err);                                         
  540.  
  541.     if (U_FAILURE(err))
  542.     {
  543. #if defined(_DEBUG)
  544.         printf ("Error transcoding2 first line of input file: (%s) %d\n", errorName(err), err);
  545. #endif
  546.         fclose(inF);
  547.         fclose(outF);
  548.         exit(1);
  549.     } 
  550.     else
  551.     {
  552.         //read the tempBuf to get the first line
  553.         //
  554.         char firstLineBuf[FIRSTLINEBUF];
  555.         int tempBufLength = 0;
  556.                 
  557.         for( bufLength = 0,  tempBufLength=0; bufLength < FIRSTLINEBUF; bufLength++, tempBufLength++)
  558.         {
  559.             if ((tempBufLength == 0) && ((inEncName == "utf-16be") || (inEncName == "utf-16le") || (inEncName == "utf16")) )
  560.                 tempBufLength++;
  561.             firstLineBuf[bufLength] = (char)tempBuf[tempBufLength];
  562.             if (tempBuf[tempBufLength] == 0x3E) {
  563.                 firstLineBuf[bufLength+1] = '\0';
  564.                 break;
  565.             }
  566.             
  567.         }
  568.         char* pFLB = new char[sizeof(firstLineBuf) +1];
  569.         strcpy(pFLB, firstLineBuf);
  570.  
  571.         //if the file doesnot contain the version string line then its and illegal file
  572.         //
  573.         if (firstLineBuf[0] != 0x3C ) 
  574.         {
  575.               fprintf(stderr,"Illegal xml file: It doesnot contain the xml declaration statement on the first line \n");
  576.               fclose(inF);
  577.               fclose(outF);
  578.               exit(1);
  579.         }
  580.      
  581.         bool encString      = true;
  582.         bool stdString      = true;
  583.         bool encInsertMid   = false;
  584.         bool encInsertLast  = false;
  585.         bool dQuote         = true;
  586.         char* doubleQuote   = "\"";
  587.         char* singleQuote   = "\'";
  588.         
  589.         if (!strstr( (const char*)pFLB, doubleQuote))
  590.         {
  591.             if (!strstr( (const char*)pFLB, singleQuote))
  592.             {
  593.               fprintf(stderr,"Illegal xml file: It doesnot contain the approprite xml declaration \n");
  594.               fclose(inF);
  595.               fclose(outF);
  596.               exit(1);
  597.             }
  598.             dQuote = false;
  599.         }
  600.         
  601.         char* newString     = strstr( (const char*) pFLB, "encoding");
  602.         char* stringWithEnc = 0;
  603.  
  604.         if (!newString)
  605.             encString = false;
  606.         else 
  607.       {
  608.         stringWithEnc = new char[strlen(newString)+1];
  609.             strcpy(stringWithEnc, newString);
  610.       }
  611.             
  612.         newString = strstr( (const char*) pFLB, "standalone");
  613.         char* stringWithStd = 0;
  614.         if (!newString) 
  615.             stdString = false;
  616.         else
  617.         {
  618.         stringWithStd = new char[strlen(newString)+1];
  619.             strcpy(stringWithStd, newString);
  620.        }
  621.         
  622.         if (!encString && !stdString)
  623.              encInsertLast = true;
  624.         if (!encString && stdString)
  625.              encInsertMid = true;
  626.  
  627.         //Encodingname for the rest of the input file could be different. 
  628.         //If its not specified in the  first line then assume it to be UTF8
  629.         if (encInsertLast || encInsertMid)
  630.         {
  631.             //if the encoding type was found utf16 family or ebcdic and 
  632.             // the encoding string is not present in the file then its an error
  633.             if (!strcmp(inEncName, "utf-16be") 
  634.                 || !strcmp(inEncName, "utf-16le")
  635.                 || !strcmp(inEncName, "ebcdic-cp-us"))
  636.             {
  637.                 fprintf(stderr, "Illegal xml file: it doesnot contain the encoding string in the first line of the input file\n");
  638.                 fclose(inF);
  639.                 fclose(outF);
  640.                 exit(1);
  641.             }
  642.             strcpy(encodingNameInFile, inEncName);
  643.         }
  644.  
  645.         char* tempString    = " encoding=";
  646.         char* dupFLB        = strdup(pFLB);
  647.     int stringTwoLength = 0;
  648.  
  649.     /* build up the length */
  650.     stringTwoLength = bufLength;
  651.  
  652.     if(tempString)
  653.       stringTwoLength += strlen(tempString);
  654.  
  655.     if(outEncName)
  656.       stringTwoLength += strlen(outEncName);
  657.  
  658.     if(stringWithStd)
  659.       stringTwoLength += strlen(stringWithStd);
  660.  
  661.     stringTwoLength   += 5;
  662.     
  663.         char* stringTwo     = new char[stringTwoLength];
  664.  
  665.         if (encInsertLast) {
  666.             char* stringOne = new char[bufLength];
  667.             strncpy(stringOne, pFLB, bufLength-1);
  668.             strcpy(stringOne+bufLength-1, "");
  669.             stringTwo = strcpy(stringTwo, stringOne);
  670.             strcat(stringTwo, tempString);
  671.             catString(stringTwo, dQuote);
  672.             strcat(stringTwo, outEncName);
  673.             catString(stringTwo, dQuote);
  674.             strcat(stringTwo , " ?>");
  675.             delete stringOne;
  676.         }
  677.         //insert the string before 'standalone' statement
  678.         else if (encInsertMid) {
  679.             char* stringThree = new char[bufLength + strlen(tempString) + strlen(outEncName) + 5];
  680.             if (dQuote)         
  681.                 stringThree = strtok(dupFLB, doubleQuote);
  682.             else
  683.                 stringThree = strtok(dupFLB, singleQuote);
  684.  
  685.             strcpy(stringTwo, stringThree);
  686.             catString(stringTwo, dQuote);
  687.  
  688.             char* tmpString;
  689.             if (dQuote)
  690.                 tmpString = strtok(0, doubleQuote);
  691.             else
  692.                 tmpString = strtok(0, singleQuote);
  693.             if (tmpString != NULL)
  694.                 strcat(stringTwo, tmpString);
  695.             
  696.             catString(stringTwo, dQuote);
  697.             strcat(stringTwo, tempString);
  698.             catString(stringTwo, dQuote);
  699.  
  700.             strcat(stringTwo, outEncName);
  701.             if (dQuote)
  702.                 strcat(stringTwo, "\" ");
  703.             else
  704.                 strcat(stringTwo, "\' ");
  705.             strcat(stringTwo, stringWithStd);
  706.             delete stringThree;
  707.         }
  708.         //if the encoding string is there then modify the output encoding name in it.
  709.         else if (encString)
  710.         {
  711.             char* stringFive  = new char[strlen(dupFLB)+1];
  712.                     
  713.             if (dQuote)
  714.                 stringFive = strtok (dupFLB, doubleQuote);
  715.             else
  716.                 stringFive = strtok (dupFLB, singleQuote);
  717.  
  718.             strcpy(stringTwo, stringFive);
  719.             catString(stringTwo, dQuote);
  720.             while (stringFive != NULL)
  721.             {
  722.                 if (dQuote)
  723.                     stringFive = strtok(0,doubleQuote);
  724.                 else
  725.                     stringFive = strtok(0,singleQuote);
  726.  
  727.                 if (stringFive == NULL)
  728.                     break;
  729.                 strcat(stringTwo, stringFive);
  730.                 
  731.                 char* n1String = strstr(stringFive, ">");
  732.                 if (!n1String)
  733.                     catString(stringTwo, dQuote);
  734.                 
  735.                 char* nString = strstr(stringFive, "encoding");
  736.                 if (nString) 
  737.                 {
  738.                     strcat(stringTwo, outEncName);
  739.                     if (dQuote)
  740.                         stringFive = strtok(0, doubleQuote);
  741.                     else
  742.                         stringFive = strtok(0, singleQuote);
  743.                     strcpy(encodingNameInFile, stringFive); //this is the encoded string name
  744.                     catString(stringTwo, dQuote);
  745.                 }
  746.             }
  747.             if (stringFive != NULL)
  748.             {
  749.                 delete stringFive;
  750.                 stringFive = 0;
  751.             }
  752.         }
  753.       
  754.         // introduce the first order bytes for utf16 be and le files
  755.         //
  756.         if (!strcmp(outEncName, "utf-16be") || !strcmp(outEncName, "utf16"))
  757.         {
  758.             uBuf[0] = 0xFE;
  759.             fwrite( (void*) uBuf, 1, 1, outF);
  760.             uBuf[0] = 0xFF;
  761.             fwrite( (void*) uBuf, 1, 1, outF);
  762.         } else if (!strcmp(outEncName , "utf-16le"))
  763.         {
  764.            uBuf[0] = 0xFF;
  765.            fwrite( (void*) uBuf, 1, 1, outF);
  766.            uBuf[0] = 0xFE;
  767.            fwrite( (void*) uBuf, 1, 1, outF);
  768.         }
  769.  
  770.         err = U_ZERO_ERROR;
  771.         long oneChar = 0;
  772.         while ( *stringTwo != '\0' )
  773.         {
  774.             //transcode character-by-character
  775.             oneChar = ucnv_convert(outEncName,
  776.                 "ascii",
  777.                 (char*) uBuf,
  778.                 0,
  779.                 (const char*) stringTwo,
  780.                 1,
  781.                 &err);
  782.             if (err == U_BUFFER_OVERFLOW_ERROR)
  783.             {
  784.                 err = U_ZERO_ERROR;
  785.             }
  786.             else if (U_FAILURE(err))
  787.             {
  788. #if defined(_DEBUG)
  789.                 fprintf (stderr, "Error transcoding char-by-char: (%s) %d\n", errorName(err), err);
  790. #endif
  791.                 fclose(inF);
  792.                 fclose(outF);
  793.                 exit(1);
  794.             }
  795.  
  796.             ucnv_convert(outEncName,
  797.                 "ascii",
  798.                 (char*) uBuf,
  799.                 oneChar,
  800.                 (const char*) stringTwo,
  801.                 1,
  802.                 &err);
  803.             if (U_FAILURE(err))
  804.             {
  805. #if defined(_DEBUG)
  806.                 fprintf (stderr, "Error transcoding2 char-by-char: (%s) %d\n", errorName(err), err);
  807. #endif
  808.                 fclose(inF);
  809.                 fclose(outF);
  810.                 exit(1);
  811.             } 
  812.             fwrite( (void*) uBuf, 1, oneChar, outF);
  813.             stringTwo++;
  814.         }
  815.     }
  816.     
  817.  
  818.     //Now get the pointer offset after the first line in the input file 
  819.     //and return this position
  820.     //
  821.     char* newInEncName  = new char[strlen(inEncName) +1];
  822.     strcpy(newInEncName, inEncName);
  823.     if (encodingNameInFile !=NULL) 
  824.     {
  825.         if (inEncName)
  826.             delete newInEncName;
  827.         newInEncName = new char[strlen(encodingNameInFile)+1];
  828.         strcpy(newInEncName, encodingNameInFile);
  829.     }
  830.  
  831.      char   oldBuf[RAWBUFSIZE];   
  832.      int    bufHere    = bufLength +1;
  833.      if (!strcmp(newInEncName, "utf-16be") || !strcmp(newInEncName, "utf16") || !strcmp(newInEncName, "utf-16le")) 
  834.      {
  835.          bufHere +=1;
  836.         memcpy((void*)oldBuf, (void*) tempBuf, bufHere);
  837.      }
  838.      else
  839.               memcpy((void*)oldBuf, (void*) tempBuf, bufHere);
  840.      
  841.      char   newBuf[RAWBUFSIZE];
  842.      long   endBytes    = 0;    
  843.      //transcode this ascii type to the input encoding type  
  844.      //and get the pointer to the end of first line in the input buffer 
  845.      //
  846.      err = U_ZERO_ERROR;
  847.      endBytes = ucnv_convert(newInEncName,
  848.              "ascii",
  849.             (char*) newBuf,
  850.             0,
  851.             (const char*) oldBuf,
  852.             bufHere,
  853.             &err);
  854.     
  855.     if (err == U_BUFFER_OVERFLOW_ERROR)
  856.     {
  857.         err = U_ZERO_ERROR;
  858.     }
  859.     else if (U_FAILURE(err))
  860.     {
  861. #if defined(_DEBUG)
  862.         fprintf (stderr, "Error transcoding from ascii to input encoding: (%s) %d\n", errorName(err), err);
  863. #endif
  864.         fclose(inF);
  865.         fclose(outF);
  866.         exit(1);
  867.     }
  868.     ucnv_convert(newInEncName,
  869.             "ascii",
  870.             (char*) newBuf,
  871.             endBytes,
  872.             (const char*) oldBuf,
  873.             bufHere,
  874.             &err);                                         
  875.     if (U_FAILURE(err))
  876.     {
  877. #if defined(_DEBUG)
  878.         fprintf (stderr, "Error transcoding2 from ascii to input encoding: (%s) %d\n", errorName(err), err);
  879. #endif
  880.         delete newInEncName;
  881.         fclose(inF);
  882.         fclose(outF);
  883.         exit(1);
  884.     }
  885.     
  886.     return endBytes;
  887. }
  888.  
  889.  
  890. int32_t  XMLUConvert( UConverter* inConverter,
  891.                       UConverter* outConverter,
  892.                       const char* inBuffer, 
  893.                       int32_t* inBufSize, 
  894.                       char* outBuffer, 
  895.                       int32_t outBufCapacity, 
  896.                       bool_t flush,
  897.                       UErrorCode* err)
  898. {
  899.     const char* inBufferAlias = inBuffer;
  900.     char* outBufferAlias = outBuffer;
  901.     const char* inBufferEnd = inBuffer + *inBufSize;
  902.     const char* outBufferEnd = outBuffer + outBufCapacity;
  903.     //const char* consumed;
  904.     
  905.     if (U_FAILURE(*err)) return 0;
  906.     
  907.     XMLU_fromCodepageToCodepage(outConverter,
  908.         inConverter,
  909.         &outBufferAlias, 
  910.         outBufferEnd, 
  911.         &inBufferAlias, 
  912.         inBufferEnd, 
  913.         NULL, 
  914.         flush,
  915.         err);
  916.     
  917.     if (*err == U_INDEX_OUTOFBOUNDS_ERROR) *err = U_BUFFER_OVERFLOW_ERROR;
  918.     
  919.    // *inBufSize = inBufferAlias;
  920.     return outBufferAlias - outBuffer;
  921. }
  922.  
  923. void XMLU_fromCodepageToCodepage(    UConverter*    outConverter,
  924.                         UConverter*    inConverter,
  925.                         char**         target,
  926.                         const char*    targetLimit,
  927.                         const char**   source,
  928.                         const char*    sourceLimit,
  929.                         int32_t*       offsets,
  930.                         bool_t         flush,
  931.                         UErrorCode*    err)
  932. {
  933.     
  934. #if 0
  935.     UChar out_chunk[RAWBUFSIZE];
  936.     const UChar* out_chunk_limit = out_chunk + RAWBUFSIZE;
  937.     UChar* out_chunk_alias;
  938.     UChar const* out_chunk_alias2;
  939.     UChar const* consumed_UChars;
  940.     
  941.     
  942.     if (U_FAILURE(*err)) return;
  943.     
  944.     *consumed = *source;
  945.     /*loops until the input buffer is completely consumed
  946.     *or if an error has be encountered
  947.     *first we convert from inConverter codepage to Unicode
  948.     *then from Unicode to outConverter codepage
  949.     */
  950.     
  951.     while ((sourceLimit != *source) && U_SUCCESS(*err))
  952.     {
  953.         out_chunk_alias = out_chunk;
  954.         *source = *consumed;
  955.         ucnv_reset(inConverter);
  956.         ucnv_toUnicode(inConverter,
  957.             &out_chunk_alias,
  958.             out_chunk_limit,
  959.             source,
  960.             sourceLimit,
  961.             consumed,
  962.             flush,
  963.             err);
  964.         
  965.             /*U_INDEX_OUTOFBOUNDS_ERROR means that the output "CHUNK" is full
  966.             *we will require at least another loop (it's a recoverable error)
  967.         */
  968.         
  969.         if (U_SUCCESS(*err) || (*err == U_INDEX_OUTOFBOUNDS_ERROR))
  970.         {
  971.             *err = U_ZERO_ERROR;
  972.             out_chunk_alias2 = out_chunk;
  973.             
  974.             while ((out_chunk_alias2 != out_chunk_alias) && U_SUCCESS(*err))
  975.             {
  976.                 ucnv_fromUnicode(outConverter,
  977.                     target,
  978.                     targetLimit,
  979.                     &out_chunk_alias2,
  980.                     out_chunk_alias,
  981.                     &consumed_UChars,
  982.                     FALSE,
  983.                     err); 
  984.                 
  985.             }
  986.         }
  987.         else break;
  988.     }
  989.     return;
  990.  
  991. #endif
  992.  
  993.  
  994.   UChar out_chunk[RAWBUFSIZE];
  995.   const UChar *out_chunk_limit = out_chunk + RAWBUFSIZE;
  996.   UChar *out_chunk_alias;
  997.   UChar const *out_chunk_alias2;
  998.  
  999.  
  1000.   if (U_FAILURE (*err))    return;
  1001.  
  1002.  
  1003.   /*loops until the input buffer is completely consumed
  1004.    *or if an error has be encountered
  1005.    *first we convert from inConverter codepage to Unicode
  1006.    *then from Unicode to outConverter codepage
  1007.    */
  1008.   while ((*source != sourceLimit) && U_SUCCESS (*err))
  1009.     {
  1010.       out_chunk_alias = out_chunk;
  1011.       ucnv_toUnicode (inConverter,
  1012.               &out_chunk_alias,
  1013.               out_chunk_limit,
  1014.               source,
  1015.               sourceLimit,
  1016.               NULL,
  1017.               flush,
  1018.               err);
  1019.  
  1020.       /*U_INDEX_OUTOFBOUNDS_ERROR means that the output "CHUNK" is full
  1021.        *we will require at least another loop (it's a recoverable error)
  1022.        */
  1023.  
  1024.       if (U_SUCCESS (*err) || (*err == U_INDEX_OUTOFBOUNDS_ERROR))
  1025.     {
  1026.       *err = U_ZERO_ERROR;
  1027.       out_chunk_alias2 = out_chunk;
  1028.  
  1029.       while ((out_chunk_alias2 != out_chunk_alias) && U_SUCCESS (*err))
  1030.         {
  1031.           ucnv_fromUnicode (outConverter,
  1032.                 target,
  1033.                 targetLimit,
  1034.                 &out_chunk_alias2,
  1035.                 out_chunk_alias,
  1036.                 NULL,
  1037.                 TRUE,
  1038.                 err);
  1039.  
  1040.         }
  1041.     }
  1042.       else
  1043.     break;
  1044.     }
  1045.  
  1046.   return;
  1047. }
  1048.  
  1049. void catString(char* thisString, bool quote)
  1050. {
  1051.     if (quote)
  1052.         strcat(thisString, "\"");
  1053.     else
  1054.         strcat(thisString, "\'");
  1055. }
  1056.