A simple FTP update client
Introduction
This code implements a simple ftp client,before you to use it you should create a ftp server,(Server_u is a good choice)and put some update file to a specify direcory .
Flow: when the pragram start,the update clent will traversal the current directory and subdirectory,the write to result to a text file "local.txt",at the same time download "update.txt "from FTP server.then compare the two file, work out which file should be updated.you can check out "update.log" if any error happens.all files have updated also record at "update.log". if the program is not the lastest,update itselt when system restart.
If you find any errors or bugs,please tell me.
Background
every software should be update.before I start to do this work,I have look up many information form Internet.something is userful for me.but I didn't find a absolute project . so I write one by myself.
Using the code
Collapse Copy Code
//usage:
#define LOCAL_FILE_PATH _T(".//local.txt")
#define UPDATE_FILE_PATH _T(".//update.txt")
vector vFileNeedToUpdate;
CWinUpdate winUpdate;
winUpdate.CheckoutUpdate(LOCAL_FILE_PATH,UPDATE_FILE_PATH,vFileNeedToUpdate);
Collapse Copy Code
//description:
//when CheckoutUpdate function called.it first check the pragram version. if it is the latest verion,do nothing,else create a temp directory "bak" and dowmload the latest from ftp server.switch it after system restart.
//after CWinUpdate initialze,it's construction called first.then do those works:
#define APPNAME _T("FTP Client Update App")
#define SERVER_NAME _T("192.168.0.105")
#define USER_NAME _T("http://www.cleansky.com/">www.cleansky.com")
#define USER_PASSWORD _T("http://www.cleansky.com/">www.cleansky.com")
#define ROMOTE_FILE_PATH _T("update.txt")
#define LOCAL_TXT_PATH _T(".//update.txt")
#define ROMOTE_VERSION_FILE _T("version.txt")
#define LOCAL_VERSION_FILE _T(".//version.txt")
#define ROMOTE_EXT_FILE _T("Update.exe")
#define LOCAL_EXE_FILE _T(".//bak//Update.exe")
#define LOCAL_FILE _T("local.txt")
#define VERSION _T("version.txt")
#define BAK_DIRECTORY _T("bak")
#define LASTEST_VERSION 2.0
Collapse Copy Code
VOID CWinUpdate::Initialization()
{
//Initializes an application's use of the WinINet functions.
InitWinINet(APPNAME);
//Opens an File Transfer Protocol
//strServerName:specifies the host name of an Internet ,you can also specifies a IP address ,such as 192.168.0.105
//strUserName: name of the user to log on,
//strUserPassword: password the user to login
Collapse Copy Code
OpenWinINetConnection(SERVER_NAME,USER_NAME,USER_PASSWORD);
WinInetDownloadFile(ROMOTE_FILE_PATH,LOCAL_TXT_PATH); //download "update.txt" form ftp server
WinInetDownloadFile(ROMOTE_VERSION_FILE,LOCAL_VERSION_FILE); //dowmload "version.txt" from ftp server
}//Initialization complete.
Collapse Copy Code
//also when CFileManage Initialize.those work would be done:
VOID CFileManage::Initialization()
{
Win32RecurseDirectory(LOCAL_FILE_PATH);//recursion browse current directory and subdirectory,find all of directory and file
Win32WriteToText(GetFileInfo(),WRITE_UPDATE_TXT_PATH);//write to the local file list to "local.txt"
}
Collapse Copy Code
ErrorType CWinUpdate::CheckoutUpdate(std::string strstrSourceFilePath,std::string strDestFilePath,vector<string>& vNeedToUpdate)
{
if (!CheckVersion())
{
SwitchFile();
m_FileManage.Win32CompareFile(strstrSourceFilePath,strDestFilePath,vNeedToUpdate); //compare update.txt and local.txt .work out the file need to be updated.
DownAllUpdateFiles(vNeedToUpdate); //download all files which are need to update.
}
return Success;
}
Collapse Copy Code
//key function:
Collapse Copy Code
//recursion browse current directory and subdirectory,find all of directory and file
VOID CFileManage::Win32RecurseDirectory(TCHAR* strDirectoryName)
{
TCHAR *strPathName = new TCHAR[BUFSIZE];
TCHAR *strTempPath = new TCHAR[BUFSIZE];
BOOL bSearchFile = FALSE;
BOOL bFinished = FALSE;
DWORD dwPos = 0;
USER_DEFINE_FIND_DATA Filedata;
ZeroMemory(&Filedata,sizeof(Filedata));
HANDLE hFindFile = INVALID_HANDLE_VALUE;
//save current path to a strPathName variable
_tcscpy(strPathName,strDirectoryName);
//add a / to the end of strPathName
if (strPathName[_tcslen(strPathName)-1] != _T('//'))
{
_tcscat(strPathName,_T("//"));
}
//add a * to the end of strPathName
_tcscat(strPathName,_T("*.*"));
//find the first file in the directory,if succeeds,return value is a search handle used in a subsequent call to FindNextFile or FindClose.
bSearchFile = (INVALID_HANDLE_VALUE !=(hFindFile = FindFirstFile(strPathName,&Filedata)));
if (bSearchFile)
{
//if direction is current or subdirectories ,ignore it
if (_tcscmp(Filedata.cFileName,_T(".")) && _tcscmp(Filedata.cFileName,_T("..")))
{
m_LogOutput.FormatOutput(_T(" %s/n"),Filedata.cFileName);
}
while (!bFinished)
{
//Continues a file search next file,recurse calls RecurseDirectory,until no file or direction left
if (FindNextFile(hFindFile,&Filedata))
{
if ((Filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && _tcscmp(Filedata.cFileName,_T(".")) && _tcscmp(Filedata.cFileName,_T("..")))
{
_tcscpy(strTempPath,strDirectoryName);
_tcscat(strTempPath,Filedata.cFileName);
_tcscat(strTempPath,_T("//"));
_tcscpy(Filedata.strFilePath,strTempPath);
//_tcscat(Filedata.strFilePath,Filedata.cFileName);
m_vFileInfo.push_back(Filedata);
Win32RecurseDirectory(strTempPath);
}
else if (_tcscmp(Filedata.cFileName,_T(".")) && _tcscmp(Filedata.cFileName,_T("..")))
{
_tcscpy(Filedata.strFilePath,strDirectoryName);
_tcscat(Filedata.strFilePath,Filedata.cFileName);
m_vFileInfo.push_back(Filedata);
}
}
else
{
if( GetLastError() == ERROR_NO_MORE_FILES )
{
bFinished = TRUE;
}
else
{
bFinished = TRUE;
}
}
}
}
else
{
m_LogOutput.FormatOutput(_T("Invalid File Handle. GetLastError reports %d/n"), GetLastError ());
}
delete []strPathName;
delete []strTempPath;
FindClose(hFindFile);
return;
}
Collapse Copy Code
//after traversal the directory and subdirectory,write to the result to "local.txt"
VOID CFileManage::Win32WriteToText(std::vector<USER_DEFINE_FIND_DATA> vFileInfo,std::string strDestPath)
{
DWORD dwByteWrite = 0;
SYSTEMTIME stUTCCreateTime;
SYSTEMTIME stUTCChangeTime;
SYSTEMTIME stCreateTime;
SYSTEMTIME stChangeTime;
FILETIME fileCreateTime;
FILETIME fileLastChageTime;
TCHAR szTemp[MAXSIZE];
ZeroMemory(szTemp,sizeof(TCHAR)*MAXSIZE);
ZeroMemory(&stCreateTime,sizeof(stCreateTime));
ZeroMemory(&fileCreateTime,sizeof(fileCreateTime));
ZeroMemory(&fileLastChageTime,sizeof(fileLastChageTime));
ZeroMemory(&stChangeTime,sizeof(stChangeTime));
ZeroMemory(&stUTCCreateTime,sizeof(stUTCCreateTime));
ZeroMemory(&stUTCChangeTime,sizeof(stUTCChangeTime));
HANDLE hFile = Win32CreateFile(strDestPath.c_str());
for (int i = 0;i < vFileInfo.size();i++ )
{
GetSystemTime(&stChangeTime);
GetSystemTime(&stCreateTime);
fileCreateTime = vFileInfo[i].ftCreationTime;
fileLastChageTime = vFileInfo[i].ftLastWriteTime;
//Converts a file time to system time format.
if (!FileTimeToSystemTime(&fileCreateTime,&stUTCCreateTime))
{
m_LogOutput.FormatOutput(_T("fileCreateTime FileTimeToSystemTime failed at %d/n"),GetLastError());
}
//Converts a time in Coordinated Universal Time (UTC) to a specified time zone's corresponding local time.
SystemTimeToTzSpecificLocalTime(NULL, &stUTCCreateTime, &stCreateTime);
if (!FileTimeToSystemTime(&fileLastChageTime,&stUTCChangeTime))
{
m_LogOutput.FormatOutput(_T("fileLastChageTime FileTimeToSystemTime failed at %d/n"),GetLastError());
}
SystemTimeToTzSpecificLocalTime(NULL, &stUTCChangeTime, &stChangeTime);
_stprintf(szTemp,_T("%d/%d/%d--%d:%d:%d,%d/%d/%d--%d:%d:%d,%d,%s,/r/n" ),stCreateTime.wMonth,stCreateTime.wDay,
stCreateTime.wYear,stCreateTime.wHour,stCreateTime.wMinute,stCreateTime.wSecond,
stChangeTime.wMonth,stChangeTime.wDay,stChangeTime.wYear,stChangeTime.wHour,stChangeTime.wMinute,stChangeTime.wSecond,
vFileInfo[i].nFileSizeLow,vFileInfo[i].strFilePath);
Win32WriteFile(hFile,szTemp,_tcslen(szTemp),dwByteWrite);
}
CloseHandle(hFile);
}
Collapse Copy Code
//prase string,string like that
//12/11/2008--10:24:16,11/11/2008--0:11:5,57,./cygwin.bat,
//12/11/2008--10:23:44,12/11/2008--10:23:44,0,./home/,
//12/11/2008--10:23:44,12/11/2008--10:23:45,0,./home/Administrator/,
//12/11/2008--10:23:44,12/8/2008--16:38:50,10067,./home/Administrator/-g,
//12/11/2008--10:23:44,11/11/2008--20:44:26,4096,./home/Administrator/.swp,
//12/11/2008--10:23:45,12/11/2008--10:23:45,0,./home/Administrator/.texmf/,
//divide the string for four parts:
12/11/2008--10:24:16
11/11/2008--0:11:5
57
./cygwin.bat
//and store it to a struct tagFILEINFO
tagFILEINFO CFileManage::ParseString(std::string strTemp)
{
int nCh = _T(',');
int nCount = 1;
int result = 0;
TCHAR *pdest;
std::string strLeft;
tagFILEINFO structLocalFile;
ZeroMemory(&structLocalFile,sizeof(structLocalFile));
// Search forward.
while (1)
{
pdest = strchr(const_cast(strTemp.c_str()), nCh );
//returns a pointer to the first occurrence of gCh in strTemp, or NULL if c is not found
if ( pdest != NULL )
{
//m_LogOutput.FormatOutput(_T("Result: first %c found at position %d/n"), nCh, result );
}
else
{
return structLocalFile;
}
//the position of which you first find the char ch
result = (int)(pdest - strTemp.c_str() + 1);
//store a file information to struct.
switch (nCount)
{
case 1:
{
for (int m = 0;m < result - 1 ; m++)
{
structLocalFile.strCreateTime += strTemp[m];
}
break;
}
case 2:
{
for (int m = 0;m < result - 1 ; m++)
{
structLocalFile.strLastWriteTime += strTemp[m];
}
break;
}
case 3:
{
for (int m = 0;m < result - 1 ; m++)
{
structLocalFile.strSize += strTemp[m];
}
break;
}
case 4:
{
for (int m = 0;m < result - 1 ; m++)
{
structLocalFile.strFilePath += strTemp[m];
}
break;
}
default:
return structLocalFile;
}
int iLen = strlen(pdest);
if (strLeft.size() != 0)
{
strLeft.clear();
}
//copy string from pdest to strLeft
for (int i = 1 ;i < iLen ; i++)
{
strLeft += pdest[i];
}
int nLen = strlen(strTemp.c_str());
strTemp = const_cast((TCHAR *)strLeft.c_str());
nCount ++;
}
return structLocalFile;
}
Collapse Copy Code
//Read string form text,only implement read ASCII text now, we should read a function to translate UNICODE text form ASCII.
VOID CFileManage::Win32ReadAsciiFile(TCHAR* strFileName,map <int, string> &mapRead)
{
int iCoutn = 0;
ifstream ifs(strFileName);
string strRead;
while (!ifs.eof()) // when the file not exist ,infinitude loop.why?
{
iCoutn ++;
getline(ifs,strRead,'/n');
if (strRead.size() != 0)
{
mapRead.insert(Int_Pair(iCoutn,strRead));
}
}
ifs.close();
}
Collapse Copy Code
//format a string and write all action to a update.log.
Collapse Copy Code
VOID CLogOutput::FormatOutput(const TCHAR *format,...)
{
TCHAR buf[4096];
TCHAR *p = buf;
va_list args;
int n;
va_start(args, format);
// buf-3 is room for CR/LF/NUL
n = _vsnprintf(p, sizeof buf - 3, format, args);
va_end(args);
p += (n < 0) ? sizeof buf - 3 : n;
while ( p > buf && isspace(p[-1]) )
{
*--p = '/0';
}
*p++ = '/r';
*p++ = '/n';
*p = '/0';
OutputDebugString(buf);
WriteLog(_T(".//update.log"),buf);
}
Collapse Copy Code
VOID CLogOutput::WriteLog(std::string strDestPath,TCHAR* strBuf)
{
DWORD dwByteWrite = 0;
TCHAR strTemp[256];
ZeroMemory(strTemp,sizeof(TCHAR)*256);
SYSTEMTIME stLocal,stUTC;
//create a file ,if the file not exist,create it ,else open it.
mhFile = CreateFile(
strDestPath.c_str(),
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == mhFile)
{
_tprintf(_T("CreateFile failed at %d/n"),GetLastError());
return;
}
//Get a file time.
GetSystemTime(&stUTC);
//Converts a time in Coordinated Universal Time (UTC) to a specified time zone's corresponding local time.
SystemTimeToTzSpecificLocalTime(NULL,&stUTC,&stLocal);
_stprintf(strTemp,_T("%d/%d/%d %d:%d:%d %s"),stLocal.wYear,stLocal.wMonth,stLocal.wDay,
stLocal.wHour,stLocal.wMinute,stLocal.wSecond,strBuf);
SetFilePointer(mhFile,0,NULL,FILE_END);
WinWriteFile(mhFile,strTemp,_tcslen(strTemp),dwByteWrite);
}
download from here: http://download.csdn.net/source/839478