mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-02-10 18:05:41 +08:00
Fix bug 62427
CFileBinary::GetTime, CFileBinary::SetTime was updated Fix bugs with time in Zip/Unzip
This commit is contained in:
@ -43,6 +43,8 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <utime.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MAC
|
||||
@ -1688,38 +1690,161 @@ namespace NSFile
|
||||
g_overrideTmpPath = strTempPath;
|
||||
}
|
||||
|
||||
unsigned long CFileBinary::GetDateTime(const std::wstring & inputFile)
|
||||
bool CFileBinary::GetTime(const std::wstring& sFilename, struct tm* ptmLastWrite, struct tm* ptmLastAccess)
|
||||
{
|
||||
unsigned long result = 0;
|
||||
#if defined(_WIN32) || defined (_WIN64)
|
||||
bool result = true;
|
||||
|
||||
if (ptmLastWrite) memset(ptmLastWrite, 0, sizeof(struct tm));
|
||||
if (ptmLastAccess) memset(ptmLastAccess, 0, sizeof(struct tm));
|
||||
|
||||
#if defined(_WIN32) || defined (_WIN64) // windows
|
||||
|
||||
HANDLE hFile;
|
||||
hFile = ::CreateFileW(inputFile.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
hFile = ::CreateFileW(sFilename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hFile)
|
||||
{
|
||||
FILETIME ft; ft.dwLowDateTime = ft.dwHighDateTime = 0;
|
||||
if (GetFileTime(hFile, NULL, NULL, &ft))
|
||||
FILETIME ftLastWrite{}, ftLastAccess{};
|
||||
if (::GetFileTime(hFile, NULL, &ftLastAccess, &ftLastWrite))
|
||||
{
|
||||
WORD fatDate = 0, fatTime = 0;
|
||||
if (FileTimeToDosDateTime(&ft, &fatDate, &fatTime))
|
||||
FILETIME ftLastWriteLocal{}, ftLastAccessLocal{};
|
||||
result = result && ::FileTimeToLocalFileTime(&ftLastWrite, &ftLastWriteLocal);
|
||||
result = result && ::FileTimeToLocalFileTime(&ftLastAccess, &ftLastAccessLocal);
|
||||
|
||||
SYSTEMTIME stLastWrite{}, stLastAccess{};
|
||||
result = result && ::FileTimeToSystemTime(&ftLastWriteLocal, &stLastWrite);
|
||||
result = result && ::FileTimeToSystemTime(&ftLastAccessLocal, &stLastAccess);
|
||||
|
||||
auto set_tm_by_st = [] (struct tm* time_tm, SYSTEMTIME* time_st) {
|
||||
time_tm->tm_sec = static_cast<int>(time_st->wSecond);
|
||||
time_tm->tm_min = static_cast<int>(time_st->wMinute);
|
||||
time_tm->tm_hour = static_cast<int>(time_st->wHour);
|
||||
time_tm->tm_mday = static_cast<int>(time_st->wDay);
|
||||
time_tm->tm_mon = static_cast<int>(time_st->wMonth);
|
||||
time_tm->tm_year = static_cast<int>(time_st->wYear);
|
||||
};
|
||||
|
||||
if (result)
|
||||
{
|
||||
result = (fatDate << 16) + fatTime;
|
||||
if (ptmLastWrite) set_tm_by_st(ptmLastWrite, &stLastWrite);
|
||||
if (ptmLastAccess) set_tm_by_st(ptmLastAccess, &stLastAccess);
|
||||
}
|
||||
}
|
||||
else
|
||||
result = false;
|
||||
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
#else
|
||||
std::string inputFileA = U_TO_UTF8(inputFile);
|
||||
#if defined(__linux__) && !defined(_MAC)
|
||||
struct stat attrib;
|
||||
stat(inputFileA.c_str(), &attrib);
|
||||
result = attrib.st_mtim.tv_nsec;
|
||||
#else
|
||||
struct stat attrib;
|
||||
stat(inputFileA.c_str(), &attrib);
|
||||
result = (unsigned long)attrib.st_mtimespec.tv_nsec;
|
||||
#endif
|
||||
#endif
|
||||
else
|
||||
result = false;
|
||||
|
||||
|
||||
#else // linux or macOS
|
||||
struct stat attr;
|
||||
result = (0 == stat(U_TO_UTF8(sFilename).c_str(), &attr));
|
||||
|
||||
if (result)
|
||||
{
|
||||
auto set_tm_by_secs = [] (struct tm* time_tm, time_t time_secs) {
|
||||
struct tm* ltime = localtime(&time_secs);
|
||||
*time_tm = *ltime;
|
||||
time_tm->tm_year += 1900;
|
||||
time_tm->tm_mon += 1;
|
||||
};
|
||||
|
||||
time_t m_secs = attr.st_mtim.tv_sec; // edit
|
||||
time_t a_secs = attr.st_atim.tv_sec; // access
|
||||
|
||||
if (ptmLastWrite) set_tm_by_secs(ptmLastWrite, m_secs);
|
||||
if (ptmLastAccess) set_tm_by_secs(ptmLastAccess, a_secs);
|
||||
}
|
||||
|
||||
#endif // defined(_WIN32) || defined (_WIN64)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CFileBinary::SetTime(const std::wstring& sFilename, struct tm* ptmLastWrite, struct tm* ptmLastAccess)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
#if defined(_WIN32) || defined (_WIN64) // windows
|
||||
|
||||
auto set_st_by_tm = [] (SYSTEMTIME* time_st, struct tm* time_tm) {
|
||||
time_st->wSecond = static_cast<WORD>(time_tm->tm_sec);
|
||||
time_st->wMinute = static_cast<WORD>(time_tm->tm_min);
|
||||
time_st->wHour = static_cast<WORD>(time_tm->tm_hour);
|
||||
time_st->wDay = static_cast<WORD>(time_tm->tm_mday);
|
||||
time_st->wMonth = static_cast<WORD>(time_tm->tm_mon);
|
||||
time_st->wYear = static_cast<WORD>(time_tm->tm_year);
|
||||
};
|
||||
|
||||
SYSTEMTIME stLastWrite{}, stLastAccess{};
|
||||
if (ptmLastWrite) set_st_by_tm(&stLastWrite, ptmLastWrite);
|
||||
if (ptmLastAccess) set_st_by_tm(&stLastAccess, ptmLastAccess);
|
||||
|
||||
FILETIME ftLastWriteLocal{}, ftLastAccessLocal{};
|
||||
if (ptmLastWrite) result = result && ::SystemTimeToFileTime(&stLastWrite, &ftLastWriteLocal);
|
||||
if (ptmLastAccess) result = result && ::SystemTimeToFileTime(&stLastAccess, &ftLastAccessLocal);
|
||||
|
||||
FILETIME ftLastWrite{}, ftLastAccess{};
|
||||
if (ptmLastWrite) result = result && ::LocalFileTimeToFileTime(&ftLastWriteLocal, &ftLastWrite);
|
||||
if (ptmLastAccess) result = result && ::LocalFileTimeToFileTime(&ftLastAccessLocal, &ftLastAccess);
|
||||
|
||||
if (result)
|
||||
{
|
||||
HANDLE hFile;
|
||||
hFile = ::CreateFileW(sFilename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile)
|
||||
{
|
||||
FILETIME* pftLastWrite = NULL;
|
||||
FILETIME* pftLastAccess = NULL;
|
||||
|
||||
if (ptmLastWrite) pftLastWrite = &ftLastWrite;
|
||||
if (ptmLastAccess) pftLastAccess = &ftLastAccess;
|
||||
|
||||
result = SetFileTime(hFile, NULL, pftLastAccess, pftLastWrite);
|
||||
}
|
||||
else
|
||||
result = false;
|
||||
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
|
||||
#else // linux or macOS
|
||||
struct stat attr;
|
||||
std::string sFilenameA = U_TO_UTF8(sFilename);
|
||||
result = (0 == stat(sFilenameA.c_str(), &attr));
|
||||
|
||||
if (result)
|
||||
{
|
||||
time_t m_secs = attr.st_mtim.tv_sec; // edit
|
||||
time_t a_secs = attr.st_atim.tv_sec; // access
|
||||
|
||||
time_t new_m_secs = m_secs;
|
||||
time_t new_a_secs = a_secs;
|
||||
|
||||
if (ptmLastWrite)
|
||||
{
|
||||
struct tm tmLastWriteUnix = *ptmLastWrite;
|
||||
tmLastWriteUnix.tm_year -= 1900;
|
||||
tmLastWriteUnix.tm_mon -= 1;
|
||||
new_m_secs = mktime(&tmLastWriteUnix);
|
||||
}
|
||||
if (ptmLastAccess)
|
||||
{
|
||||
struct tm tmLastAccessUnix = *ptmLastAccess;
|
||||
tmLastAccessUnix.tm_year -= 1900;
|
||||
tmLastAccessUnix.tm_mon -= 1;
|
||||
new_a_secs = mktime(&tmLastAccessUnix);
|
||||
}
|
||||
|
||||
utimbuf new_time{};
|
||||
new_time.actime = new_a_secs;
|
||||
new_time.modtime = new_m_secs;
|
||||
utime(sFilenameA.c_str(), &new_time);
|
||||
}
|
||||
#endif // defined(_WIN32) || defined (_WIN64)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,7 +194,18 @@ namespace NSFile
|
||||
static bool OpenTempFile(std::wstring *pwsName, FILE **ppFile, wchar_t *wsMode, wchar_t *wsExt, wchar_t *wsFolder, wchar_t* wsName = NULL);
|
||||
static FILE* OpenFileNative(const std::wstring& sFileName, const std::wstring& sMode);
|
||||
|
||||
static unsigned long GetDateTime(const std::wstring & strFileName);
|
||||
// returns true if everything is OK;
|
||||
// you can set ptmLastWrite / ptmLastAccess to nullptr if you are not going to use them;
|
||||
// tm_wday && tm_yday && tm_isdst is unused on windows
|
||||
static bool GetTime(const std::wstring& sFilename,
|
||||
struct tm* ptmLastWrite = nullptr,
|
||||
struct tm* ptmLastAccess = nullptr);
|
||||
|
||||
// returns true if everything is OK;
|
||||
// you can set ptmLastWrite / ptmLastAccess to nullptr if you are not going to change them
|
||||
static bool SetTime(const std::wstring& sFilename,
|
||||
struct tm* ptmLastWrite = nullptr,
|
||||
struct tm* ptmLastAccess = nullptr);
|
||||
};
|
||||
|
||||
class KERNEL_DECL CBase64Converter
|
||||
|
||||
@ -53,7 +53,7 @@ public:
|
||||
HRESULT ExtractToDirectory (const std::wstring& zipFile, const std::wstring& unzipDir, wchar_t* password, short extract_without_path);
|
||||
HRESULT ExtractToDirectory (BYTE* data, size_t len, const std::wstring& unzipDir, wchar_t* password, short extract_without_path);
|
||||
|
||||
HRESULT CompressFileOrDirectory (const std::wstring& name, const std::wstring& outputFile, bool bSorted = false, int method = Z_DEFLATED, short level = -1, bool bDateTime = false);
|
||||
HRESULT CompressFileOrDirectory (const std::wstring& name, const std::wstring& outputFile, bool bSorted = false, int method = Z_DEFLATED, short level = -1, bool bDateTime = true);
|
||||
|
||||
HRESULT Uncompress (BYTE* destBuf, ULONG* destSize, BYTE* sourceBuf, ULONG sourceSize);
|
||||
HRESULT Compress (BYTE* destBuf, ULONG* destSize, BYTE* sourceBuf, ULONG sourceSize, short level = -1);
|
||||
|
||||
@ -217,28 +217,6 @@ namespace ZLibZipUtils
|
||||
|
||||
/*========================================================================================================*/
|
||||
|
||||
/* change_file_date : change the date/time of a file
|
||||
filename : the filename of the file where date/time must be modified
|
||||
dosdate : the new date at the MSDos format (4 bytes)
|
||||
tmu_date : the SAME new date at the tm_unz format */
|
||||
static void change_file_date( const wchar_t *filename, uLong dosdate, tm_unz tmu_date )
|
||||
{
|
||||
#if defined(_WIN32) || defined (_WIN64)
|
||||
HANDLE hFile;
|
||||
FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
|
||||
|
||||
hFile = CreateFileW(filename,GENERIC_READ | GENERIC_WRITE,
|
||||
0,NULL,OPEN_EXISTING,0,NULL);
|
||||
GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
|
||||
DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
|
||||
LocalFileTimeToFileTime(&ftLocal,&ftm);
|
||||
SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
|
||||
CloseHandle(hFile);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*========================================================================================================*/
|
||||
|
||||
static void replace_all(std::string& subject, const std::string& search, const std::string& replace)
|
||||
{
|
||||
size_t pos = 0;
|
||||
@ -380,13 +358,22 @@ namespace ZLibZipUtils
|
||||
break;
|
||||
}
|
||||
}
|
||||
// ?
|
||||
while (err>0);
|
||||
|
||||
//close вызовется в oFile
|
||||
|
||||
if (err==0)
|
||||
{
|
||||
change_file_date(write_filename, file_info.dosDate, file_info.tmu_date);
|
||||
oFile.CloseFile();
|
||||
|
||||
struct tm time;
|
||||
memset(&time, 0, sizeof(struct tm));
|
||||
time.tm_sec = file_info.tmu_date.tm_sec;
|
||||
time.tm_min = file_info.tmu_date.tm_min;
|
||||
time.tm_hour = file_info.tmu_date.tm_hour;
|
||||
time.tm_mday = file_info.tmu_date.tm_mday;
|
||||
time.tm_mon = file_info.tmu_date.tm_mon + 1;
|
||||
time.tm_year = file_info.tmu_date.tm_year;
|
||||
|
||||
NSFile::CFileBinary::SetTime(write_filename, &time);
|
||||
}
|
||||
}
|
||||
|
||||
@ -568,16 +555,24 @@ namespace ZLibZipUtils
|
||||
|
||||
zip_fileinfo zinfo;
|
||||
zinfo.dosDate = zinfo.external_fa = zinfo.internal_fa = 0;
|
||||
zinfo.tmz_date.tm_sec = zinfo.tmz_date.tm_min = zinfo.tmz_date.tm_hour = 0;
|
||||
zinfo.tmz_date.tm_mday = 1;
|
||||
zinfo.tmz_date.tm_mon = 0;
|
||||
zinfo.tmz_date.tm_year = 1980;
|
||||
|
||||
zip_fileinfo* zi_new = zi ? zi : &zinfo;
|
||||
if (bDateTime )
|
||||
|
||||
if (bDateTime)
|
||||
{
|
||||
zi_new->dosDate = oFile.GetDateTime(file_name);
|
||||
struct tm edited;
|
||||
bool ok = NSFile::CFileBinary::GetTime(file_name, &edited);
|
||||
if (ok)
|
||||
{
|
||||
zi_new->tmz_date.tm_sec = edited.tm_sec;
|
||||
zi_new->tmz_date.tm_min = edited.tm_min;
|
||||
zi_new->tmz_date.tm_hour = edited.tm_hour;
|
||||
zi_new->tmz_date.tm_mday = edited.tm_mday;
|
||||
zi_new->tmz_date.tm_mon = edited.tm_mon - 1;
|
||||
zi_new->tmz_date.tm_year = edited.tm_year;
|
||||
}
|
||||
}
|
||||
|
||||
if(oFile.OpenFile(file_name))
|
||||
{
|
||||
DWORD dwSizeRead;
|
||||
@ -726,9 +721,24 @@ namespace ZLibZipUtils
|
||||
|
||||
zip_fileinfo zinfo;
|
||||
zinfo.external_fa = zinfo.internal_fa = 0;
|
||||
zinfo.dosDate = bDateTime ? oFile.GetDateTime(inputFile) : 0;
|
||||
zinfo.dosDate = 0;
|
||||
|
||||
if(oFile.OpenFile(inputFile))
|
||||
if (bDateTime)
|
||||
{
|
||||
struct tm edited;
|
||||
bool ok = NSFile::CFileBinary::GetTime(inputFile, &edited);
|
||||
if (ok)
|
||||
{
|
||||
zinfo.tmz_date.tm_sec = edited.tm_sec;
|
||||
zinfo.tmz_date.tm_min = edited.tm_min;
|
||||
zinfo.tmz_date.tm_hour = edited.tm_hour;
|
||||
zinfo.tmz_date.tm_mday = edited.tm_mday;
|
||||
zinfo.tmz_date.tm_mon = edited.tm_mon - 1;
|
||||
zinfo.tmz_date.tm_year = edited.tm_year;
|
||||
}
|
||||
}
|
||||
|
||||
if (oFile.OpenFile(inputFile))
|
||||
{
|
||||
DWORD dwSizeRead;
|
||||
BYTE* pData = new BYTE[oFile.GetFileSize()];
|
||||
|
||||
Reference in New Issue
Block a user