From 8c17ce67c5247810de012b9a78674d97db5e500f Mon Sep 17 00:00:00 2001 From: Keelan Stuart Date: Thu, 11 Jun 2020 23:28:22 -0400 Subject: [PATCH] A number of features and fixes - welcome and license messages, when referencing files to use the contents of, were not displayed properly if the file was given relative to the location of the sfxpp file itself. this is now fixed. - files can now be given http[s] source paths and they will be downloaded when the installer runs. - related to that, there was a bug with the downloader; it could corrupt files by potentially writing more data than was received. this is now fixed - added GetFileNameFromPath js function, which finds the file name portion of a full path and returns a string containing only that. - the TextFileReadLn js function could potentially return bad data, in addition to leaving the trailing \n. this is now fixed. --- Archiver/Include/Archiver.h | 2 + Archiver/Source/FastLZArchiver.cpp | 201 ++++++++++++-------- Archiver/Source/FastLZArchiver.h | 3 +- sfx/sfx/HttpDownload.cpp | 34 ++-- sfx/sfx/ProgressDlg.cpp | 118 ++++++++++-- sfx/sfx/sfx.vcxproj | 6 +- sfx/sfxPackager/sfxPackager.rc | Bin 46460 -> 46456 bytes sfx/sfxPackager/sfxPackager.vcxproj | 16 +- sfx/sfxPackager/sfxPackager.vcxproj.filters | 2 - sfx/sfxPackager/sfxPackagerDoc.cpp | 130 +++++++++---- 10 files changed, 357 insertions(+), 155 deletions(-) diff --git a/Archiver/Include/Archiver.h b/Archiver/Include/Archiver.h index 6c67d23..37d1f92 100644 --- a/Archiver/Include/Archiver.h +++ b/Archiver/Include/Archiver.h @@ -143,6 +143,8 @@ class IExtractor ER_DONE, + ER_MUSTDOWNLOAD, + ER_UNKNOWN_ERROR }; diff --git a/Archiver/Source/FastLZArchiver.cpp b/Archiver/Source/FastLZArchiver.cpp index db00dff..66b5175 100644 --- a/Archiver/Source/FastLZArchiver.cpp +++ b/Archiver/Source/FastLZArchiver.cpp @@ -65,101 +65,130 @@ size_t CFastLZArchiver::GetFileCount(IArchiver::INFO_MODE mode) // Adds a file to the archive CFastLZArchiver::ADD_RESULT CFastLZArchiver::AddFile(const TCHAR *src_filename, const TCHAR *dst_filename, uint64_t *sz_uncomp, uint64_t *sz_comp, const TCHAR *scriptsnippet) { - CFastLZArchiver::ADD_RESULT ret = AR_OK; + CFastLZArchiver::ADD_RESULT ret = AR_UNKNOWN_ERROR; - HANDLE hin = CreateFile(src_filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if (hin != INVALID_HANDLE_VALUE) + SFileTableEntry fte; + + TCHAR dst_path[MAX_PATH]; + _tcscpy_s(dst_path, MAX_PATH, dst_filename); + + // for download references (filenames that contain the "http[s]:\\" marker, we don't care about disk spanning, etc... + // there's no actual file, so just add it to the file table and mark it as a doanloadable + const TCHAR *pss = src_filename; + if (!_tcsnicmp(pss, _T("http"), 4)) { - TCHAR dst_path[MAX_PATH]; - _tcscpy_s(dst_path, MAX_PATH, dst_filename); - PathRemoveFileSpec(dst_path); + pss += 4; + if (!_tcsnicmp(pss, _T("s"), 1)) + pss++; - TCHAR *fn = PathFindFileName(dst_filename); + if (!_tcsnicmp(pss, _T("://"), 3)) + { + fte.m_Flags |= SFileTableEntry::FTEFLAG_DOWNLOAD; + } + } - SFileTableEntry fte; + if (!(fte.m_Flags & SFileTableEntry::FTEFLAG_DOWNLOAD)) + PathRemoveFileSpec(dst_path); - fte.m_Filename = fn; - fte.m_Path = dst_path; + const TCHAR *fn = (fte.m_Flags & SFileTableEntry::FTEFLAG_DOWNLOAD) ? src_filename : PathFindFileName(dst_filename); - // store the size of the uncompressed file - LARGE_INTEGER fsz; - GetFileSizeEx(hin, &fsz); - fte.m_UncompressedSize = fsz.QuadPart; - if (sz_uncomp) - *sz_uncomp = fte.m_UncompressedSize; + fte.m_Filename = fn; + fte.m_Path = dst_path; - // store the file time - GetFileTime(hin, &(fte.m_FTCreated), NULL, &(fte.m_FTModified)); + fte.m_ScriptSnippet = scriptsnippet; - SFileBlock b; + if (fte.m_Flags & SFileTableEntry::FTEFLAG_DOWNLOAD) + { + ret = AR_OK_UNCOMPRESSED; + } + else + { + HANDLE hin = CreateFile(src_filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (hin != INVALID_HANDLE_VALUE) + { + // store the size of the uncompressed file + LARGE_INTEGER fsz; + GetFileSizeEx(hin, &fsz); + fte.m_UncompressedSize = fsz.QuadPart; + if (sz_uncomp) + *sz_uncomp = fte.m_UncompressedSize; - fte.m_Offset = m_pah->GetOffset(); + // store the file time + GetFileTime(hin, &(fte.m_FTCreated), NULL, &(fte.m_FTModified)); - fte.m_ScriptSnippet = scriptsnippet; + SFileBlock b; - // read uncompressed blocks of data from the file - while (b.ReadUncompressedData(hin)) - { - fte.m_BlockCount++; + fte.m_Offset = m_pah->GetOffset(); - // compress and write the data to the archive - if (b.CompressData()) - { - // update the compressed size of the file - fte.m_CompressedSize += b.m_Header.m_SizeC; - } - else + // read uncompressed blocks of data from the file + while (b.ReadUncompressedData(hin)) { - fte.m_CompressedSize += b.m_Header.m_SizeU; - } + fte.m_BlockCount++; + + // compress and write the data to the archive + if (b.CompressData()) + { + // update the compressed size of the file + fte.m_CompressedSize += b.m_Header.m_SizeC; + } + else + { + fte.m_CompressedSize += b.m_Header.m_SizeU; + } - b.WriteCompressedData(m_pah->GetHandle()); + b.WriteCompressedData(m_pah->GetHandle()); - // spanning logic - if ((m_MaxSize != UINT64_MAX) && ((m_pah->GetLength() + (uint64_t)ComputeFileTableSize()) >= m_MaxSize)) - { - // if we're spanning, then we need to add this entry to the file table now and do some cleanup - m_FileTable.push_back( fte ); + // spanning logic + if ((m_MaxSize != UINT64_MAX) && ((m_pah->GetLength() + (uint64_t)ComputeFileTableSize()) >= m_MaxSize)) + { + // if we're spanning, then we need to add this entry to the file table now and do some cleanup + m_FileTable.push_back(fte); - // reset the block count and compressed size (because this should technically be a new data stream) - fte.m_BlockCount = 0; - fte.m_CompressedSize = 0; + // reset the block count and compressed size (because this should technically be a new data stream) + fte.m_BlockCount = 0; + fte.m_CompressedSize = 0; - // have the stream handle spanning behind the scenes - m_pah->Span(); + // have the stream handle spanning behind the scenes + m_pah->Span(); - DWORD bw; - uint32_t magic = IArchiver::MAGIC; - WriteFile(m_pah->GetHandle(), &magic, sizeof(uint32_t), &bw, NULL); + DWORD bw; + uint32_t magic = IArchiver::MAGIC; + WriteFile(m_pah->GetHandle(), &magic, sizeof(uint32_t), &bw, NULL); - uint32_t comp_magic = CFastLZArchiver::MAGIC_FASTLZ; - WriteFile(m_pah->GetHandle(), &comp_magic, sizeof(uint32_t), &bw, NULL); + uint32_t comp_magic = CFastLZArchiver::MAGIC_FASTLZ; + WriteFile(m_pah->GetHandle(), &comp_magic, sizeof(uint32_t), &bw, NULL); - uint64_t flags = 0; - WriteFile(m_pah->GetHandle(), &flags, sizeof(uint64_t), &bw, NULL); + uint64_t flags = 0; + WriteFile(m_pah->GetHandle(), &flags, sizeof(uint64_t), &bw, NULL); - // after the span, we should expect that offset will be different - m_InitialOffset = m_pah->GetOffset(); + // after the span, we should expect that offset will be different + m_InitialOffset = m_pah->GetOffset(); - fte.m_Offset = m_pah->GetOffset(); + fte.m_Offset = m_pah->GetOffset(); - // mark it as spanned so that the next archive can append to, rather than create, the file - fte.m_Flags |= SFileTableEntry::FTEFLAG_SPANNED; + // mark it as spanned so that the next archive can append to, rather than create, the file + fte.m_Flags |= SFileTableEntry::FTEFLAG_SPANNED; + } } - } - if (fte.m_CompressedSize == fte.m_UncompressedSize) - ret = AR_OK_UNCOMPRESSED; + if (fte.m_CompressedSize >= fte.m_UncompressedSize) + ret = AR_OK_UNCOMPRESSED; + else + ret = AR_OK; + + if (sz_comp) + *sz_comp = (fte.m_CompressedSize != (uint64_t)-1) ? fte.m_CompressedSize : fte.m_UncompressedSize; - if (sz_comp) - *sz_comp = (fte.m_CompressedSize != (uint64_t)-1) ? fte.m_CompressedSize : fte.m_UncompressedSize; + CloseHandle(hin); + } + } + if (ret <= AR_OK_UNCOMPRESSED) + { // add the file to the file table m_FileTable.push_back( fte ); m_OverallFileCount++; - - CloseHandle(hin); } return ret; @@ -711,23 +740,39 @@ IExtractor::EXTRACT_RESULT CFastLZExtractor::ExtractFile(size_t file_idx, tstrin SFileTableEntry &fte = m_FileTable.at(file_idx); - // if we're not where we're supposed to be for the file indicated, then we need to move the file pointer - if ((m_CachedFilePosition != m_pah->GetOffset()) || (m_CachedFilePosition != fte.m_Offset)) - { - LARGE_INTEGER p; - p.QuadPart = fte.m_Offset; - SetFilePointerEx(m_pah->GetHandle(), p, NULL, FILE_BEGIN); - } - TCHAR path[MAX_PATH]; tstring _cvtpath, cvtpath; + tstring _cvtfile, cvtfile; + + if (!(fte.m_Flags & SFileTableEntry::FTEFLAG_DOWNLOAD)) + { + // if we're not where we're supposed to be for the file indicated, then we need to move the file pointer + if ((m_CachedFilePosition != m_pah->GetOffset()) || (m_CachedFilePosition != fte.m_Offset)) + { + LARGE_INTEGER p; + p.QuadPart = fte.m_Offset; + SetFilePointerEx(m_pah->GetHandle(), p, NULL, FILE_BEGIN); + } + + ReplaceEnvironmentVariables(fte.m_Filename, _cvtfile); + ReplaceRegistryKeys(_cvtfile, cvtfile); + } + else + { + cvtfile = fte.m_Filename; + } + ReplaceEnvironmentVariables(fte.m_Path, _cvtpath); ReplaceRegistryKeys(_cvtpath, cvtpath); - tstring _cvtfile, cvtfile; - ReplaceEnvironmentVariables(fte.m_Filename, _cvtfile); - ReplaceRegistryKeys(_cvtfile, cvtfile); + if (fte.m_Flags & SFileTableEntry::FTEFLAG_DOWNLOAD) + { + if (output_filename) + *output_filename = cvtpath; + + return IExtractor::ER_MUSTDOWNLOAD; + } if (!override_filename) { @@ -753,6 +798,9 @@ IExtractor::EXTRACT_RESULT CFastLZExtractor::ExtractFile(size_t file_idx, tstrin _tcscat_s(path, MAX_PATH, override_filename); } + if (output_filename) + *output_filename = path; + bool append = false; // if we're spanned and the file index we want is 0, then we need to append to the file rather than creating a new one if ((fte.m_Flags & SFileTableEntry::FTEFLAG_SPANNED) && (file_idx == 0)) @@ -764,9 +812,6 @@ IExtractor::EXTRACT_RESULT CFastLZExtractor::ExtractFile(size_t file_idx, tstrin if ((hf != INVALID_HANDLE_VALUE) || test_only) { - if (output_filename) - *output_filename = path; - if (append && !test_only) SetFilePointer(hf, 0, NULL, FILE_END); diff --git a/Archiver/Source/FastLZArchiver.h b/Archiver/Source/FastLZArchiver.h index a35e664..f1997d5 100644 --- a/Archiver/Source/FastLZArchiver.h +++ b/Archiver/Source/FastLZArchiver.h @@ -24,7 +24,8 @@ struct sFileTableEntry { enum { - FTEFLAG_SPANNED = 0x0000000000000001, // a spanned file will be partially in multiple files + FTEFLAG_SPANNED = 0x0000000000000001, // a spanned file will be partially in multiple files + FTEFLAG_DOWNLOAD = 0x0000000000000002, // an empty file that is just a download reference }; uint64_t m_Flags; diff --git a/sfx/sfx/HttpDownload.cpp b/sfx/sfx/HttpDownload.cpp index edace30..6a096f5 100644 --- a/sfx/sfx/HttpDownload.cpp +++ b/sfx/sfx/HttpDownload.cpp @@ -108,11 +108,17 @@ extern bool FLZACreateDirectories(const TCHAR *dir); BOOL CHttpDownloader::DownloadHttpFile(const TCHAR *szUrl, const TCHAR *szDestFile, const TCHAR *szDestDir, float *ppct, BOOL *pabortque, UINT expected_size) { + if (!szUrl) + return false; + if (sCommFailures > 10) return false; BOOL retval = false; + tstring url = szUrl; + std::replace(url.begin(), url.end(), _T('\\'), _T('/')); + FLZACreateDirectories(szDestDir); #if defined(DOWNLOADER_USES_WININET) @@ -133,11 +139,11 @@ BOOL CHttpDownloader::DownloadHttpFile(const TCHAR *szUrl, const TCHAR *szDestFi PathAppend(filepath, szDestFile); } - if (!PathIsURL(szUrl)) + if (!PathIsURL(url.c_str())) { - if (PathFileExists(szUrl)) + if (PathFileExists(url.c_str())) { - return CopyFile(szUrl, filepath, false); + return CopyFile(url.c_str(), filepath, false); } } @@ -152,11 +158,11 @@ BOOL CHttpDownloader::DownloadHttpFile(const TCHAR *szUrl, const TCHAR *szDestFi DWORD flags = INTERNET_FLAG_RESYNCHRONIZE | INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI; - if (_tcsnicmp(szUrl, _T("https"), 5) == 0) + if (_tcsnicmp(url.c_str(), _T("https"), 5) == 0) flags |= INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_SECURE; // Open the url specified - m_hUrl = InternetOpenUrl(m_hInet, szUrl, NULL, 0, flags, (DWORD_PTR)this); + m_hUrl = InternetOpenUrl(m_hInet, url.c_str(), NULL, 0, flags, (DWORD_PTR)this); // if we didn't get the hurl back immediately (which we won't, because it's an async op) // then wait until the semaphore clears @@ -219,13 +225,14 @@ BOOL CHttpDownloader::DownloadHttpFile(const TCHAR *szUrl, const TCHAR *szDestFi hfile = 0; } - DWORD amount_to_download = chunked ? BUFFER_SIZE : _ttoi(buf_query); + uint64_t amount_to_download = chunked ? BUFFER_SIZE : _ttoi64(buf_query); if (amount_to_download && (errcode < 400)) { empty_file = false; - DWORD amount_downloaded = 0; + uint64_t amount_downloaded = 0; + uint64_t amount_remaining = amount_to_download; INTERNET_BUFFERS inbuf[2]; int bufidx; @@ -269,16 +276,17 @@ BOOL CHttpDownloader::DownloadHttpFile(const TCHAR *szUrl, const TCHAR *szDestFi { void *data_start = inbuf[bufidx].lpvBuffer; - DWORD data_size = inbuf[bufidx].dwBufferLength; + uint64_t data_size = std::min(amount_remaining, uint64_t(inbuf[bufidx].dwBufferLength)); // and if we have a valid file handle, write data if (hfile) { DWORD bwritten; - WriteFile(hfile, data_start, data_size, &bwritten, NULL); + WriteFile(hfile, data_start, (DWORD)data_size, &bwritten, NULL); } - amount_downloaded += inbuf[bufidx].dwBufferLength; + amount_downloaded += data_size; + amount_remaining -= data_size; if (ppct) *ppct = chunked ? 0 : (float)amount_downloaded / (float)amount_to_download; @@ -365,9 +373,9 @@ BOOL CHttpDownloader::DownloadHttpFile(const TCHAR *szUrl, const TCHAR *szDestFi { CURLcode curlret; - TCHAR *canonUrl = (TCHAR *)_alloca(((_tcslen(szUrl) * 3) + 1) * sizeof(TCHAR));; - DWORD cch = (UINT)_tcslen(szUrl) * 3; - HRESULT hr = UrlCanonicalize(szUrl, canonUrl, &cch, URL_ESCAPE_UNSAFE); + TCHAR *canonUrl = (TCHAR *)_alloca(((_tcslen(url.c_str()) * 3) + 1) * sizeof(TCHAR));; + DWORD cch = (UINT)_tcslen(url.c_str()) * 3; + HRESULT hr = UrlCanonicalize(url.c_str(), canonUrl, &cch, URL_ESCAPE_UNSAFE); canonUrl[cch] = '\0'; int len = WideCharToMultiByte(CP_UTF8, 0, canonUrl, -1, NULL, 0, NULL, NULL); diff --git a/sfx/sfx/ProgressDlg.cpp b/sfx/sfx/ProgressDlg.cpp index 88ea2c0..71ca422 100644 --- a/sfx/sfx/ProgressDlg.cpp +++ b/sfx/sfx/ProgressDlg.cpp @@ -872,7 +872,7 @@ void scTextFileOpen(CScriptVar *c, void *userdata) FILE *f = nullptr; if (pfile) - f = _tfopen(pfile->getString().c_str(), pmode ? pmode->getString().c_str() : _T("r")); + f = _tfopen(pfile->getString().c_str(), pmode ? pmode->getString().c_str() : _T("r, ccs=UTF-8")); CScriptVar *ret = c->getReturnVar(); if (ret) @@ -905,8 +905,15 @@ void scTextFileReadLn(CScriptVar *c, void *userdata) if (f) { TCHAR _s[4096]; - _fgetts(_s, 4096, f); - s = _s; + if (_fgetts(_s, 4096, f)) + { + size_t n = _tcslen(_s); + + if ((n > 0) && (n <= 4096)) + _s[n - 1] = _T('\0'); + + s = _s; + } } } @@ -963,6 +970,29 @@ void scGetCurrentDateStr(CScriptVar *c, void *userdata) } +void scGetFileNameFromPath(CScriptVar *c, void *userdata) +{ + CScriptVar *pfilename = c->getParameter(_T("filepath")); + + tstring n; + if (pfilename) + { + tstring _n = pfilename->getString(); + size_t o = _n.find_last_of(_T("\\/")); + tstring::const_iterator it = _n.cbegin(); + if (o <= _n.length()) + { + it += (o + 1); + while (it != _n.cend()) { n += *it; it++; } + } + } + + CScriptVar *ret = c->getReturnVar(); + if (ret) + ret->setString(n); +} + + // ****************************************************************************** // ****************************************************************************** @@ -1009,6 +1039,7 @@ DWORD CProgressDlg::RunInstall() theApp.m_js.addNative(_T("function GetCurrentDateString()"), scGetCurrentDateStr, (void *)this); theApp.m_js.addNative(_T("function GetGlobalInt(name)"), scGetGlobalInt, (void *)this); theApp.m_js.addNative(_T("function GetExeVersion(file)"), scGetExeVersion, (void*)this); + theApp.m_js.addNative(_T("function GetFileNameFromPath(filepath)"), scGetFileNameFromPath, (void*)this); theApp.m_js.addNative(_T("function GetLicenseKey()"), scGetLicenseKey, (void *)this); theApp.m_js.addNative(_T("function GetLicenseOrg()"), scGetLicenseOrg, (void *)this); theApp.m_js.addNative(_T("function GetLicenseUser()"), scGetLicenseUser, (void *)this); @@ -1037,7 +1068,7 @@ DWORD CProgressDlg::RunInstall() iscr += _T("var BASEPATH = \""); iscr += (LPCTSTR)(theApp.m_InstallPath); - iscr += _T("\"; // the base install path\n\n"); + iscr += _T("\"; /* the base install path */\n\n"); iscr += theApp.m_Script[CSfxApp::EScriptType::INIT]; @@ -1090,41 +1121,88 @@ DWORD CProgressDlg::RunInstall() IExtractor::EXTRACT_RESULT er = pie->ExtractFile(i, &ffull, nullptr, theApp.m_TestOnlyMode); - for (tstring::iterator rit = ffull.begin(), last_rit = ffull.end(); rit != last_rit; rit++) - { - if (*rit == _T('\\')) - *rit = _T('/'); - } - - for (tstring::iterator rit = fpath.begin(), last_rit = fpath.end(); rit != last_rit; rit++) - { - if (*rit == _T('\\')) - *rit = _T('/'); - } switch (er) { + case IExtractor::ER_MUSTDOWNLOAD: + { + TCHAR dir[MAX_PATH], *_dir = dir; + _tcscpy_s(dir, ffull.c_str()); + while (_dir && *(_dir++)) { if (*_dir == _T('/')) *_dir = _T('\\'); } + + msg.Format(_T("Downloading \"%s\" from (%s)... "), ffull.c_str(), fname.c_str()); + m_Status.SetSel(-1, 0, FALSE); + m_Status.ReplaceSel(msg); + + if (!theApp.m_TestOnlyMode) + { + PathRemoveFileSpec(dir); + FLZACreateDirectories(dir); + + CHttpDownloader dl; + if (!dl.DownloadHttpFile(fname.c_str(), ffull.c_str(), _T(""))) + { + msg.Format(_T("[download failed]\r\n")); + m_Status.SetSel(-1, 0, FALSE); + m_Status.ReplaceSel(msg); + break; + } + } + + HANDLE dlfh = CreateFile(ffull.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, NULL); + if (dlfh == INVALID_HANDLE_VALUE) + { + msg.Format(_T("[file error]\r\n")); + m_Status.SetSel(-1, 0, FALSE); + m_Status.ReplaceSel(msg); + break; + } + + GetFileSizeEx(dlfh, (PLARGE_INTEGER)&usize); + CloseHandle(dlfh); + + std::replace(ffull.begin(), ffull.end(), _T('\\'), _T('/')); + + fname = PathFindFileName(ffull.c_str()); + fpath = ffull; + size_t sp = fpath.find_last_of(_T('/')); + if (sp < fpath.length()) + { + tstring::const_iterator pit = fpath.cbegin() + sp; + fpath.erase(pit, fpath.cend()); + } + else + fpath = _T("."); + + msg.Format(_T("\r\n")); + m_Status.SetSel(-1, 0, FALSE); + m_Status.ReplaceSel(msg); + } + case IExtractor::ER_OK: { + std::replace(ffull.begin(), ffull.end(), _T('\\'), _T('/')); + std::replace(fpath.begin(), fpath.end(), _T('\\'), _T('/')); + if (!theApp.m_Script[CSfxApp::EScriptType::PERFILE].empty()) { tstring pfscr; pfscr += _T("var BASEPATH = \""); pfscr += (LPCTSTR)(theApp.m_InstallPath); - pfscr += _T("\"; // the base install path\n\n"); + pfscr += _T("\"; /* the base install path */\n\n"); pfscr += _T("var FILENAME = \""); pfscr += fname.c_str(); - pfscr += _T("\"; // the name of the file that was just extracted\n"); + pfscr += _T("\"; /* the name of the file that was just extracted */\n"); pfscr += _T("var PATH = \""); pfscr += fpath.c_str(); - pfscr += _T("\"; // the output path of that file\n"); + pfscr += _T("\"; /* the output path of that file */\n"); pfscr += _T("var FILEPATH = \""); pfscr += ffull.c_str(); - pfscr += _T("\"; // the full filename (path + name)\n\n"); + pfscr += _T("\"; /* the full filename (path + name) */\n\n"); pfscr += theApp.m_Script[CSfxApp::EScriptType::PERFILE]; @@ -1161,7 +1239,7 @@ DWORD CProgressDlg::RunInstall() fscr += _T("var BASEPATH = \""); fscr += (LPCTSTR)(theApp.m_InstallPath); - fscr += _T("\"; // the base install path\n\n"); + fscr += _T("\"; /* the base install path */\n\n"); fscr += theApp.m_Script[CSfxApp::EScriptType::FINISH]; diff --git a/sfx/sfx/sfx.vcxproj b/sfx/sfx/sfx.vcxproj index bca2c19..635774e 100644 --- a/sfx/sfx/sfx.vcxproj +++ b/sfx/sfx/sfx.vcxproj @@ -64,19 +64,19 @@ true $(SolutionDir)bin\ $(ProjectDir)obj\$(Configuration)$(PlatformArchitecture)\ - $(ProjectName)$(PlatformArchitecture)$(ShortConfiguration) + $(ProjectName) false $(SolutionDir)bin\ $(ProjectDir)obj\$(Configuration)$(PlatformArchitecture)\ - $(ProjectName)$(PlatformArchitecture)$(ShortConfiguration) + $(ProjectName) false $(SolutionDir)bin\ $(ProjectDir)obj\$(Configuration)$(PlatformArchitecture)\ - $(ProjectName)$(PlatformArchitecture)$(ShortConfiguration) + $(ProjectName) diff --git a/sfx/sfxPackager/sfxPackager.rc b/sfx/sfxPackager/sfxPackager.rc index 76ad01e14e26b8914835c8c9ee7872f0f49c8fc8..c8b39e61d17b5836f87e45c068baf0e9beb2be1a 100644 GIT binary patch delta 85 zcmezKis{EIrVSd!oTdyq3iMO^`a&t}b5hkFJ9#8=gPySe{ySc2)3ROsa P^M#5Rtef}L9WVm`E;1Tu delta 89 zcmezIis{cQrVSd!oF)u942D2#G}*9N6N$IBSaNes@ewAVkRDKh9#Fx@Qr*pEWmc#{ U;+rp2ykKQEV=&pgz3!kH0FaFu*#H0l diff --git a/sfx/sfxPackager/sfxPackager.vcxproj b/sfx/sfxPackager/sfxPackager.vcxproj index 0066bd4..c773710 100644 --- a/sfx/sfxPackager/sfxPackager.vcxproj +++ b/sfx/sfxPackager/sfxPackager.vcxproj @@ -78,6 +78,13 @@ _DEBUG;%(PreprocessorDefinitions) $(IntDir);%(AdditionalIncludeDirectories) + + + + + + del $(SolutionDir)bin\sfx.exe + @@ -105,10 +112,15 @@ NDEBUG;%(PreprocessorDefinitions) $(IntDir);%(AdditionalIncludeDirectories) + + + + + + del $(SolutionDir)bin\sfx.exe + - - diff --git a/sfx/sfxPackager/sfxPackager.vcxproj.filters b/sfx/sfxPackager/sfxPackager.vcxproj.filters index 52d901c..f379e2f 100644 --- a/sfx/sfxPackager/sfxPackager.vcxproj.filters +++ b/sfx/sfxPackager/sfxPackager.vcxproj.filters @@ -94,8 +94,6 @@ Resource Files - - diff --git a/sfx/sfxPackager/sfxPackagerDoc.cpp b/sfx/sfxPackager/sfxPackagerDoc.cpp index 5ab9f22..062107c 100644 --- a/sfx/sfxPackager/sfxPackagerDoc.cpp +++ b/sfx/sfxPackager/sfxPackagerDoc.cpp @@ -227,6 +227,10 @@ class CSfxHandle : public IArchiveHandle { bool ret = false; + TCHAR docpath[MAX_PATH]; + _tcscpy_s(docpath, m_pDoc->GetPathName()); + PathRemoveFileSpec(docpath); + HRSRC hsfxres = FindResource(NULL, MAKEINTRESOURCE(IDR_EXE_SFX), _T("EXE")); if (hsfxres) { @@ -297,9 +301,6 @@ class CSfxHandle : public IArchiveHandle if (PathIsRelative(m_pDoc->m_IconFile)) { - TCHAR docpath[MAX_PATH]; - _tcscpy_s(docpath, MAX_PATH, m_pDoc->GetPathName()); - PathRemoveFileSpec(docpath); PathCombine(iconpath, docpath, m_pDoc->m_IconFile); } else @@ -363,14 +364,11 @@ class CSfxHandle : public IArchiveHandle if (PathIsRelative(m_pDoc->m_ImageFile)) { - TCHAR docpath[MAX_PATH]; - _tcscpy(docpath, m_pDoc->GetPathName()); - PathRemoveFileSpec(docpath); PathCombine(imgpath, docpath, m_pDoc->m_ImageFile); } else { - _tcscpy(imgpath, m_pDoc->m_ImageFile); + _tcscpy_s(imgpath, m_pDoc->m_ImageFile); } if (PathFileExists(imgpath)) @@ -415,18 +413,31 @@ class CSfxHandle : public IArchiveHandle { char *shtml; bool created_shtml = false; - if (PathFileExists(m_pDoc->m_Description)) + + TCHAR welcomepath[MAX_PATH]; + + if (PathIsRelative(m_pDoc->m_Description)) + { + PathCombine(welcomepath, docpath, m_pDoc->m_Description); + } + else + { + _tcscpy_s(welcomepath, m_pDoc->m_Description); + } + + if (PathFileExists(welcomepath)) { - HANDLE hhtmlfile = CreateFile(m_pDoc->m_Description, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + HANDLE hhtmlfile = CreateFile(welcomepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hhtmlfile) { DWORD fsz = GetFileSize(hhtmlfile, NULL); - shtml = (char *)malloc(fsz); + shtml = (char *)malloc(fsz + 1); if (shtml) { created_shtml = true; DWORD rb; ReadFile(hhtmlfile, shtml, fsz, &rb, NULL); + shtml[fsz] = 0; } CloseHandle(hhtmlfile); @@ -449,18 +460,31 @@ class CSfxHandle : public IArchiveHandle { char *shtml; bool created_shtml = false; - if (PathFileExists(m_pDoc->m_LicenseMessage)) + + TCHAR licensepath[MAX_PATH]; + + if (PathIsRelative(m_pDoc->m_LicenseMessage)) + { + PathCombine(licensepath, docpath, m_pDoc->m_LicenseMessage); + } + else + { + _tcscpy_s(licensepath, m_pDoc->m_LicenseMessage); + } + + if (PathFileExists(licensepath)) { - HANDLE hhtmlfile = CreateFile(m_pDoc->m_LicenseMessage, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + HANDLE hhtmlfile = CreateFile(licensepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hhtmlfile) { DWORD fsz = GetFileSize(hhtmlfile, NULL); - shtml = (char *)malloc(fsz); + shtml = (char *)malloc(fsz + 1); if (shtml) { created_shtml = true; DWORD rb; ReadFile(hhtmlfile, shtml, fsz, &rb, NULL); + shtml[fsz] = 0; } CloseHandle(hhtmlfile); @@ -836,19 +860,48 @@ bool CSfxPackagerDoc::AddFileToArchive(CSfxPackagerView *pview, IArchiver *parc, if (!srcspec) return false; + CString msg; + CMainFrame *pmf = (CMainFrame *)(AfxGetApp()->m_pMainWnd); + const TCHAR *pss = srcspec; + if (!_tcsnicmp(pss, _T("http"), 4)) + { + pss += 4; + if (!_tcsnicmp(pss, _T("s"), 1)) + pss++; + + if (!_tcsnicmp(pss, _T("://"), 3)) + { + TCHAR local_dstpath[MAX_PATH], *dp = local_dstpath; + _tcscpy_s(local_dstpath, dstpath); + if (_tcslen(local_dstpath) > 0) + PathAddBackslash(local_dstpath); + _tcscat(local_dstpath, dstfilename); + + while (dp && *(dp++)) { if (*dp == _T('/')) *dp = _T('\\'); } + + parc->AddFile(srcspec, local_dstpath, nullptr, nullptr, scriptsnippet); + + msg.Format(_T(" Adding download reference to \"%s\" from (%s) ...\r\n"), local_dstpath, srcspec); + pmf->GetOutputWnd().AppendMessage(COutputWnd::OT_BUILD, msg); + + return true; + } + } + + TCHAR docpath[MAX_PATH]; + _tcscpy_s(docpath, GetPathName()); + PathRemoveFileSpec(docpath); + TCHAR fullfilename[MAX_PATH]; if (PathIsRelative(srcspec)) { - TCHAR docpath[MAX_PATH]; - _tcscpy(docpath, GetPathName()); - PathRemoveFileSpec(docpath); PathCombine(fullfilename, docpath, srcspec); } else { - _tcscpy(fullfilename, srcspec); + _tcscpy_s(fullfilename, srcspec); } TCHAR *filespec = PathFindFileName(srcspec); @@ -877,8 +930,6 @@ bool CSfxPackagerDoc::AddFileToArchive(CSfxPackagerView *pview, IArchiver *parc, { ret = true; - CString msg; - do { wr = WaitForSingleObject(m_hCancelEvent, 0); @@ -901,7 +952,7 @@ bool CSfxPackagerDoc::AddFileToArchive(CSfxPackagerView *pview, IArchiver *parc, _tcscat(filename, filespec); TCHAR local_dstpath[MAX_PATH]; - _tcscpy(local_dstpath, dstpath); + _tcscpy_s(local_dstpath, dstpath); if (_tcslen(local_dstpath) > 0) PathAddBackslash(local_dstpath); _tcscat(local_dstpath, fd.cFileName); @@ -923,7 +974,7 @@ bool CSfxPackagerDoc::AddFileToArchive(CSfxPackagerView *pview, IArchiver *parc, dstpath++; TCHAR dst[MAX_PATH]; - _tcscpy(dst, dstpath ? dstpath : _T("")); + _tcscpy_s(dst, dstpath ? dstpath : _T("")); if (dst[0] != _T('\0')) PathAddBackslash(dst); @@ -932,7 +983,7 @@ bool CSfxPackagerDoc::AddFileToArchive(CSfxPackagerView *pview, IArchiver *parc, if (PathFileExists(fullfilename)) { - msg.Format(_T(" Adding \"%s\" from \"%s\"...\r\n"), dst, fullfilename); + msg.Format(_T(" Adding \"%s\" from \"%s\" ...\r\n"), dst, fullfilename); pmf->GetOutputWnd().AppendMessage(COutputWnd::OT_BUILD, msg); parc->AddFile(fullfilename, dst, &uncomp, &comp, scriptsnippet); @@ -986,13 +1037,14 @@ bool CSfxPackagerDoc::CreateSFXPackage(const TCHAR *filename, CSfxPackagerView * CMainFrame *pmf = (CMainFrame *)(AfxGetApp()->m_pMainWnd); + TCHAR docpath[MAX_PATH]; + _tcscpy_s(docpath, GetPathName()); + PathRemoveFileSpec(docpath); + TCHAR fullfilename[MAX_PATH]; if (PathIsRelative(filename)) { - TCHAR docpath[MAX_PATH]; - _tcscpy(docpath, GetPathName()); - PathRemoveFileSpec(docpath); PathCombine(fullfilename, docpath, filename); } else @@ -1051,7 +1103,7 @@ bool CSfxPackagerDoc::CreateSFXPackage(const TCHAR *filename, CSfxPackagerView * _tcscat(fullfilename, extcpy); } - msg.Format(_T("Beginning build of \"%s\" (%s)...\r\n"), m_Caption, fullfilename); + msg.Format(_T("Beginning build of \"%s\" (%s) ...\r\n"), m_Caption, fullfilename); pmf->GetOutputWnd().AppendMessage(COutputWnd::OT_BUILD, msg); TStringArray created_archives; @@ -1099,7 +1151,7 @@ bool CSfxPackagerDoc::CreateSFXPackage(const TCHAR *filename, CSfxPackagerView * { // TODO: add include / exclude lists TCHAR srcpath[MAX_PATH]; - _tcscpy(srcpath, it->second.srcpath.c_str()); + _tcscpy_s(srcpath, it->second.srcpath.c_str()); PathAddBackslash(srcpath); _tcscat(srcpath, it->second.name.c_str()); @@ -1134,10 +1186,15 @@ bool CSfxPackagerDoc::CreateSFXPackage(const TCHAR *filename, CSfxPackagerView * } else { - msg.Format(_T("Added %d files, spanning %d archive(s). Compression ratio: %1.02f :: 1.\r\n"), parc->GetFileCount(IArchiver::IM_WHOLE), spanct, (double)m_UncompressedSize.QuadPart / (double)sz_totalcomp); + msg.Format(_T("Done.\r\n\r\nAdded %d files, spanning %d archive(s).\r\n"), parc->GetFileCount(IArchiver::IM_WHOLE), spanct); pmf->GetOutputWnd().AppendMessage(COutputWnd::OT_BUILD, msg); - msg.Format(_T("Done. (completed in: %02d:%02d:%02d)\r\n"), hours, minutes, seconds); + double comp_pct = 0.0; + if (sz_totalcomp > 0) + { + comp_pct = 100.0 * std::max(0.0, (((double)m_UncompressedSize.QuadPart / (double)sz_totalcomp) - 1.0)); + } + msg.Format(_T("Compression: %1.02f%%\r\nCompleted in: %02d:%02d:%02d\r\n\r\n\r\n"), comp_pct, hours, minutes, seconds); } pmf->GetOutputWnd().AppendMessage(COutputWnd::OT_BUILD, msg); @@ -1163,12 +1220,13 @@ bool CSfxPackagerDoc::CopyFileToTemp(CSfxPackagerView *pview, const TCHAR *srcsp CMainFrame *pmf = (CMainFrame *)(AfxGetApp()->m_pMainWnd); + TCHAR docpath[MAX_PATH]; + _tcscpy_s(docpath, GetPathName()); + PathRemoveFileSpec(docpath); + TCHAR fullfilename[MAX_PATH]; if (PathIsRelative(srcspec)) { - TCHAR docpath[MAX_PATH]; - _tcscpy(docpath, GetPathName()); - PathRemoveFileSpec(docpath); PathCombine(fullfilename, docpath, srcspec); } else @@ -1224,7 +1282,7 @@ bool CSfxPackagerDoc::CopyFileToTemp(CSfxPackagerView *pview, const TCHAR *srcsp _tcscat(filename, filespec); TCHAR local_dstpath[MAX_PATH]; - _tcscpy(local_dstpath, dstpath); + _tcscpy_s(local_dstpath, dstpath); if (_tcslen(local_dstpath) > 0) PathAddBackslash(local_dstpath); _tcscat(local_dstpath, fd.cFileName); @@ -1238,7 +1296,7 @@ bool CSfxPackagerDoc::CopyFileToTemp(CSfxPackagerView *pview, const TCHAR *srcsp dstpath++; TCHAR dst[MAX_PATH]; - _tcscpy(dst, dstpath ? dstpath : _T("")); + _tcscpy_s(dst, dstpath ? dstpath : _T("")); CreateDirectories(dst); @@ -1293,13 +1351,13 @@ bool CSfxPackagerDoc::CreateTarGzipPackage(const TCHAR *filename, CSfxPackagerVi if (PathIsRelative(filename)) { TCHAR docpath[MAX_PATH]; - _tcscpy(docpath, GetPathName()); + _tcscpy_s(docpath, GetPathName()); PathRemoveFileSpec(docpath); PathCombine(fullfilename, docpath, filename); } else { - _tcscpy(fullfilename, filename); + _tcscpy_s(fullfilename, filename); } TCHAR filename_sans_ext[MAX_PATH];