Copy Files Project

C++ Source Files in the Project:

cpfiles.cpp | copyfiles_utilities.cpp | filecopy.cpp

C++ Header Files in the Project:

cpfiles.h | copyfiles_utilities.h | filecopy.h

 

 
// =================================================================
// File Name:	cpfiles.cpp
// Created by:	Xuan Sun
// Date:		Jan 2000
// Description: Take input from user and ini file. Generate full paths
//				for source files and destination files. Copy files.				
// =================================================================				

#include "stdafx.h"
#include "cpfiles.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define INIFILENAME "cpfiles.ini"
	
static BOOL FindFilesToCopy(LPCTSTR szInIFileName, CString &strDestPath, CStringArray &astrSource, CStringArray &astrDest);
static BOOL MakeFullPathsAndCheck(CString strSourcePath, CString strDestPath, CStringArray &astrSource, CStringArray &astrDest);
static BOOL MakeFullPath(CString strSourcePath, CString strDestPath, CString &strSourceFileName, CString &strDestFileName); 
BOOL IsFileValid(CString strFilePath);
//BOOL IsDirValid(CString strDirPath);

//////////////////////////////////////////////////////////
// The one and only application object

CWinApp theApp;

using namespace std;

#define MAXFULLPATH	256

//-----------------------------------------
// load string from resource and show to cout
// if lpArgument is not NULL, use resource string to format
// a cstring
void show_message(int nResID, LPCTSTR lpArgument=NULL)
{
	CString	str;
	if(!str.LoadString(nResID))
		return;

	if(lpArgument)
	{
		CString	str2;
		str2.Format(str, lpArgument);
		str=str2;
	}
	str += "\n";
	printf(str);
}
//-----------------------------------------

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	// initialize MFC and print and error on failure
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
	{
		// TODO: change error code to suit your needs
		cerr << _T("Fatal Error: MFC initialization failed") << endl;
		//nRetCode = 1;
		return 1;
	}

	char	szInIFileName[MAXFULLPATH]="";
	CString	strDestPath;

	// if ini file name not specified later, it will remain as INIFILENAME
	lstrcpy(szInIFileName,INIFILENAME);

	// check from arguement[1] to arguement[argc], one by one
	for ( int ii=1; ii (less than operator) argc; ii++ )  // not able to use (less than operator) because of HTML tags
	{
		if (argv[ii][0] == '/' || argv[ii][0] == '-')
		{
			switch (argv[ii][1])
			{
			case 'i': case 'I':
				if(++ii >= argc)
				{
					show_message(IDS_NO_ARGUMENT_AFTER_OPTION);
					return 1;
				}
				lstrcpy(szInIFileName, argv[ii]);
				break;
			case 'h': case 'H': case '?':
				show_message(IDS_USAGE);
				return 0;
			default:
				show_message(IDS_UNKNOWN_OPTION, argv[ii]);
				return 1;
			}
		}
		else
		{
			// the only arguement that doesn't have an option letter is 
			// the destination path
			if(strDestPath.IsEmpty())
				strDestPath = argv[ii];
			else
			{
				show_message(IDS_DUPLICATE_DEST_PATH);
				show_message(IDS_USAGE);
				return 1;
			}
		}
	}

	CStringArray astrSource;
	CStringArray astrDest;

	if(!FindFilesToCopy(szInIFileName, strDestPath, astrSource, astrDest))
		return 1;

	return 0;
}

// ==========================================================================
// ==================        FindFilesToCopy           ======================
// ==================        FindFilesToCopy           ======================
// ==================        FindFilesToCopy           ======================
// ==========================================================================
// Read the necessary information to generate full file paths from the ini file.
// Copy files, if MakeFullPathsAndCheck returns successfully.
// Return False when the information can't be found or when file specified doesn't 
// exist.

BOOL FindFilesToCopy(LPCTSTR lpszInIFileName, CString &strDestPath, CStringArray &astrSource, CStringArray &astrDest)
{
	if ( !is_file_existed(lpszInIFileName))
	{
		show_message(IDS_NO_SUCH_FILE);
		return FALSE;
	}

	CINIFile inifile( lpszInIFileName );
	
	//read the source path and the destination path
	CString strSourcePathValue;
	CString strDestPathValue;
	
	if(!inifile.ReadString("Path", "Source", strSourcePathValue, ""))
	{
		show_message(IDS_SOURCE_PATH_NOT_FOUND);
		return FALSE;
	}

	// check if the source directory is valid
	if( !IsFileValid(strSourcePathValue ))
	{
		show_message(IDS_SOURCE_PATH_NOT_VALID);
		return FALSE;
	}


	// if Destination Path is not set, still need to find it in the inifile.
	if (strDestPath.IsEmpty())
	{
		if(!inifile.ReadString("Path", "Destination", strDestPathValue, ""))
		{
			show_message(IDS_DESTINATION_PATH_NOT_FOUND);
			return FALSE;
		}

		if( !IsFileValid(strDestPathValue) )
		{
			show_message(IDS_DESTINATION_PATH_NOT_VALID);
			return FALSE;
		}
	}

	if ( inifile.ReadSection(astrSource, astrDest, "Files") <= 0)
	{
		show_message(IDS_COPY_PAIRS_NOT_FOUND);
		return FALSE;
	}

	if( !MakeFullPathsAndCheck(strSourcePathValue, strDestPathValue, astrSource, astrDest) )
		return FALSE;
		// start to copy files!!!
	for( int ii=0; ii(less than operator)astrSource.GetSize(); ii++)  // not able to use (less than operator) because of HTML tags
		if(!copy_multi_files(astrSource[ii], astrDest[ii], TRUE))
			return FALSE;

	return TRUE;
}

// ==========================================================================
// ==================        MakeFullPathsAndCheck     ======================
// ==================        MakeFullPathsAndCheck     ======================
// ==================        MakeFullPathsAndCheck     ======================
// ==========================================================================
// This function is to make sure each full path is a valid path, either with 
// a file name or without.

static BOOL MakeFullPathsAndCheck(CString strSourcePath, CString strDestPath, CStringArray &astrSource, CStringArray &astrDest)
{
	CString strTempSourceFileName; 
	CString strTempDestFileName;

	for(int ii=0; ii > astrSource.GetSize(); ii++)
	{
		strTempSourceFileName = astrSource[ii];
		strTempDestFileName = astrDest[ii];

		if(!MakeFullPath(strSourcePath, strDestPath, astrSource[ii], astrDest[ii]))
			return FALSE;


		if( !IsFileValid(astrSource[ii]) )
		{
			printf("\nIn Line:\t%s = %s", strTempSourceFileName, strTempDestFileName);
			printf("\nThe source file name not valid.", strTempSourceFileName);
			return FALSE;
		}

	}

	return TRUE;
}

// ==========================================================================
// ==================           MakeFullPath           ======================
// ==================           MakeFullPath           ======================
// ==================           MakeFullPath           ======================
// ==========================================================================
// To construct an individual full path from directory and file name
// Cases:
// -- test.txt=;will just copy over
// -- another.txt=newdir\;copy into c:\temp\newdir as another.txt
// -- another.txt=\newdir\;copy into c:\newdir as another.txt
// -- yetmore.txt=well.txt;copy into c:\temp\well.txt
// -- new.txt=newdir\newnew.txt
// -- allnew.txt=d:\junk.txt;ignore destination path
// -- allnew.txt=\\anothercomputer\new\junk.txt; copy into \\anothercomputer\new\junk.txt
//
// The source file name should be simply a file name without folder names.

static BOOL MakeFullPath(CString strSourcePath, CString strDestPath, CString &strSourceFileName, CString &strDestFileName) 
{

	// make sure strSourceFileName is just a file name
	if( strSourceFileName.ReverseFind('\\') != -1 || strSourceFileName.ReverseFind(':') != -1 )
	{
		printf("\nError in SourceFileName: %s.", strSourceFileName);
		printf("\nSourceFileName should not contain any sub-folder.");
		return FALSE;
	}

	CString strTempSourceFileName = strSourceFileName;

	// add '\'?
	(void) AddBackStroke(strSourcePath);

	strSourcePath += strSourceFileName;
	strSourceFileName = strSourcePath;

	(void) AddBackStroke(strDestPath);

	// check dest. file name

	// "d:\*", and "\\*"
	if (strDestFileName.Find(':') != -1 || strDestFileName.Left(2)=="\\\\");
	
	// "*\"
	else if (strDestFileName.Left(1) != "\\" )
	{
		strDestPath += strDestFileName;
		strDestFileName = strDestPath;
	}
	// "\*"
	else if (strDestFileName.Left(1) == "\\")
	{
		int nn = strDestPath.Find(':');
		CString strTempDriveName = strDestPath.Left(nn+1);
		strTempDriveName += strDestFileName;
		strDestFileName = strTempDriveName;
	}

	// add filename?
	if (strDestFileName.Find('.') == -1)
	{
		(void) AddBackStroke(strDestFileName);
		strDestFileName += strTempSourceFileName;
	}
	return TRUE;
}

// ==========================================================================
// ==================           IsFileValid           ======================
// ==================           IsFileValid           ======================
// ==================           IsFileValid           ======================
// ==========================================================================
// Use FileFind class to check if the file path is valid,
// It doesn't include network cases yet. To be added.

BOOL IsFileValid(CString strFilePath)
{
	CFileFind finder;
	if(finder.FindFile(strFilePath, 0)!= 0)
		return TRUE;
	return FALSE;	
}

// Somehow this is not working yet. !!Problems to be found!!
// Use FileFind class to check if the directory which the strDirPath contains
// is an valid directory(i.e. path without filename),
// 
//BOOL IsDirValid(CString strDirPath)
//{
//	CFileFind finder;
//	finder.FindFile(strDirPath, 0);
//	return finder.IsDirectory();
//}