home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 September / Chip_2002-09_cd1.bin / zkuste / vbasic / Data / Utils / XZipComp.exe / XceedEncoding.Cab / F112885_unMain.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-05-11  |  32.3 KB  |  968 lines

  1. /*
  2.   Xceed Binary Encoding Library - Encoding/Decoding Manager sample
  3.   Copyright (c) 2001 Xceed Software Inc.
  4.  
  5.   [unMain.cpp]
  6.                                                                        s
  7.   This sample demonstrate how to encode a file using different kinds of
  8.   encoding methods, and decode and encoded file. It specifically uses:
  9.     - The ProcessFile method
  10.     - The EndOfLineType, MaxLineLength, ContinueOnInvalidData,
  11.       HeaderDataForkLength, HeaderResourceForkLength, HeaderFilename,
  12.       EncodingFormat and DataFormating properties.
  13.  
  14.   This file is part of the Xceed Binary Encoding Library sample applications.
  15.   The source code in this file is only intended as a supplement to the Xceed
  16.   Binary Encoding Library's documentation, and is provided "as is", without
  17.   warranty of any kind, either expressed or implied.
  18. */
  19.  
  20. //---------------------------------------------------------------------------
  21. #include <vcl.h>
  22. #pragma hdrstop
  23.  
  24. #include "unMain.h"
  25. //---------------------------------------------------------------------------
  26. #pragma package(smart_init)
  27. #pragma link "XceedBinaryEncodingLib_OCX"
  28. #pragma resource "*.dfm"
  29. TfrmManager *frmManager;
  30.  
  31. //---------------------------------------------------------------------------
  32. // If a destination file name already exists for the encoding, change
  33. // its extension for a new one appropriate to the new encoding method
  34. //---------------------------------------------------------------------------
  35. void TfrmManager::SetDestinationFileExtension( TEncodingMethod eOldEncodingMethod,
  36.                                                TEncodingMethod eNewEncodingMethod )
  37. {
  38.   AnsiString sDestinationFilename;
  39.   AnsiString sDestinationFilenameExtension;
  40.   bool       bChangedExtension;
  41.  
  42.   bChangedExtension = false;
  43.   sDestinationFilename = edtDestinationFile->Text;
  44.   sDestinationFilenameExtension = ExtractFileExtension( sDestinationFilename.UpperCase() );
  45.  
  46.   // If there is a destination file, we verify if its extension corresponds
  47.   // to the old encoding method. If it corresponds or if there is no extension,
  48.   // we set the flag that will do the change of extension below.
  49.  
  50.   if( sDestinationFilename.Length() != 0 )
  51.   {
  52.     switch( eOldEncodingMethod )
  53.     {
  54.       case emUUEncode :
  55.       {
  56.         if( ( sDestinationFilenameExtension == "UUE" ) || ( sDestinationFilenameExtension.Length() == 0 ) )
  57.         {
  58.           bChangedExtension = true;
  59.           break;
  60.         }
  61.       }
  62.       case emXXEncode :
  63.       {
  64.         if( ( sDestinationFilenameExtension == "XXE" ) || ( sDestinationFilenameExtension.Length() == 0 ) )
  65.         {
  66.           bChangedExtension = true;
  67.           break;
  68.         }
  69.       }
  70.       case emBase64 :
  71.       {
  72.         if( ( sDestinationFilenameExtension == "B64" ) || ( sDestinationFilenameExtension.Length() == 0 ) )
  73.         {
  74.           bChangedExtension = true;
  75.           break;
  76.         }
  77.       }
  78.       case emHexaDecimal :
  79.       {
  80.         if( ( sDestinationFilenameExtension == "HEX" ) || ( sDestinationFilenameExtension.Length() == 0 ) )
  81.         {
  82.           bChangedExtension = true;
  83.           break;
  84.         }
  85.       }
  86.       case emQuotedPrintable :
  87.       {
  88.         if( ( sDestinationFilenameExtension == "QPR" ) || ( sDestinationFilenameExtension.Length() == 0 ) )
  89.         {
  90.           bChangedExtension = true;
  91.           break;
  92.         }
  93.       }
  94.       case emBinHex :
  95.       {
  96.         if( ( sDestinationFilenameExtension == "HQX" ) || ( sDestinationFilenameExtension.Length() == 0 ) )
  97.         {
  98.           bChangedExtension = true;
  99.           break;
  100.         }
  101.       }   
  102.     }
  103.  
  104.     // If we have determined that a change of extension is in order, Do it!
  105.     if( bChangedExtension )
  106.     {
  107.       sDestinationFilename = RemoveFileExtension( sDestinationFilename ) +
  108.                              StdFileExtension( eNewEncodingMethod );
  109.       edtDestinationFile->Text = sDestinationFilename;
  110.     }
  111.   }
  112. }
  113.  
  114. //---------------------------------------------------------------------------
  115. // Set a default destination file name used for the encoding process. This
  116. // file name is derived from the source file name. If a destination file
  117. // name is already specified, do nothing.
  118. //---------------------------------------------------------------------------
  119. void TfrmManager::SetDestinationFilename()
  120. {
  121.   AnsiString sEncodedFilename;
  122.  
  123.   sEncodedFilename = edtDestinationFile->Text;
  124.  
  125.   if( sEncodedFilename.Length() == 0 )
  126.   {
  127.     sEncodedFilename = RemoveFileExtension( edtSourceFileToEncode->Text );
  128.  
  129.     if( sEncodedFilename.Length() != 0 )
  130.     {
  131.       edtDestinationFile->Text = sEncodedFilename;
  132.       SetDestinationFileExtension( m_eEncodingMethod, m_eEncodingMethod );
  133.     }
  134.   }
  135. }
  136.  
  137. //---------------------------------------------------------------------------
  138. // Add the specified file name to the list box of file names to decode
  139. //---------------------------------------------------------------------------
  140. void TfrmManager::AddEncodedFileToList( AnsiString sFilename )
  141. {
  142.   int        i;
  143.   bool       bFound;
  144.   int        nNbItem;
  145.   AnsiString sDecodeFolder;
  146.   AnsiString sExtension;
  147.  
  148.   nNbItem = lstFilesToDecode->Items->Count;
  149.   bFound = false;
  150.  
  151.   // Do not allow more than 1000 files to be decoded at one time
  152.   if( nNbItem < 1000 )
  153.   {
  154.     for( i = 0; i <= nNbItem - 1; i++ )
  155.     {
  156.       // Check if the file is already in the list of files
  157.       if( lstFilesToDecode->Items->Strings[ i ] == sFilename )
  158.       {
  159.         bFound = true;
  160.         break;
  161.       }
  162.     }
  163.  
  164.     if( !bFound )
  165.     {
  166.       // add the file name to the list
  167.       lstFilesToDecode->Items->Add( sFilename );
  168.  
  169.       // If no decode folder is specified, set one to the folder name of
  170.       // the added file name.
  171.       sDecodeFolder = edtDecodeFolder->Text;
  172.  
  173.       if( sDecodeFolder.Length() == 0 )
  174.       {
  175.         sDecodeFolder = ExtractFilePath( sFilename );
  176.  
  177.         if( sDecodeFolder.Length() != 0 )
  178.           edtDecodeFolder->Text = sDecodeFolder;
  179.       }
  180.  
  181.       // If it's the first file added to the list, select it in the list
  182.       if( nNbItem == 0 )
  183.         lstFilesToDecode->ItemIndex = 0;
  184.  
  185.       // Set the decoding method according to the file name extension
  186.       sExtension = sFilename.SubString( ( sFilename.Length() - 3 ), 4 );
  187.  
  188.       if( sExtension.UpperCase() == ".UUE" )
  189.       {
  190.         m_eDecodingMethod = emUUEncode;
  191.         rgMethod->ItemIndex = 0;
  192.       }
  193.  
  194.       if( sExtension.UpperCase() == ".XXE" )
  195.       {
  196.         m_eDecodingMethod = emXXEncode;
  197.         rgMethod->ItemIndex = 1;
  198.       }
  199.  
  200.       if( sExtension.UpperCase() == ".B64" )
  201.       {
  202.         m_eDecodingMethod = emBase64;
  203.         rgMethod->ItemIndex = 2;
  204.       }
  205.  
  206.       if( sExtension.UpperCase() == ".HEX" )
  207.       {
  208.         m_eDecodingMethod = emHexaDecimal;
  209.         rgMethod->ItemIndex = 3;
  210.       }
  211.  
  212.       if( sExtension.UpperCase() == ".QPR" )
  213.       {
  214.         m_eDecodingMethod = emQuotedPrintable;
  215.         rgMethod->ItemIndex = 4;
  216.       }
  217.  
  218.       if( sExtension.UpperCase() == ".HQX" )
  219.       {
  220.         m_eDecodingMethod = emBinHex;
  221.         rgMethod->ItemIndex = 5;
  222.       }
  223.     }
  224.   }
  225. }
  226.  
  227. //---------------------------------------------------------------------------
  228. // Return the extension part of a specified file name
  229. //---------------------------------------------------------------------------
  230. AnsiString TfrmManager::ExtractFileExtension( AnsiString sFilename )
  231. {
  232.   int i;
  233.   int nFilenameLen;
  234.   int nLenToRemove;
  235.  
  236.   nFilenameLen = sFilename.Length();
  237.   i            = nFilenameLen;
  238.   nLenToRemove = -1;
  239.  
  240.   // Start from the end of the string, we check each character and stop
  241.   // at the first occurrence of . or "\"
  242.   while( ( i > 0 ) && ( nLenToRemove == -1 ) )
  243.   {
  244.     // The length of the extension part is the length of the string minus
  245.     // the position of the "."
  246.     if( sFilename.SubString( i, 1 ) == "." )
  247.       nLenToRemove = nFilenameLen - i;
  248.  
  249.     if( sFilename.SubString( i, 1 ) == "\\" )
  250.       nLenToRemove = 0;
  251.  
  252.     i = i - 1;
  253.   }
  254.  
  255.   // If no extension was found we return an empty string
  256.   if( nLenToRemove == -1 )
  257.     return "";
  258.   else
  259.     return sFilename.SubString( ( sFilename.Length() - nLenToRemove + 1 ),
  260.                                   nLenToRemove );
  261. }
  262.  
  263. //---------------------------------------------------------------------------
  264. // Return the specified file name WITHOUT its extension, if any
  265. //---------------------------------------------------------------------------
  266. AnsiString TfrmManager::RemoveFileExtension( AnsiString sFilename )
  267. {
  268.   int i;
  269.   int nFilenameLen;
  270.   int nLenToRemove;
  271.  
  272.   nFilenameLen = sFilename.Length();
  273.   i = nFilenameLen;
  274.   nLenToRemove = -1;
  275.  
  276.   // Starting from the end of the string, we check each character and stop
  277.   // at the first occurrence of "." or "\\"
  278.   while( ( i > 0 ) && ( nLenToRemove == -1 ) )
  279.   {
  280.     // The length of the file name part is the position of the "." minus
  281.     // 1 (to exclude the ".")
  282.     if( sFilename.SubString( i, 1 ) == "." )
  283.       nLenToRemove = i - 1;
  284.  
  285.     // The filename contains a path. Returns all the string
  286.     if( sFilename.SubString( i, 1 ) == "\\" )
  287.       nLenToRemove = nFilenameLen;
  288.  
  289.     i = i -1;
  290.   }
  291.  
  292.   // No extension was found, return an empty strin
  293.   if( nLenToRemove == -1 )
  294.     return "";
  295.   else
  296.     return sFilename.SubString( 1, nLenToRemove );
  297. }
  298.  
  299. //---------------------------------------------------------------------------
  300. // Return a default extension based on an encoding method.
  301. //---------------------------------------------------------------------------
  302. AnsiString TfrmManager::StdFileExtension( TEncodingMethod eMethod )
  303. {
  304.   switch( eMethod )
  305.   {
  306.     case emUUEncode         : return ".uue";
  307.     case emXXEncode         : return ".xxe";
  308.     case emBase64           : return ".b64";
  309.     case emHexaDecimal      : return ".hex";
  310.     case emQuotedPrintable  : return ".qpr";
  311.     case emBinHex           : return ".hqx";
  312.   }
  313.   // although this situation should noto occur. IF it does, we will return a
  314.   // default UUEncode extention.
  315.   return ".uue";
  316. }
  317.  
  318. //---------------------------------------------------------------------------
  319. // Encode the file!
  320. //---------------------------------------------------------------------------
  321. bool TfrmManager::EncodeFile( AnsiString       sSourceFilename,
  322.                               TEncodingMethod  eMethod,
  323.                               EXBEndOfLineType eEndOfLineType,
  324.                               long             lMaxLineLength,
  325.                               AnsiString       sEncodedFilename )
  326. {
  327.   IXceedBinaryEncodingPtr piEncoder;
  328.  
  329.   // Create an instance of our Xceed Binary Encoding Object
  330.   piEncoder.CreateInstance( CLSID_XceedBinaryEncoding );
  331.  
  332.   // Create and prepare the encoding format (XX, UU, BinHex...). we also set
  333.   // the end of line type and the maximum line length for the chosen
  334.   // encoding format.
  335.  
  336.   switch( eMethod )
  337.   {
  338.     case emUUEncode :
  339.     {
  340.       IXceedUUEncodingFormatPtr piUUEncode;
  341.       piUUEncode.CreateInstance( CLSID_XceedUUEncodingFormat );
  342.  
  343.       piUUEncode->IncludeHeaderFooter = true;
  344.       piUUEncode->EndOfLineType = eEndOfLineType;
  345.       piUUEncode->MaxLineLength = lMaxLineLength;
  346.       
  347.       piEncoder->EncodingFormat = piUUEncode;
  348.       break;
  349.     }
  350.     case emXXEncode :
  351.     {
  352.       IXceedXXEncodingFormatPtr piXXEncode;
  353.       piXXEncode.CreateInstance( CLSID_XceedXXEncodingFormat );
  354.  
  355.       piXXEncode->IncludeHeaderFooter = true;
  356.       piXXEncode->EndOfLineType = eEndOfLineType;
  357.       piXXEncode->MaxLineLength = lMaxLineLength;
  358.  
  359.       piEncoder->EncodingFormat = piXXEncode;
  360.       break;
  361.     }
  362.     case emBase64 :
  363.     {
  364.       IXceedBase64EncodingFormatPtr piBase64;
  365.       piBase64.CreateInstance( CLSID_XceedBase64EncodingFormat );
  366.  
  367.       piBase64->EndOfLineType = eEndOfLineType;
  368.       piBase64->MaxLineLength = lMaxLineLength;
  369.  
  370.       piEncoder->EncodingFormat = piBase64;
  371.       break;
  372.     }
  373.     case emHexaDecimal :
  374.     {
  375.       IXceedHexaEncodingFormatPtr piHexaDecimal;
  376.       piHexaDecimal.CreateInstance( CLSID_XceedHexaEncodingFormat );
  377.  
  378.       piHexaDecimal->EndOfLineType = eEndOfLineType;
  379.       piHexaDecimal->MaxLineLength = lMaxLineLength;
  380.  
  381.       piEncoder->EncodingFormat = piHexaDecimal;
  382.       break;
  383.     }
  384.     case emQuotedPrintable :
  385.     {
  386.       IXceedQuotedPrintableEncodingFormatPtr piQuotedPrintable;
  387.       piQuotedPrintable.CreateInstance( CLSID_XceedQuotedPrintableEncodingFormat );
  388.  
  389.       piQuotedPrintable->EndOfLineType = eEndOfLineType;
  390.       piQuotedPrintable->MaxLineLength = lMaxLineLength;
  391.  
  392.       piEncoder->EncodingFormat = piQuotedPrintable;
  393.       break;
  394.     }
  395.     case emBinHex :
  396.     {
  397.       IXceedBinHexEncodingFormatPtr piBinHex;
  398.       piBinHex.CreateInstance( CLSID_XceedBinHexEncodingFormat );
  399.  
  400.       piBinHex->IncludeHeaderFooter = true;
  401.       piBinHex->EndOfLineType = eEndOfLineType;
  402.       piBinHex->MaxLineLength = lMaxLineLength;
  403.  
  404.       // For the BinHex format, we must specify the data fork length
  405.       // and the resource fork length
  406.      HANDLE  hFileHandle;
  407.      hFileHandle = CreateFile( sSourceFilename.c_str(), GENERIC_READ,
  408.                                FILE_SHARE_READ, NULL, OPEN_EXISTING,
  409.                                FILE_ATTRIBUTE_NORMAL, NULL );
  410.  
  411.  
  412.      piBinHex->HeaderDataForkLength = GetFileSize( hFileHandle, NULL );
  413.      piBinHex->HeaderResourceForkLength = 0;
  414.  
  415.      CloseHandle( hFileHandle );
  416.      piEncoder->EncodingFormat = piBinHex;
  417.      break;
  418.     }
  419.   }
  420.  
  421.   // if no extension for the destination file name was provided by the user
  422.   // we set a default one (according to the encoding method)
  423.   if( AnsiString( ExtractFileExtension( sEncodedFilename ) ).Length() == 0 )
  424.     sEncodedFilename = sEncodedFilename + StdFileExtension( eMethod );
  425.  
  426.   lstMessages->Clear();
  427.  
  428.   try
  429.   {
  430.     wchar_t wszSourceFilename[ MAX_PATH ];
  431.     wchar_t wszEncodedFilename[ MAX_PATH ];
  432.  
  433.     sSourceFilename.WideChar( wszSourceFilename, MAX_PATH );
  434.     sEncodedFilename.WideChar( wszEncodedFilename, MAX_PATH );
  435.  
  436.     DWORD dwBytesRead;
  437.     DWORD dwBytesWritten;
  438.  
  439.     // Encode the file, providing:
  440.     //  - A source filename, without any offset or size, since we want
  441.     //    encode it all.
  442.     //  - The processing we want to perform, in this case cfpEncode.
  443.     //  - True in the bEndOfData parameter, since we encode it in a single 
  444.     //    call.
  445.     //  - A destination filename we wish to overwrite (bAppend parameter 
  446.     //    is FALSE).
  447.     //  - The address of two DWORD which will receive the number of bytes
  448.     //    read and written.
  449.     piEncoder->ProcessFile( wszSourceFilename, 0, 0, bfpEncode, true,
  450.                             wszEncodedFilename, false, &dwBytesRead,
  451.                             &dwBytesWritten );
  452.  
  453.     // Display a message of success!
  454.     lstMessages->Items->Add( sSourceFilename + " successfully encoded in " +
  455.                              sEncodedFilename );
  456.   }
  457.   catch( Exception& xErr )
  458.   {
  459.     lstMessages->Items->Add( xErr.Message );
  460.     return false;
  461.   }
  462.   catch( ... )
  463.   {
  464.     lstMessages->Items->Add( "An unexpected error occured while encoding the file" );
  465.     return false;
  466.   }
  467.   return true;
  468. }
  469.  
  470. //---------------------------------------------------------------------------
  471. // Decode the files!
  472. //---------------------------------------------------------------------------
  473. bool TfrmManager::DecodeFile( TStringList*     pslEncodedFile,
  474.                               int              nNbEncodedFile,
  475.                               TEncodingMethod  eMethod,
  476.                               bool             bContinueOnInvalidData,
  477.                               AnsiString       sDecodeFolder,
  478.                               AnsiString       sDecodedFilename )
  479. {
  480.   IXceedBinaryEncodingPtr piDecoder;
  481.  
  482.   // Create our instance of the Xceed Binary Encoding Library
  483.   piDecoder.CreateInstance( CLSID_XceedBinaryEncoding );
  484.   
  485.   if( sDecodeFolder.SubString( sDecodeFolder.Length() - 1, 1 ) == "\\" )
  486.     // The decode folder must end with a "\\"
  487.     sDecodeFolder = sDecodeFolder + "\\";
  488.  
  489.   // Create and prepare the decoding format (XX, UU, BinHex...) and tell
  490.   // wether or not we want to ignore invalid character in the file(s) to
  491.   // decode. If no file name was specified by the user, read the one used
  492.   // by default by the Encoding Library (set at the first call).
  493.   switch( eMethod )
  494.   {
  495.     case emUUEncode :
  496.     {
  497.       IXceedUUEncodingFormatPtr piUUEncode;
  498.       piUUEncode.CreateInstance( CLSID_XceedUUEncodingFormat );
  499.  
  500.       piUUEncode->IncludeHeaderFooter = true;
  501.       piUUEncode->ContinueOnInvalidData = bContinueOnInvalidData;
  502.  
  503.       if( sDecodedFilename.Length() == 0 )
  504.         sDecodedFilename = piUUEncode->HeaderFilename;
  505.  
  506.       piDecoder->EncodingFormat = piUUEncode;
  507.       break;
  508.     }
  509.     case emXXEncode :
  510.     {
  511.       IXceedXXEncodingFormatPtr piXXEncode;
  512.       piXXEncode.CreateInstance( CLSID_XceedXXEncodingFormat );
  513.  
  514.       piXXEncode->IncludeHeaderFooter = true;
  515.       piXXEncode->ContinueOnInvalidData = bContinueOnInvalidData;
  516.  
  517.       if( sDecodedFilename.Length() == 0 )
  518.         sDecodedFilename = piXXEncode->HeaderFilename;
  519.  
  520.       piDecoder->EncodingFormat = piXXEncode;
  521.       break;
  522.     }
  523.     case emBase64 :
  524.     {
  525.       IXceedBase64EncodingFormatPtr piBase64;
  526.       piBase64.CreateInstance( CLSID_XceedBase64EncodingFormat );
  527.  
  528.       piBase64->ContinueOnInvalidData = bContinueOnInvalidData;
  529.  
  530.       piDecoder->EncodingFormat = piBase64;
  531.       break;
  532.     }
  533.     case emHexaDecimal :
  534.     {
  535.       IXceedHexaEncodingFormatPtr piHexa;
  536.       piHexa.CreateInstance( CLSID_XceedHexaEncodingFormat );
  537.  
  538.       piHexa->ContinueOnInvalidData = bContinueOnInvalidData;
  539.  
  540.       piDecoder->EncodingFormat = piHexa;
  541.       break;
  542.     }
  543.     case emQuotedPrintable :
  544.     {
  545.       IXceedQuotedPrintableEncodingFormatPtr piQuotedPrintable;
  546.       piQuotedPrintable.CreateInstance( CLSID_XceedQuotedPrintableEncodingFormat );
  547.  
  548.       piQuotedPrintable->ContinueOnInvalidData = bContinueOnInvalidData;
  549.  
  550.       piDecoder->EncodingFormat = piQuotedPrintable;
  551.       break;
  552.     }
  553.     case emBinHex :
  554.     {
  555.       IXceedBinHexEncodingFormatPtr piBinHex;
  556.       piBinHex.CreateInstance( CLSID_XceedBinHexEncodingFormat );
  557.  
  558.       piBinHex->IncludeHeaderFooter = true;
  559.       piBinHex->ContinueOnInvalidData = bContinueOnInvalidData;
  560.  
  561.       if( sDecodedFilename.Length() == 0 )
  562.         sDecodedFilename = piBinHex->HeaderFilename;
  563.  
  564.       piDecoder->EncodingFormat = piBinHex;
  565.       break;
  566.     }
  567.   }
  568.  
  569.   lstMessages->Clear();
  570.  
  571.   try
  572.   {
  573.     wchar_t wsEncodedFilename[ MAX_PATH ];
  574.     wchar_t wsDestinationFilename[ MAX_PATH ];
  575.     AnsiString sFullDestinationFilename;
  576.     DWORD dwBytesRead;
  577.     DWORD dwBytesWritten;
  578.  
  579.     sFullDestinationFilename = sDecodeFolder + sDecodedFilename;
  580.     sFullDestinationFilename.WideChar( wsDestinationFilename, MAX_PATH );
  581.  
  582.     for( int i = 0; i < nNbEncodedFile; i++ )
  583.     {
  584.       pslEncodedFile->Strings[ i ].WideChar( wsEncodedFilename, MAX_PATH );
  585.  
  586.       // Decode a source file, providing:
  587.       //  - The source filename, without any offset or size, since we
  588.       //    want to decode it all.
  589.       //  - The type of processing, in this case cfpDecode.
  590.       //  - bEndOfData set to true only for the last file.
  591.       //  - The destination filename we are appending to
  592.       //    (bAppend set to True).
  593.       //  - The addres of two DWORd that will contain the number of bytes
  594.       //    read and written on return.
  595.       piDecoder->ProcessFile( wsEncodedFilename, 0, 0, bfpDecode,
  596.                               ( i == nNbEncodedFile-1 ), wsDestinationFilename,
  597.                                true, &dwBytesRead, &dwBytesWritten );
  598.  
  599.       // Display a message of success
  600.       lstMessages->Items->Add( AnsiString( wsEncodedFilename ) + " successfully decoded in " +
  601.                                AnsiString( wsDestinationFilename ) );
  602.     }
  603.   }
  604.   catch( Exception& xErr )
  605.   {
  606.     lstMessages->Items->Add( xErr.Message );
  607.     return false;
  608.   }
  609.   catch( ... )
  610.   {
  611.     lstMessages->Items->Add( "An expected error occurred while decoding" );
  612.     return false;
  613.   }
  614.   return true;
  615. }
  616.  
  617. //---------------------------------------------------------------------------
  618. // Initalize folder browsing window
  619. //---------------------------------------------------------------------------
  620. /* static */
  621. int __stdcall TfrmManager::BrowseCallbackProc( HWND hWnd, UINT uMsg,
  622.                                                LPARAM lParam, LPARAM lpData )
  623. {
  624.   if( uMsg == BFFM_INITIALIZED )
  625.     SendMessageA( hWnd, BFFM_SETSELECTION, 1, lpData );
  626.   else if( uMsg == BFFM_SELCHANGED )
  627.   {
  628.     // Change the text of the current directory
  629.     char szDir[ MAX_PATH ];
  630.     if( SHGetPathFromIDList( ( _ITEMIDLIST* )lParam, szDir ) )
  631.       SendMessageA( hWnd, BFFM_SETSTATUSTEXT, 0, ( LPARAM )szDir );
  632.   }
  633.   return 0;
  634. }
  635.  
  636. //---------------------------------------------------------------------------
  637. // Browse for a destination folder
  638. //---------------------------------------------------------------------------
  639. bool TfrmManager::BrowseFolder( HWND hWnd, AnsiString& sFolder,
  640.                                 AnsiString sDesc )
  641. {
  642.   char szBuffer[ 300 ];
  643.  
  644.   BROWSEINFO bi;
  645.  
  646.   bi.hwndOwner      = hWnd;
  647.   bi.pidlRoot       = NULL;
  648.   bi.pszDisplayName = szBuffer;
  649.   bi.lpszTitle      = sDesc.c_str();
  650.   bi.ulFlags        = BIF_RETURNONLYFSDIRS;
  651.   bi.lpfn           = BrowseCallbackProc;
  652.   bi.lParam         = ( DWORD )sFolder.c_str();
  653.   bi.iImage         = 0;
  654.  
  655.   bool bResult = false;
  656.   _ITEMIDLIST* pItem = SHBrowseForFolder( &bi );
  657.  
  658.   if( pItem )
  659.   {
  660.     if( SHGetPathFromIDList( pItem, szBuffer ) )
  661.     {
  662.       sFolder = szBuffer;
  663.       bResult = true;
  664.     }
  665.  
  666.     CoTaskMemFree( pItem );
  667.   }
  668.  
  669.   return bResult;
  670. }
  671.  
  672. //---------------------------------------------------------------------------
  673. // Prepare the main window by assigning the default values
  674. //---------------------------------------------------------------------------
  675. __fastcall TfrmManager::TfrmManager(TComponent* Owner)
  676.   : TForm(Owner)
  677. {
  678.   m_eEncodingMethod = emUUEncode;
  679.   m_eDecodingMethod = emUUEncode;
  680.   m_lMaxLineLength  = StrToInt( edtMaxLineLen->Text );
  681.   m_eEndOfLineType  = bltCrLf;
  682.  
  683.   // Decoding option
  684.   m_bContinueOnInvalidData = chkContinueOnInvalidData->Checked;
  685.  
  686.   rgMethod->ItemIndex = 0;
  687.   lstFilesToDecode->Clear();
  688. }
  689.  
  690. //---------------------------------------------------------------------------
  691. // Do the encoding of the selected file name to the destination file
  692. //---------------------------------------------------------------------------
  693. void __fastcall TfrmManager::btEncodeClick(TObject *Sender)
  694. {
  695.   if( edtSourceFileToEncode->Text.Length() != 0 )
  696.   {
  697.     // There is something to encode! Do the encoding
  698.  
  699.     if( EncodeFile( edtSourceFileToEncode->Text, m_eEncodingMethod,
  700.                     m_eEndOfLineType, m_lMaxLineLength,
  701.                     edtDestinationFile->Text ) )
  702.     {
  703.       // The encoding was successful sp we clear the source and destination
  704.       // edit boxes
  705.       edtSourceFileToEncode->Text = "";
  706.       edtDestinationFile->Text = "";
  707.     }
  708.   }
  709. }
  710.  
  711. //---------------------------------------------------------------------------
  712. // Remove all items from the files to decode list box
  713. //---------------------------------------------------------------------------
  714. void __fastcall TfrmManager::btClearListClick(TObject *Sender)
  715. {
  716.   lstFilesToDecode->Clear();  
  717. }
  718.  
  719. //---------------------------------------------------------------------------
  720. // Select wether the deconding process should continue if invalid data is
  721. // encountered
  722. //---------------------------------------------------------------------------
  723. void __fastcall TfrmManager::chkContinueOnInvalidDataClick(TObject *Sender)
  724. {
  725.   m_bContinueOnInvalidData = chkContinueOnInvalidData->Checked;
  726. }
  727.  
  728. //---------------------------------------------------------------------------
  729. // Update the MaxLineLength to use
  730. //---------------------------------------------------------------------------
  731. void __fastcall TfrmManager::edtMaxLineLenChange(TObject *Sender)
  732. {
  733.   m_lMaxLineLength = StrToInt( edtMaxLineLen->Text );  
  734. }
  735.  
  736. //---------------------------------------------------------------------------
  737. // Select the end of line type to use
  738. //---------------------------------------------------------------------------
  739. void __fastcall TfrmManager::rgEndOfLineOptionsClick(TObject *Sender)
  740. {
  741.   switch( rgEndOfLineOptions->ItemIndex )
  742.   {
  743.     case 0 :
  744.     {
  745.       m_eEndOfLineType = bltCrLf;
  746.       break;
  747.     }
  748.     case 1 :
  749.     {
  750.       m_eEndOfLineType = bltLf;
  751.       break;
  752.     }
  753.   }
  754. }
  755.  
  756. //---------------------------------------------------------------------------
  757. // Remove the selected file from the list of files to decode
  758. //---------------------------------------------------------------------------
  759. void __fastcall TfrmManager::btRemoveFilesClick(TObject *Sender)
  760. {
  761.   int nFirstItem = 0;
  762.   int nNbItemRemoved = 0;
  763.   int nNbItemsToRemove;
  764.   int nNbItem;
  765.   int i;
  766.  
  767.   nNbItemsToRemove = lstFilesToDecode->SelCount;
  768.  
  769.   if( nNbItemsToRemove != 0 )
  770.   {
  771.     // Check each file in the list of files to decode and remove if selected
  772.     nNbItem = lstFilesToDecode->Items->Count;
  773.  
  774.     for( i = nNbItem - 1; i >= 0; i-- )
  775.     {
  776.       if( lstFilesToDecode->Selected[ i ] )
  777.       {
  778.         lstFilesToDecode->Items->Delete( i );
  779.         nNbItemRemoved = nNbItemRemoved + 1;
  780.         nNbItem = nNbItem - 1;
  781.  
  782.         if( nNbItem == nNbItemsToRemove )
  783.         {
  784.           // We removed the original number of files selected. We set then
  785.           // new item to select in the file list (the file that follows the
  786.           // last selected item) and exit the loop.
  787.           nFirstItem = i;
  788.           break;
  789.         }
  790.       }
  791.     }
  792.  
  793.     if( nNbItem != 0 )
  794.     {
  795.       // There is at least one file left in the list
  796.       if( nFirstItem >= nNbItem )
  797.         // There was no file after the last one that was removed. We select
  798.         // the last file of the list
  799.         lstFilesToDecode->ItemIndex = nNbItem - 1;
  800.       else
  801.         lstFilesToDecode->ItemIndex = nFirstItem;
  802.     }
  803.   }
  804. }
  805.  
  806.  
  807. //---------------------------------------------------------------------------
  808. // File the destination file name to the default value
  809. //---------------------------------------------------------------------------
  810. void __fastcall TfrmManager::edtSourceFileToEncodeExit(TObject *Sender)
  811. {
  812.   SetDestinationFilename();  
  813. }
  814.  
  815. //---------------------------------------------------------------------------
  816. // Select the source folder and file name that will be encoded
  817. //---------------------------------------------------------------------------
  818. void __fastcall TfrmManager::btBrowseForSourceClick(TObject *Sender)
  819. {
  820.   xOpenDialog->Files->Clear();
  821.   xOpenDialog->Title       = "Source file";
  822.   xOpenDialog->Filter      = "All type (*.*)|*.*";
  823.   xOpenDialog->FilterIndex = 0;
  824.  
  825.   //Show an Open common dialog to let the user select a file
  826.   if( xOpenDialog->Execute() )
  827.   {
  828.     edtSourceFileToEncode->Text = xOpenDialog->Files->Text.Trim();
  829.     SetDestinationFilename();
  830.   }
  831. }
  832.  
  833. //---------------------------------------------------------------------------
  834. // Select the destination and name of the encoded file that will be created
  835. //---------------------------------------------------------------------------
  836. void __fastcall TfrmManager::btBrowseForDestinationClick(TObject *Sender)
  837. {
  838.   xOpenDialog->Files->Clear();
  839.   xOpenDialog->Title = "Destination file";
  840.   xOpenDialog->FilterIndex = 0;
  841.   xOpenDialog->Filter = "Encoded (*.uue;*.xxe;*.b64;*.hex;*.hqz;*.qpr)|"
  842.                         "*.uue;*.xxe;*.b64;*.hex;*.hqz;*.qpr|"
  843.                         "UU encode (*.uue)|*.uue|XX encode (*.xxe)|*.xxe|"
  844.                         "Base 64 (*.b64)|*.b64|HexaDecimal (*.hex)|*.hex|"
  845.                         "Quoted Printable (*.qpr)|*.qpr|BinHex (*.hqz)|*.hqz";
  846.  
  847.   // Show an open dialog to let the user select the destination file name
  848.   if( xOpenDialog->Execute() )
  849.     edtDestinationFile->Text = xOpenDialog->Files->Text.Trim();
  850. }
  851.  
  852. //---------------------------------------------------------------------------
  853. // The user changed the selected encoding or decoding method
  854. //---------------------------------------------------------------------------
  855. void __fastcall TfrmManager::rgMethodClick(TObject *Sender)
  856. {
  857.   if( pgMain->ActivePage == tabEncode )
  858.   {
  859.     // Change the extension of the destination (encoded) file name to
  860.     // be consistent with the newly selected encoding method
  861.     SetDestinationFileExtension( m_eEncodingMethod, TEncodingMethod( rgMethod->ItemIndex ) );
  862.     m_eEncodingMethod = TEncodingMethod( rgMethod->ItemIndex );
  863.   }
  864.  
  865.   if( pgMain->ActivePage == tabDecode )
  866.     // The user changed the selected decoding method
  867.     m_eDecodingMethod = TEncodingMethod( rgMethod->ItemIndex );
  868. }
  869.  
  870. //---------------------------------------------------------------------------
  871. // Add file(s) to the list of files to decode
  872. //---------------------------------------------------------------------------
  873. void __fastcall TfrmManager::btAddFilesToDecodeClick(TObject *Sender)
  874. {
  875.   TStringList* pslFilenames = new TStringList();
  876.   int i;
  877.  
  878.   xOpenDialog->Files->Clear();
  879.   xOpenDialog->Title = "Encoded file(s)";
  880.   xOpenDialog->FilterIndex = 0;
  881.   xOpenDialog->Options << ofAllowMultiSelect;
  882.  
  883.   xOpenDialog->Filter = "Encoded (*.uue;*.xxe;*.b64;*.hex;*.hqz;*.qpr)|"
  884.                         "*.uue;*.xxe;*.b64;*.hex;*.hqz;*.qpr|"
  885.                         "UU encode (*.uue)|*.uue|XX encode (*.xxe)|*.xxe|"
  886.                         "Base 64 (*.b64)|*.b64|HexaDecimal (*.hex)|*.hex|"
  887.                         "Quoted Printable (*.qpr)|*.qpr|BinHex (*.hqz)|*.hqz|"
  888.                         "All types (*.*)|*.*";
  889.  
  890.   // Show an Open common dialog to let the user select the files to be decoded
  891.   if( xOpenDialog->Execute() )
  892.   {
  893.     pslFilenames->AddStrings( xOpenDialog->Files );
  894.  
  895.     for( i = 0; i <= pslFilenames->Count - 1; i++ )
  896.       // Add the extracted file name to the list of files to decode
  897.       AddEncodedFileToList( pslFilenames->Strings[ i ] );
  898.     
  899.     delete pslFilenames;
  900.   }
  901. }
  902.  
  903. //---------------------------------------------------------------------------
  904. // Do the decoding of the selected source file(s) to the selected
  905. // destination folder
  906. //---------------------------------------------------------------------------
  907. void __fastcall TfrmManager::btDecodeClick(TObject *Sender)
  908. {
  909.   AnsiString  sDecodedFilename;
  910.  
  911.   sDecodedFilename = edtDecodedFilename->Text;
  912.  
  913.   if( ( sDecodedFilename.Length() == 0 ) &&
  914.       ( m_eDecodingMethod != emUUEncode ) &&
  915.       ( m_eDecodingMethod != emXXEncode ) )
  916.   {
  917.     // No decode file name was entered by the user. Use the filename of the
  918.     // first item in the list of encoded files.
  919.     sDecodedFilename = RemoveFileExtension( ExtractFileName
  920.                                             ( lstFilesToDecode->Items->Strings[ 0 ] ) ) +
  921.                                             ".bin";
  922.     if( sDecodedFilename.Length() != 0 )
  923.       edtDecodedFilename->Text = sDecodedFilename;
  924.   }
  925.  
  926.   int nNbEncodedFile = lstFilesToDecode->Items->Count;
  927.  
  928.   if( nNbEncodedFile != 0 )
  929.   {
  930.     // Fill the TStringList with all the encoded file names from the list box
  931.     TStringList* slEncodedFiles = new TStringList();
  932.  
  933.     for( int i = 0; i < nNbEncodedFile; i++ )
  934.       slEncodedFiles->Add( lstFilesToDecode->Items->Strings[ i ] );
  935.  
  936.     // Do the decoding
  937.     if( DecodeFile( slEncodedFiles, nNbEncodedFile, m_eDecodingMethod,
  938.                     m_bContinueOnInvalidData, edtDecodeFolder->Text,
  939.                     sDecodedFilename ) );
  940.     {
  941.       // The decoding was successful. We clear the file source list box
  942.       // and the destination text box
  943.       edtDecodedFilename->Text = "";
  944.       edtDecodeFolder->Text = "";
  945.       lstFilesToDecode->Clear();
  946.  
  947.       delete slEncodedFiles;
  948.     }
  949.   }
  950. }
  951.  
  952. //---------------------------------------------------------------------------
  953. // Select a folder that will contain the decoded file
  954. //---------------------------------------------------------------------------
  955. void __fastcall TfrmManager::btBrowseForDecodeFolderClick(TObject *Sender)
  956. {
  957.   AnsiString sFolder = edtDecodeFolder->Text;
  958.  
  959.   // By default the browse folder window will be positionned in the currently
  960.   // selected Decode folder.
  961.   if( BrowseFolder( Handle, sFolder, "Decode folder:" ) )
  962.   {
  963.     edtDecodeFolder->Text = sFolder;
  964.   }
  965. }
  966. //---------------------------------------------------------------------------
  967.  
  968.