OSDN Git Service

Update OpenSSL to 1.0.2f.
[ffftp/ffftp.git] / updater.c
index 66fd783..d60464d 100644 (file)
--- a/updater.c
+++ b/updater.c
@@ -15,6 +15,7 @@ typedef SOCKADDR_STORAGE *PSOCKADDR_STORAGE, FAR *LPSOCKADDR_STORAGE;
 #include "socketwrapper.h"\r
 #include "protectprocess.h"\r
 #include "mbswrapper.h"\r
+#include "apiemulator.h"\r
 \r
 typedef struct\r
 {\r
@@ -37,10 +38,14 @@ typedef struct
 {\r
        DWORD Version;\r
        CHAR VersionString[32];\r
+       CHAR Description[1024];\r
        DWORD FileCount;\r
        UPDATE_LIST_FILE File[1];\r
 } UPDATE_LIST;\r
 \r
+#define UPDATE_MAX_LIST_SIZE 1048576\r
+#define UPDATE_MAX_FILE_SIZE 16777216\r
+\r
 BOOL ReadFileViaHTTPW(void* pOut, DWORD Length, DWORD* pLength, LPCWSTR UserAgent, LPCWSTR ServerName, LPCWSTR ObjectName)\r
 {\r
        BOOL bResult;\r
@@ -102,7 +107,12 @@ BOOL SaveMemoryToFileWithTimestamp(LPCTSTR FileName, void* pData, DWORD Size, FI
        {\r
                if(WriteFile(hFile, pData, Size, &Size, NULL))\r
                {\r
-                       if(SetFileTime(hFile, NULL, NULL, pTimestamp))\r
+                       if(pTimestamp)\r
+                       {\r
+                               if(SetFileTime(hFile, NULL, NULL, pTimestamp))\r
+                                       bResult = TRUE;\r
+                       }\r
+                       else\r
                                bResult = TRUE;\r
                }\r
                CloseHandle(hFile);\r
@@ -110,6 +120,38 @@ BOOL SaveMemoryToFileWithTimestamp(LPCTSTR FileName, void* pData, DWORD Size, FI
        return bResult;\r
 }\r
 \r
+BOOL LoadMemoryFromFileWithTimestamp(LPCTSTR FileName, void* pData, DWORD Size, DWORD* pReadSize, FILETIME* pTimestamp)\r
+{\r
+       BOOL bResult;\r
+       HANDLE hFile;\r
+       LARGE_INTEGER li;\r
+       bResult = FALSE;\r
+       if((hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)\r
+       {\r
+               if(GetFileSizeEx(hFile, &li))\r
+               {\r
+                       if(li.QuadPart <= (LONGLONG)Size)\r
+                       {\r
+                               if(ReadFile(hFile, pData, Size, pReadSize, NULL))\r
+                               {\r
+                                       if(*pReadSize == li.LowPart)\r
+                                       {\r
+                                               if(pTimestamp)\r
+                                               {\r
+                                                       if(GetFileTime(hFile, NULL, NULL, pTimestamp))\r
+                                                               bResult = TRUE;\r
+                                               }\r
+                                               else\r
+                                                       bResult = TRUE;\r
+                                       }\r
+                               }\r
+                       }\r
+                       CloseHandle(hFile);\r
+               }\r
+       }\r
+       return bResult;\r
+}\r
+\r
 BOOL CopyAllFilesInDirectory(LPCTSTR From, LPCTSTR To)\r
 {\r
        BOOL bResult;\r
@@ -158,44 +200,189 @@ BOOL DeleteDirectoryAndContents(LPCTSTR Path)
        return bResult;\r
 }\r
 \r
+DWORD ListUpdateFile(UPDATE_LIST* pList, DWORD MaxCount, LPCTSTR ServerPath, LPCTSTR ReferenceDir, LPCTSTR Path)\r
+{\r
+       DWORD Result;\r
+       TCHAR Temp1[MAX_PATH];\r
+       TCHAR Temp2[MAX_PATH];\r
+       TCHAR Temp3[MAX_PATH];\r
+       HANDLE hFind;\r
+       WIN32_FIND_DATA Find;\r
+       void* pBuf;\r
+       DWORD Length;\r
+       FILETIME Time;\r
+       BYTE Hash[64];\r
+       Result = 0;\r
+       if(!Path)\r
+               Path = _T("");\r
+       if(_tcslen(ReferenceDir) + _tcslen(Path) + _tcslen(_T("\\*")) < MAX_PATH)\r
+       {\r
+               _tcscpy(Temp1, ReferenceDir);\r
+               _tcscat(Temp1, Path);\r
+               _tcscat(Temp1, _T("\\*"));\r
+               if((hFind = FindFirstFile(Temp1, &Find)) != INVALID_HANDLE_VALUE)\r
+               {\r
+                       do\r
+                       {\r
+                               if(_tcscmp(Find.cFileName, _T(".")) != 0 && _tcscmp(Find.cFileName, _T("..")) != 0)\r
+                               {\r
+                                       if(_tcslen(ServerPath) + _tcslen(_T("/")) + _tcslen(Find.cFileName) < 128 && _tcslen(Path) + _tcslen(_T("\\")) + _tcslen(Find.cFileName) < 128)\r
+                                       {\r
+                                               _tcscpy(Temp1, ServerPath);\r
+                                               _tcscat(Temp1, _T("/"));\r
+                                               _tcscat(Temp1, Find.cFileName);\r
+                                               _tcscpy(Temp2, Path);\r
+                                               _tcscat(Temp2, _T("\\"));\r
+                                               _tcscat(Temp2, Find.cFileName);\r
+                                               if(_tcslen(ReferenceDir) + _tcslen(Temp2) < MAX_PATH)\r
+                                               {\r
+                                                       _tcscpy(Temp3, ReferenceDir);\r
+                                                       _tcscat(Temp3, Temp2);\r
+                                                       if((Find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))\r
+                                                       {\r
+                                                               if(!(Find.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))\r
+                                                               {\r
+                                                                       if(pList)\r
+                                                                       {\r
+                                                                               memset(&pList->File[pList->FileCount], 0, sizeof(UPDATE_LIST_FILE));\r
+                                                                               pList->File[pList->FileCount].Flags = UPDATE_LIST_FILE_FLAG_DIRECTORY;\r
+                                                                               _tcscpy(pList->File[pList->FileCount].DstPath, Temp2);\r
+                                                                               pList->FileCount++;\r
+                                                                       }\r
+                                                                       Result++;\r
+                                                                       if(Result >= MaxCount)\r
+                                                                               break;\r
+                                                                       Result += ListUpdateFile(pList, MaxCount, Temp1, ReferenceDir, Temp2);\r
+                                                               }\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               if(pList)\r
+                                                               {\r
+                                                                       if(pBuf = malloc(UPDATE_MAX_FILE_SIZE))\r
+                                                                       {\r
+                                                                               if(LoadMemoryFromFileWithTimestamp(Temp3, pBuf, UPDATE_MAX_FILE_SIZE, &Length, &Time))\r
+                                                                               {\r
+                                                                                       if(GetHashSHA512(pBuf, Length, &Hash))\r
+                                                                                       {\r
+                                                                                               memset(&pList->File[pList->FileCount], 0, sizeof(UPDATE_LIST_FILE));\r
+                                                                                               _tcscpy(pList->File[pList->FileCount].SrcPath, Temp1);\r
+                                                                                               memcpy(&pList->File[pList->FileCount].SrcHash, &Hash, 64);\r
+                                                                                               _tcscpy(pList->File[pList->FileCount].DstPath, Temp2);\r
+                                                                                               pList->File[pList->FileCount].Timestamp = Time;\r
+                                                                                               pList->FileCount++;\r
+                                                                                       }\r
+                                                                               }\r
+                                                                               free(pBuf);\r
+                                                                       }\r
+                                                               }\r
+                                                               Result++;\r
+                                                               if(Result >= MaxCount)\r
+                                                                       break;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       while(FindNextFile(hFind, &Find));\r
+                       FindClose(hFind);\r
+               }\r
+       }\r
+       return Result;\r
+}\r
+\r
+// FFFTPの更新情報を作成\r
+BOOL BuildUpdates(LPCTSTR PrivateKeyFile, LPCTSTR Password, LPCTSTR ServerPath, LPCTSTR HashFile, LPCTSTR ListFile, DWORD Version, LPCTSTR VersionString, LPCTSTR Description)\r
+{\r
+       BOOL bResult;\r
+       char PrivateKey[4096];\r
+       DWORD Length;\r
+       TCHAR Name[MAX_PATH];\r
+       TCHAR* p;\r
+       UPDATE_LIST* pList;\r
+       UPDATE_HASH Hash;\r
+       BYTE Buf[1024];\r
+       bResult = FALSE;\r
+       memset(PrivateKey, 0, sizeof(PrivateKey));\r
+       if(LoadMemoryFromFileWithTimestamp(PrivateKeyFile, &PrivateKey, sizeof(PrivateKey) - sizeof(char), &Length, NULL))\r
+       {\r
+               if(GetModuleFileName(NULL, Name, MAX_PATH) > 0)\r
+               {\r
+                       if(p = _tcsrchr(Name, _T('\\')))\r
+                               *p = _T('\0');\r
+                       if(pList = (UPDATE_LIST*)malloc(UPDATE_MAX_LIST_SIZE))\r
+                       {\r
+                               memset(pList, 0, UPDATE_MAX_LIST_SIZE);\r
+                               pList->Version = Version;\r
+                               _tcscpy(pList->VersionString, VersionString);\r
+                               _tcscpy(pList->Description, Description);\r
+                               ListUpdateFile(pList, (UPDATE_MAX_LIST_SIZE - sizeof(UPDATE_LIST)) / sizeof(UPDATE_LIST_FILE) + 1, ServerPath, Name, NULL);\r
+                               Length = (pList->FileCount - 1) * sizeof(UPDATE_LIST_FILE) + sizeof(UPDATE_LIST);\r
+                               if(SaveMemoryToFileWithTimestamp(ListFile, pList, Length, NULL))\r
+                               {\r
+                                       memcpy(&Hash.Signature, UPDATE_SIGNATURE, 64);\r
+                                       if(GetHashSHA512(pList, Length, &Hash.ListHash))\r
+                                       {\r
+                                               if(EncryptSignature(PrivateKey, Password, &Hash, sizeof(UPDATE_HASH), &Buf, sizeof(Buf), &Length))\r
+                                               {\r
+                                                       if(SaveMemoryToFileWithTimestamp(HashFile, &Buf, Length, NULL))\r
+                                                               bResult = TRUE;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               free(pList);\r
+                       }\r
+               }\r
+       }\r
+       return bResult;\r
+}\r
+\r
 // FFFTPの更新情報を確認\r
-BOOL CheckForUpdates(BOOL bDownload, LPCTSTR DownloadDir, DWORD* pVersion, LPTSTR pVersionString)\r
+BOOL CheckForUpdates(BOOL bDownload, LPCTSTR DownloadDir, DWORD* pVersion, LPTSTR pVersionString, LPTSTR pDescription)\r
 {\r
        BOOL bResult;\r
        DWORD Length;\r
-       BYTE Buf1[65536];\r
+       BYTE Buf1[1024];\r
        BYTE Buf2[1024];\r
+       void* pBuf;\r
        UPDATE_HASH UpdateHash;\r
        BYTE Hash[64];\r
        UPDATE_LIST* pUpdateList;\r
        bResult = FALSE;\r
        if(ReadFileViaHTTP(&Buf1, sizeof(Buf1), &Length, HTTP_USER_AGENT, UPDATE_SERVER, UPDATE_HASH_PATH))\r
        {\r
-               if(DecryptSignature(UPDATE_RSA_PUBLIC_KEY, &Buf1, Length, &Buf2, sizeof(Buf2), &Length))\r
+               if(DecryptSignature(UPDATE_RSA_PUBLIC_KEY, NULL, &Buf1, Length, &Buf2, sizeof(Buf2), &Length))\r
                {\r
                        if(Length == sizeof(UPDATE_HASH))\r
                        {\r
                                memcpy(&UpdateHash, &Buf2, sizeof(UPDATE_HASH));\r
                                if(memcmp(&UpdateHash.Signature, UPDATE_SIGNATURE, 64) == 0)\r
                                {\r
-                                       if(ReadFileViaHTTP(&Buf1, sizeof(Buf1), &Length, HTTP_USER_AGENT, UPDATE_SERVER, UPDATE_LIST_PATH))\r
+                                       if(pBuf = malloc(UPDATE_MAX_LIST_SIZE))\r
                                        {\r
-                                               GetHashSHA512(&Buf1, Length, &Hash);\r
-                                               if(memcmp(&Hash, &UpdateHash.ListHash, 64) == 0)\r
+                                               if(ReadFileViaHTTP(pBuf, UPDATE_MAX_LIST_SIZE, &Length, HTTP_USER_AGENT, UPDATE_SERVER, UPDATE_LIST_PATH))\r
                                                {\r
-                                                       if(Length >= sizeof(UPDATE_LIST))\r
+                                                       if(GetHashSHA512(pBuf, Length, &Hash))\r
                                                        {\r
-                                                               bResult = TRUE;\r
-                                                               pUpdateList = (UPDATE_LIST*)&Buf1;\r
-                                                               if(pUpdateList->Version > *pVersion)\r
+                                                               if(memcmp(&Hash, &UpdateHash.ListHash, 64) == 0)\r
                                                                {\r
-                                                                       *pVersion = pUpdateList->Version;\r
-                                                                       _tcscpy(pVersionString, pUpdateList->VersionString);\r
+                                                                       if(Length >= sizeof(UPDATE_LIST))\r
+                                                                       {\r
+                                                                               bResult = TRUE;\r
+                                                                               pUpdateList = (UPDATE_LIST*)pBuf;\r
+                                                                               if(pUpdateList->Version > *pVersion)\r
+                                                                               {\r
+                                                                                       *pVersion = pUpdateList->Version;\r
+                                                                                       _tcscpy(pVersionString, pUpdateList->VersionString);\r
+                                                                                       _tcscpy(pDescription, pUpdateList->Description);\r
+                                                                               }\r
+                                                                               if(bDownload)\r
+                                                                                       bResult = PrepareUpdates(pBuf, Length, DownloadDir);\r
+                                                                       }\r
                                                                }\r
-                                                               if(bDownload)\r
-                                                                       bResult = PrepareUpdates(&Buf1, Length, DownloadDir);\r
                                                        }\r
                                                }\r
+                                               free(pBuf);\r
                                        }\r
                                }\r
                        }\r
@@ -210,11 +397,13 @@ BOOL PrepareUpdates(void* pList, DWORD ListLength, LPCTSTR DownloadDir)
        BOOL bResult;\r
        UPDATE_LIST* pUpdateList;\r
        void* pBuf;\r
+       TCHAR LocalDir[MAX_PATH];\r
+       TCHAR* p;\r
        DWORD i;\r
        BOOL b;\r
+       TCHAR Path[MAX_PATH];\r
        DWORD Length;\r
        BYTE Hash[64];\r
-       TCHAR Path[MAX_PATH];\r
        bResult = FALSE;\r
        if(ListLength >= sizeof(UPDATE_LIST))\r
        {\r
@@ -224,40 +413,62 @@ BOOL PrepareUpdates(void* pList, DWORD ListLength, LPCTSTR DownloadDir)
                        bResult = TRUE;\r
                        DeleteDirectoryAndContents(DownloadDir);\r
                        CreateDirectory(DownloadDir, NULL);\r
-                       pBuf = malloc(16777216);\r
-                       for(i = 0; i < pUpdateList->FileCount; i++)\r
+                       if(pBuf = malloc(UPDATE_MAX_FILE_SIZE))\r
                        {\r
-                               b = FALSE;\r
-                               if(pUpdateList->File[i].Flags & UPDATE_LIST_FILE_FLAG_DIRECTORY)\r
+                               if(GetModuleFileName(NULL, LocalDir, MAX_PATH) > 0)\r
                                {\r
-                                       _tcscpy(Path, DownloadDir);\r
-                                       _tcscat(Path, _T("\\"));\r
-                                       _tcscat(Path, pUpdateList->File[i].DstPath);\r
-                                       if(CreateDirectory(Path, NULL))\r
-                                               b = TRUE;\r
+                                       if(p = _tcsrchr(LocalDir, _T('\\')))\r
+                                               *p = _T('\0');\r
                                }\r
-                               if(strlen(pUpdateList->File[i].SrcPath) > 0)\r
+                               else\r
+                                       _tcscpy(LocalDir, _T("."));\r
+                               for(i = 0; i < pUpdateList->FileCount; i++)\r
                                {\r
-                                       if(ReadFileViaHTTP(pBuf, 16777216, &Length, HTTP_USER_AGENT, UPDATE_SERVER, pUpdateList->File[i].SrcPath))\r
+                                       b = FALSE;\r
+                                       if(pUpdateList->File[i].Flags & UPDATE_LIST_FILE_FLAG_DIRECTORY)\r
+                                       {\r
+                                               _tcscpy(Path, DownloadDir);\r
+                                               _tcscat(Path, pUpdateList->File[i].DstPath);\r
+                                               if(CreateDirectory(Path, NULL))\r
+                                                       b = TRUE;\r
+                                       }\r
+                                       if(strlen(pUpdateList->File[i].SrcPath) > 0)\r
                                        {\r
-                                               GetHashSHA512(pBuf, Length, &Hash);\r
-                                               if(memcmp(&Hash, &pUpdateList->File[i].SrcHash, 64) == 0)\r
+                                               _tcscpy(Path, LocalDir);\r
+                                               _tcscat(Path, pUpdateList->File[i].DstPath);\r
+                                               if(LoadMemoryFromFileWithTimestamp(Path, pBuf, UPDATE_MAX_FILE_SIZE, &Length, NULL))\r
                                                {\r
-                                                       _tcscpy(Path, DownloadDir);\r
-                                                       _tcscat(Path, _T("\\"));\r
-                                                       _tcscat(Path, pUpdateList->File[i].DstPath);\r
-                                                       if(SaveMemoryToFileWithTimestamp(Path, pBuf, Length, &pUpdateList->File[i].Timestamp))\r
-                                                               b = TRUE;\r
+                                                       if(GetHashSHA512(pBuf, Length, &Hash))\r
+                                                       {\r
+                                                               if(memcmp(&Hash, &pUpdateList->File[i].SrcHash, 64) == 0)\r
+                                                                       b = TRUE;\r
+                                                       }\r
+                                               }\r
+                                               if(!b)\r
+                                               {\r
+                                                       if(ReadFileViaHTTP(pBuf, UPDATE_MAX_FILE_SIZE, &Length, HTTP_USER_AGENT, UPDATE_SERVER, pUpdateList->File[i].SrcPath))\r
+                                                       {\r
+                                                               if(GetHashSHA512(pBuf, Length, &Hash))\r
+                                                               {\r
+                                                                       if(memcmp(&Hash, &pUpdateList->File[i].SrcHash, 64) == 0)\r
+                                                                       {\r
+                                                                               _tcscpy(Path, DownloadDir);\r
+                                                                               _tcscat(Path, pUpdateList->File[i].DstPath);\r
+                                                                               if(SaveMemoryToFileWithTimestamp(Path, pBuf, Length, &pUpdateList->File[i].Timestamp))\r
+                                                                                       b = TRUE;\r
+                                                                       }\r
+                                                               }\r
+                                                       }\r
                                                }\r
                                        }\r
+                                       if(!b)\r
+                                       {\r
+                                               bResult = FALSE;\r
+                                               break;\r
+                                       }\r
                                }\r
-                               if(!b)\r
-                               {\r
-                                       bResult = FALSE;\r
-                                       break;\r
-                               }\r
+                               free(pBuf);\r
                        }\r
-                       free(pBuf);\r
                }\r
        }\r
        return bResult;\r
@@ -280,20 +491,23 @@ BOOL ApplyUpdates(LPCTSTR DestinationDir, LPCTSTR BackupDirName)
                _tcscat(Backup, _T("\\"));\r
                _tcscat(Backup, BackupDirName);\r
                DeleteDirectoryAndContents(Backup);\r
-               if(CopyAllFilesInDirectory(DestinationDir, Backup))\r
+               if(CreateDirectory(Backup, NULL))\r
                {\r
-                       _tcscpy(DestinationBackup, DestinationDir);\r
-                       _tcscat(DestinationBackup, _T("\\"));\r
-                       _tcscat(DestinationBackup, BackupDirName);\r
-                       if(CopyAllFilesInDirectory(Source, DestinationDir))\r
-                       {\r
-                               DeleteDirectoryAndContents(DestinationBackup);\r
-                               bResult = TRUE;\r
-                       }\r
-                       else\r
+                       if(CopyAllFilesInDirectory(DestinationDir, Backup))\r
                        {\r
-                               DeleteDirectoryAndContents(DestinationBackup);\r
-                               CopyAllFilesInDirectory(Backup, DestinationDir);\r
+                               _tcscpy(DestinationBackup, DestinationDir);\r
+                               _tcscat(DestinationBackup, _T("\\"));\r
+                               _tcscat(DestinationBackup, BackupDirName);\r
+                               if(CopyAllFilesInDirectory(Source, DestinationDir))\r
+                               {\r
+                                       DeleteDirectoryAndContents(DestinationBackup);\r
+                                       bResult = TRUE;\r
+                               }\r
+                               else\r
+                               {\r
+                                       DeleteDirectoryAndContents(DestinationBackup);\r
+                                       CopyAllFilesInDirectory(Backup, DestinationDir);\r
+                               }\r
                        }\r
                }\r
        }\r
@@ -353,7 +567,10 @@ BOOL RestartUpdateProcessAsAdministrator(LPCTSTR CommandLine, LPCTSTR Keyword)
                                memset(&Info, 0, sizeof(SHELLEXECUTEINFO));\r
                                Info.cbSize = sizeof(SHELLEXECUTEINFO);\r
                                Info.fMask = SEE_MASK_NOCLOSEPROCESS;\r
-                               Info.lpVerb = _T("runas");\r
+                               if(IsUserAnAdmin())\r
+                                       Info.lpVerb = _T("open");\r
+                               else\r
+                                       Info.lpVerb = _T("runas");\r
                                Info.lpFile = Path;\r
                                Info.lpParameters = NewCommandLine;\r
                                Info.nShow = SW_SHOW;\r