From 36e1481e95302d388cc834405dd7b0e5eb27747b Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 22 May 2013 21:06:15 +0000 Subject: PluginUpdater: - separating flies from cutlets; - Update dialog stores the state of each file; - code cleaning git-svn-id: http://svn.miranda-ng.org/main/trunk@4806 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/PluginUpdater/PluginUpdater_10.vcxproj | 3 +- .../PluginUpdater/PluginUpdater_10.vcxproj.filters | 7 +- plugins/PluginUpdater/PluginUpdater_11.vcxproj | 3 +- .../PluginUpdater/PluginUpdater_11.vcxproj.filters | 7 +- plugins/PluginUpdater/src/Common.h | 44 +- plugins/PluginUpdater/src/DlgListNew.cpp | 503 +++++++++++++++++ plugins/PluginUpdater/src/DlgUpdate.cpp | 627 +++++++++++++++++++++ plugins/PluginUpdater/src/Notifications.cpp | 620 -------------------- plugins/PluginUpdater/src/Scanner.cpp | 571 ------------------- 9 files changed, 1183 insertions(+), 1202 deletions(-) create mode 100644 plugins/PluginUpdater/src/DlgListNew.cpp create mode 100644 plugins/PluginUpdater/src/DlgUpdate.cpp delete mode 100644 plugins/PluginUpdater/src/Scanner.cpp diff --git a/plugins/PluginUpdater/PluginUpdater_10.vcxproj b/plugins/PluginUpdater/PluginUpdater_10.vcxproj index cf8883ba64..a1ae2d7e2f 100644 --- a/plugins/PluginUpdater/PluginUpdater_10.vcxproj +++ b/plugins/PluginUpdater/PluginUpdater_10.vcxproj @@ -191,6 +191,8 @@ + + NotUsing @@ -215,7 +217,6 @@ Create - diff --git a/plugins/PluginUpdater/PluginUpdater_10.vcxproj.filters b/plugins/PluginUpdater/PluginUpdater_10.vcxproj.filters index ca82a85264..5c464dd0ae 100644 --- a/plugins/PluginUpdater/PluginUpdater_10.vcxproj.filters +++ b/plugins/PluginUpdater/PluginUpdater_10.vcxproj.filters @@ -91,10 +91,13 @@ Source Files\Minizip - + Source Files - + + Source Files + + Source Files diff --git a/plugins/PluginUpdater/PluginUpdater_11.vcxproj b/plugins/PluginUpdater/PluginUpdater_11.vcxproj index 88241dbec3..1a29bced25 100644 --- a/plugins/PluginUpdater/PluginUpdater_11.vcxproj +++ b/plugins/PluginUpdater/PluginUpdater_11.vcxproj @@ -194,6 +194,8 @@ + + NotUsing @@ -218,7 +220,6 @@ Create - diff --git a/plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters b/plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters index 4f6cd1a2b0..5c6b0de410 100644 --- a/plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters +++ b/plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters @@ -91,10 +91,13 @@ Source Files\Minizip - + Source Files - + + Source Files + + Source Files diff --git a/plugins/PluginUpdater/src/Common.h b/plugins/PluginUpdater/src/Common.h index 8c101c5e84..5011421482 100644 --- a/plugins/PluginUpdater/src/Common.h +++ b/plugins/PluginUpdater/src/Common.h @@ -72,9 +72,9 @@ struct FILEURL struct FILEINFO { - TCHAR tszOldName[MAX_PATH], tszNewName[MAX_PATH]; + TCHAR tszOldName[MAX_PATH], tszNewName[MAX_PATH]; FILEURL File; - BOOL bEnabled, bDeleteOnly; + BOOL bEnabled, bDeleteOnly; }; typedef OBJLIST FILELIST; @@ -147,17 +147,51 @@ INT_PTR MenuCommand(WPARAM wParam,LPARAM lParam); INT_PTR ShowListCommand(WPARAM wParam,LPARAM lParam); INT_PTR EmptyFolder(WPARAM wParam,LPARAM lParam); -INT_PTR CALLBACK DlgUpdate(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); -INT_PTR CALLBACK DlgList(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK DlgMsgPop(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +int ImageList_AddIconFromIconLib(HIMAGELIST hIml, const char *name); + bool unzip(const TCHAR *ptszZipFile, TCHAR *ptszDestPath, TCHAR *ptszBackPath); void strdel(TCHAR *parBuffer, int len); -////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +struct ServListEntry +{ + ServListEntry(const char* _name, const char* _hash, int _crc) : + m_name( mir_a2t(_name)), + m_bNeedFree(true), + m_crc(_crc) + { + strncpy(m_szHash, _hash, sizeof(m_szHash)); + } + + ServListEntry(TCHAR* _name) : + m_name(_name), + m_bNeedFree(false) + { + } + + ~ServListEntry() + { + if (m_bNeedFree) + mir_free(m_name); + } + + TCHAR *m_name; + char m_szHash[32+1]; + bool m_bNeedFree; + int m_crc; +}; + +typedef OBJLIST SERVLIST; + +/////////////////////////////////////////////////////////////////////////////// +int CalculateModuleHash(const TCHAR *tszFileName, char *dest); BOOL IsRunAsAdmin(); BOOL IsProcessElevated(); +bool PrepareEscalation(); int SafeCreateDirectory(const TCHAR *ptszDirName); int SafeCopyFile(const TCHAR *ptszSrc, const TCHAR *ptszDst); diff --git a/plugins/PluginUpdater/src/DlgListNew.cpp b/plugins/PluginUpdater/src/DlgListNew.cpp new file mode 100644 index 0000000000..3e19a30bd4 --- /dev/null +++ b/plugins/PluginUpdater/src/DlgListNew.cpp @@ -0,0 +1,503 @@ +/* +Copyright (C) 2010 Mataes + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "common.h" + +static void SelectAll(HWND hDlg, bool bEnable) +{ + OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); + + for (int i=0; i < todo.getCount(); i++) { + ListView_SetCheckState(hwndList, i, bEnable); + todo[i].bEnabled = bEnable; + } +} + +static void ApplyDownloads(void *param) +{ + HWND hDlg = (HWND)param; + + ////////////////////////////////////////////////////////////////////////////////////// + // if we need to escalate priviledges, launch a atub + + if ( !PrepareEscalation()) { + DestroyWindow(hDlg); + return; + } + + ////////////////////////////////////////////////////////////////////////////////////// + // ok, let's unpack all zips + + HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); + OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + TCHAR tszBuff[2048], tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH]; + + mir_sntprintf(tszFileBack, SIZEOF(tszFileBack), _T("%s\\Backups"), tszRoot); + SafeCreateDirectory(tszFileBack); + + mir_sntprintf(tszFileTemp, SIZEOF(tszFileTemp), _T("%s\\Temp"), tszRoot); + SafeCreateDirectory(tszFileTemp); + + for (int i=0; i < todo.getCount(); ++i) { + ListView_EnsureVisible(hwndList, i, FALSE); + if ( !todo[i].bEnabled) { + ListView_SetItemText(hwndList, i, 2, TranslateT("Skipped.")); + continue; + } + + // download update + ListView_SetItemText(hwndList, i, 2, TranslateT("Downloading...")); + + FILEURL *pFileUrl = &todo[i].File; + if ( !DownloadFile(pFileUrl->tszDownloadURL, pFileUrl->tszDiskPath, pFileUrl->CRCsum)){ + ListView_SetItemText(hwndList, i, 2, TranslateT("Failed!")); + } + else + ListView_SetItemText(hwndList, i, 2, TranslateT("Succeeded.")); + } + + if (todo.getCount() > 0) { + ShowPopup(0, LPGENT("Plugin Updater"), TranslateT("Download complete"), 2, 0); + + TCHAR *tszMirandaPath = Utils_ReplaceVarsT(_T("%miranda_path%")); + + for (int i = 0; i < todo.getCount(); i++) { + if ( !todo[i].bEnabled) + continue; + + TCHAR tszBackFile[MAX_PATH]; + FILEINFO& p = todo[i]; + if (p.bDeleteOnly) { // we need only to backup the old file + TCHAR *ptszRelPath = p.tszNewName + _tcslen(tszMirandaPath) + 1; + mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, ptszRelPath); + BackupFile(p.tszNewName, tszBackFile); + continue; + } + + // if file name differs, we also need to backup the old file here + // otherwise it would be replaced by unzip + if ( _tcsicmp(p.tszOldName, p.tszNewName)) { + TCHAR tszSrcPath[MAX_PATH]; + mir_sntprintf(tszSrcPath, SIZEOF(tszSrcPath), _T("%s\\%s"), tszMirandaPath, p.tszOldName); + mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, p.tszOldName); + BackupFile(tszSrcPath, tszBackFile); + } + + if ( unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack)) + SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update + } + } + + PopupDataText temp; + temp.Title = TranslateT("Plugin Updater"); + temp.Text = tszBuff; + lstrcpyn(tszBuff, TranslateT("Download complete. Do you want go to plugins option page?"), SIZEOF(tszBuff)); + int rc = MessageBox(NULL, temp.Text, temp.Title, MB_YESNO | MB_ICONQUESTION); + if (rc == IDYES) + CallFunctionAsync(OpenPluginOptions, 0); + + if (hPipe) + CloseHandle(hPipe); + CloseWindow(hDlg); + DestroyWindow(hDlg); + hwndDialog = NULL; + return; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static LRESULT CALLBACK PluginListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_LBUTTONDOWN) { + LVHITTESTINFO hi; + hi.pt.x = LOWORD(lParam); hi.pt.y = HIWORD(lParam); + ListView_SubItemHitTest(hwnd, &hi); + if (hi.iSubItem == 1) { + LVITEM lvi = {0}; + lvi.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_GROUPID; + lvi.stateMask = -1; + lvi.iItem = hi.iItem; + if (ListView_GetItem(hwnd, &lvi) && lvi.iGroupId == 1) { + TCHAR link[MAX_PATH]; + FILEINFO *info = (FILEINFO *)lvi.lParam; + + TCHAR tszFileName[MAX_PATH]; + _tcscpy(tszFileName, _tcsrchr(info->tszNewName, L'\\') + 1); + TCHAR *p = _tcschr(tszFileName, L'.'); *p = 0; + + mir_sntprintf(link, MAX_PATH, L"http://wiki.miranda-ng.org/index.php?title=Plugin:%s", tszFileName); + CallService(MS_UTILS_OPENURL, OUF_TCHAR, (LPARAM) link); + } + } + } + + return mir_callNextSubclass(hwnd, PluginListWndProc, msg, wParam, lParam); +} + +static int ListDlg_Resize(HWND, LPARAM, UTILRESIZECONTROL *urc) +{ + switch (urc->wId) { + case IDC_SELALL: + case IDC_SELNONE: + return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM; + + case IDOK: + return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; + } + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; +} + +INT_PTR CALLBACK DlgList(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); + + switch (message) { + case WM_INITDIALOG: + hwndDialog = hDlg; + TranslateDialogDefault( hDlg ); + mir_subclassWindow(hwndList, PluginListWndProc); + + SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)Skin_GetIcon("plg_list", 1)); + SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)Skin_GetIcon("plg_list")); + { + HIMAGELIST hIml = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 4, 0); + ImageList_AddIconFromIconLib(hIml, "info"); + ListView_SetImageList(hwndList, hIml, LVSIL_SMALL); + + OSVERSIONINFO osver = { sizeof(osver) }; + if (GetVersionEx(&osver) && osver.dwMajorVersion >= 6) { + wchar_t szPath[MAX_PATH]; + GetModuleFileName(NULL, szPath, SIZEOF(szPath)); + TCHAR *ext = _tcsrchr(szPath, '.'); + if (ext != NULL) + *ext = '\0'; + _tcscat(szPath, _T(".test")); + HANDLE hFile = CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + // Running Windows Vista or later (major version >= 6). + Button_SetElevationRequiredState(GetDlgItem(hDlg, IDOK), !IsProcessElevated()); + else { + CloseHandle(hFile); + DeleteFile(szPath); + } + } + RECT r; + GetClientRect(hwndList, &r); + + /// + LVCOLUMN lvc = {0}; + lvc.mask = LVCF_WIDTH | LVCF_TEXT; + //lvc.fmt = LVCFMT_LEFT; + + lvc.pszText = TranslateT("Component Name"); + lvc.cx = 220; // width of column in pixels + ListView_InsertColumn(hwndList, 0, &lvc); + + lvc.pszText = L""; + lvc.cx = 32 - GetSystemMetrics(SM_CXVSCROLL); // width of column in pixels + ListView_InsertColumn(hwndList, 1, &lvc); + + lvc.pszText = TranslateT("State"); + lvc.cx = 100 - GetSystemMetrics(SM_CXVSCROLL); // width of column in pixels + ListView_InsertColumn(hwndList, 2, &lvc); + + /// + LVGROUP lvg; + lvg.cbSize = sizeof(LVGROUP); + lvg.mask = LVGF_HEADER | LVGF_GROUPID; + + lvg.pszHeader = TranslateT("Plugins"); + lvg.iGroupId = 1; + ListView_InsertGroup(hwndList, 0, &lvg); + + lvg.pszHeader = TranslateT("Icons"); + lvg.iGroupId = 2; + ListView_InsertGroup(hwndList, 0, &lvg); + + lvg.pszHeader = TranslateT("Other"); + lvg.iGroupId = 3; + ListView_InsertGroup(hwndList, 0, &lvg); + + ListView_EnableGroupView(hwndList, TRUE); + + /// + SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES | LVS_EX_CHECKBOXES | LVS_EX_LABELTIP); + ListView_DeleteAllItems(hwndList); + + /// + OBJLIST &todo = *(OBJLIST *)lParam; + for (int i = 0; i < todo.getCount(); ++i) { + int groupId = 3; + LVITEM lvi = {0}; + lvi.mask = LVIF_PARAM | LVIF_GROUPID | LVIF_TEXT | LVIF_IMAGE; + + if (_tcschr(todo[i].tszOldName, L'\\') != NULL) + groupId = _tcsstr(todo[i].tszOldName, L"Plugins") != NULL ? 1 : 2; + + lvi.iItem = i; + lvi.lParam = (LPARAM)&todo[i]; + lvi.iGroupId = groupId; + lvi.iImage = -1; + lvi.pszText = todo[i].tszOldName; + int iRow = ListView_InsertItem(hwndList, &lvi); + + + if (iRow != -1) { + lvi.iItem = iRow; + if (groupId == 1) { + lvi.mask = LVIF_IMAGE; + lvi.iSubItem = 1; + lvi.iImage = 0; + ListView_SetItem(hwndList, &lvi); + } + } + todo[i].bEnabled = false; + } + HWND hwOk = GetDlgItem(hDlg, IDOK); + EnableWindow(hwOk, false); + } + + // do this after filling list - enables 'ITEMCHANGED' below + SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam); + Utils_RestoreWindowPosition(hDlg, 0, MODNAME, "ListWindow"); + return TRUE; + + case WM_NOTIFY: + if (((LPNMHDR) lParam)->hwndFrom == hwndList) { + switch (((LPNMHDR) lParam)->code) { + case LVN_ITEMCHANGED: + if (GetWindowLongPtr(hDlg, GWLP_USERDATA)) { + NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; + + LVITEM lvI = {0}; + lvI.iItem = nmlv->iItem; + lvI.iSubItem = 0; + lvI.mask = LVIF_PARAM; + ListView_GetItem(hwndList, &lvI); + + OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + if ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) { + todo[lvI.iItem].bEnabled = ListView_GetCheckState(hwndList, nmlv->iItem); + + bool enableOk = false; + for (int i=0; i < todo.getCount(); ++i) { + if (todo[i].bEnabled) { + enableOk = true; + break; + } + } + HWND hwOk = GetDlgItem(hDlg, IDOK); + EnableWindow(hwOk, enableOk ? TRUE : FALSE); + } + } + break; + } + } + break; + + case WM_COMMAND: + if (HIWORD( wParam ) == BN_CLICKED) { + switch(LOWORD(wParam)) { + case IDOK: + EnableWindow( GetDlgItem(hDlg, IDOK), FALSE); + EnableWindow( GetDlgItem(hDlg, IDC_SELALL), FALSE); + EnableWindow( GetDlgItem(hDlg, IDC_SELNONE), FALSE); + + mir_forkthread(ApplyDownloads, hDlg); + return TRUE; + + case IDC_SELALL: + SelectAll(hDlg, true); + break; + + case IDC_SELNONE: + SelectAll(hDlg, false); + break; + + case IDCANCEL: + DestroyWindow(hDlg); + return TRUE; + } + } + break; + + case WM_SIZE: // make the dlg resizeable + if ( !IsIconic(hDlg)) { + UTILRESIZEDIALOG urd = { sizeof(urd) }; + urd.hInstance = hInst; + urd.hwndDlg = hDlg; + urd.lpTemplate = MAKEINTRESOURCEA(IDD_LIST); + urd.pfnResizer = ListDlg_Resize; + CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd); + } + break; + + case WM_DESTROY: + Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ListWindow"); + Skin_ReleaseIcon((HICON)SendMessage(hDlg, WM_SETICON, ICON_BIG, 0)); + Skin_ReleaseIcon((HICON)SendMessage(hDlg, WM_SETICON, ICON_SMALL, 0)); + hwndDialog = NULL; + delete (OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + SetWindowLongPtr(hDlg, GWLP_USERDATA, 0); + break; + } + + return FALSE; +} + +static void __stdcall LaunchListDialog(void *param) +{ + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_LIST), GetDesktopWindow(), DlgList, (LPARAM)param); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// building file list in the separate thread + +static void GetList(void *) +{ + char szKey[64] = {0}; + DBVARIANT dbVar = {0}; + + TCHAR tszTempPath[MAX_PATH]; + DWORD dwLen = GetTempPath(SIZEOF(tszTempPath), tszTempPath); + if (tszTempPath[dwLen-1] == '\\') + tszTempPath[dwLen-1] = 0; + + // Load files info + if (db_get_ts(NULL, MODNAME, "UpdateURL", &dbVar)) { // URL is not set + db_set_ts(NULL, MODNAME, "UpdateURL", _T(DEFAULT_UPDATE_URL)); + db_get_ts(NULL, MODNAME, "UpdateURL", &dbVar); + } + + REPLACEVARSARRAY vars[2]; + vars[0].lptzKey = _T("platform"); + #ifdef WIN64 + vars[0].lptzValue = _T("64"); + #else + vars[0].lptzValue = _T("32"); + #endif + vars[1].lptzKey = vars[1].lptzValue = 0; + + REPLACEVARSDATA dat = { sizeof(REPLACEVARSDATA) }; + dat.dwFlags = RVF_TCHAR; + dat.variables = vars; + mir_ptr tszBaseUrl((TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)dbVar.ptszVal, (LPARAM)&dat)); + db_free(&dbVar); + + // Download version info + ShowPopup(NULL, TranslateT("Plugin Updater"), TranslateT("Downloading version info..."), 4, 0); + + FILEURL pFileUrl; + mir_sntprintf(pFileUrl.tszDownloadURL, SIZEOF(pFileUrl.tszDownloadURL), _T("%s/hashes.zip"), (TCHAR*)tszBaseUrl); + mir_sntprintf(pFileUrl.tszDiskPath, SIZEOF(pFileUrl.tszDiskPath), _T("%s\\hashes.zip"), tszTempPath); + if (!DownloadFile(pFileUrl.tszDownloadURL, pFileUrl.tszDiskPath, 0)) { + ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("An error occured while downloading the update."), 1, 0); + hListThread = NULL; + return; + } + + unzip(pFileUrl.tszDiskPath, tszTempPath, NULL); + DeleteFile(pFileUrl.tszDiskPath); + + TCHAR tszTmpIni[MAX_PATH] = {0}; + mir_sntprintf(tszTmpIni, SIZEOF(tszTmpIni), _T("%s\\hashes.txt"), tszTempPath); + FILE *fp = _tfopen(tszTmpIni, _T("r")); + if (!fp) { + hListThread = NULL; + return; + } + + FILELIST *UpdateFiles = new FILELIST(20); + char str[200]; + TCHAR *dirname = Utils_ReplaceVarsT(_T("%miranda_path%")); + while(fgets(str, SIZEOF(str), fp) != NULL) { + rtrim(str); + char *p = strchr(str, ' '); + if (p == NULL) + continue; + + *p++ = 0; + _strlwr(p); + + int dwCrc32; + char *p1 = strchr(p, ' '); + if (p1 == NULL) + dwCrc32 = 0; + else { + *p1++ = 0; + sscanf(p1, "%08x", &dwCrc32); + } + ServListEntry hash(str, p, dwCrc32); + + TCHAR tszPath[MAX_PATH]; + mir_sntprintf(tszPath, SIZEOF(tszPath), _T("%s\\%s"), dirname, hash.m_name); + + if (GetFileAttributes(tszPath) != DWORD(-1)) + continue; + + FILEINFO *FileInfo = new FILEINFO; + FileInfo->bDeleteOnly = FALSE; + _tcscpy(FileInfo->tszOldName, hash.m_name); // copy the relative old name + _tcscpy(FileInfo->tszNewName, hash.m_name); + + TCHAR tszFileName[MAX_PATH]; + _tcscpy(tszFileName, _tcsrchr(tszPath, L'\\') + 1); + TCHAR *tp = _tcschr(tszFileName, L'.'); *tp = 0; + + TCHAR tszRelFileName[MAX_PATH]; + _tcscpy(tszRelFileName, hash.m_name); + tp = _tcsrchr(tszRelFileName, L'.'); if (tp) *tp = 0; + tp = _tcschr(tszRelFileName, L'\\'); if (tp) tp++; else tp = tszRelFileName; + _tcslwr(tp); + + mir_sntprintf(FileInfo->File.tszDiskPath, SIZEOF(FileInfo->File.tszDiskPath), _T("%s\\Temp\\%s.zip"), tszRoot, tszFileName); + mir_sntprintf(FileInfo->File.tszDownloadURL, SIZEOF(FileInfo->File.tszDownloadURL), _T("%s/%s.zip"), tszBaseUrl, tszRelFileName); + for (tp = _tcschr(FileInfo->File.tszDownloadURL, '\\'); tp != 0; tp = _tcschr(tp, '\\')) + *tp++ = '/'; + FileInfo->File.CRCsum = hash.m_crc; + UpdateFiles->insert(FileInfo); + } + fclose(fp); + DeleteFile(tszTmpIni); + + mir_free(dirname); + + // Show dialog + if (UpdateFiles->getCount() == 0) { + if ( !opts.bSilent) + ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("List is empty."), 2, 0); + } + else CallFunctionAsync(LaunchListDialog, UpdateFiles); + + hListThread = NULL; +} + +void DoGetList(int iFlag) +{ + if (hListThread) + ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("List loading already started!"), 2, 0); + else if (hwndDialog) { + ShowWindow(hwndDialog, SW_SHOW); + SetForegroundWindow(hwndDialog); + SetFocus(hwndDialog); + } + else if (iFlag) + hListThread = mir_forkthread(GetList, 0); +} diff --git a/plugins/PluginUpdater/src/DlgUpdate.cpp b/plugins/PluginUpdater/src/DlgUpdate.cpp new file mode 100644 index 0000000000..93ff4fc86b --- /dev/null +++ b/plugins/PluginUpdater/src/DlgUpdate.cpp @@ -0,0 +1,627 @@ +/* +Copyright (C) 2010 Mataes + +This is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this file; see the file license.txt. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#include "common.h" + +static bool bShowDetails; + +static void SelectAll(HWND hDlg, bool bEnable) +{ + OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); + + for (int i=0; i < todo.getCount(); i++) { + ListView_SetCheckState(hwndList, i, bEnable); + db_set_b(NULL, MODNAME "Files", _T2A(todo[i].tszOldName), todo[i].bEnabled = bEnable); + } +} + +static void SetStringText(HWND hWnd, size_t i, TCHAR *ptszText) +{ + ListView_SetItemText(hWnd, i, 1, ptszText); +} + +static void ApplyUpdates(void *param) +{ + HWND hDlg = (HWND)param; + + ////////////////////////////////////////////////////////////////////////////////////// + // if we need to escalate priviledges, launch a atub + + if ( !PrepareEscalation()) { + DestroyWindow(hDlg); + return; + } + + ////////////////////////////////////////////////////////////////////////////////////// + // ok, let's unpack all zips + + HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); + OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + TCHAR tszBuff[2048], tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH]; + + mir_sntprintf(tszFileBack, SIZEOF(tszFileBack), _T("%s\\Backups"), tszRoot); + SafeCreateDirectory(tszFileBack); + + mir_sntprintf(tszFileTemp, SIZEOF(tszFileTemp), _T("%s\\Temp"), tszRoot); + SafeCreateDirectory(tszFileTemp); + + for (int i=0; i < todo.getCount(); ++i) { + ListView_EnsureVisible(hwndList, i, FALSE); + if ( !todo[i].bEnabled) { + SetStringText(hwndList, i, TranslateT("Skipped.")); + continue; + } + if (todo[i].bDeleteOnly) { + SetStringText(hwndList, i, TranslateT("Will be deleted!")); + continue; + } + + // download update + SetStringText(hwndList, i, TranslateT("Downloading...")); + + FILEURL *pFileUrl = &todo[i].File; + if ( !DownloadFile(pFileUrl->tszDownloadURL, pFileUrl->tszDiskPath, pFileUrl->CRCsum)) + SetStringText(hwndList, i, TranslateT("Failed!")); + else + SetStringText(hwndList, i, TranslateT("Succeeded.")); + } + + if (todo.getCount() == 0) { +LBL_Exit: + if (hPipe) + CloseHandle(hPipe); + DestroyWindow(hDlg); + return; + } + + PopupDataText temp; + temp.Title = TranslateT("Plugin Updater"); + temp.Text = tszBuff; + lstrcpyn(tszBuff, TranslateT("Download complete. Start updating? All your data will be saved and Miranda NG will be closed."), SIZEOF(tszBuff)); + int rc = MessageBox(NULL, temp.Text, temp.Title, MB_YESNO | MB_ICONQUESTION); + if (rc != IDYES) { + mir_sntprintf(tszBuff, SIZEOF(tszBuff), TranslateT("You have chosen not to install the plugin updates immediately.\nYou can install it manually from this location:\n\n%s"), tszFileTemp); + ShowPopup(0, LPGENT("Plugin Updater"), tszBuff, 2, 0); + goto LBL_Exit; + } + + TCHAR *tszMirandaPath = Utils_ReplaceVarsT(_T("%miranda_path%")); + + for (int i = 0; i < todo.getCount(); i++) { + if ( !todo[i].bEnabled) + continue; + + TCHAR tszBackFile[MAX_PATH]; + FILEINFO& p = todo[i]; + if (p.bDeleteOnly) { // we need only to backup the old file + TCHAR *ptszRelPath = p.tszNewName + _tcslen(tszMirandaPath) + 1; + mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, ptszRelPath); + BackupFile(p.tszNewName, tszBackFile); + continue; + } + + // if file name differs, we also need to backup the old file here + // otherwise it would be replaced by unzip + if ( _tcsicmp(p.tszOldName, p.tszNewName)) { + TCHAR tszSrcPath[MAX_PATH]; + mir_sntprintf(tszSrcPath, SIZEOF(tszSrcPath), _T("%s\\%s"), tszMirandaPath, p.tszOldName); + mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, p.tszOldName); + BackupFile(tszSrcPath, tszBackFile); + } + + if ( unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack)) + SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update + } + + db_set_b(NULL, MODNAME, "RestartCount", 2); + CallFunctionAsync(RestartMe, 0); + goto LBL_Exit; +} + +static void ResizeVert(HWND hDlg, int yy) +{ + RECT r = { 0, 0, 244, yy }; + MapDialogRect(hDlg, &r); + r.bottom += GetSystemMetrics(SM_CYSMCAPTION); + SetWindowPos(hDlg, 0, 0, 0, r.right, r.bottom, SWP_NOMOVE | SWP_NOZORDER); +} + +static INT_PTR CALLBACK DlgUpdate(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); + + switch (message) { + case WM_INITDIALOG: + hwndDialog = hDlg; + TranslateDialogDefault( hDlg ); + SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); + { + OSVERSIONINFO osver = { sizeof(osver) }; + if (GetVersionEx(&osver) && osver.dwMajorVersion >= 6) + { + wchar_t szPath[MAX_PATH]; + GetModuleFileName(NULL, szPath, SIZEOF(szPath)); + TCHAR *ext = _tcsrchr(szPath, '.'); + if (ext != NULL) + *ext = '\0'; + _tcscat(szPath, _T(".test")); + HANDLE hFile = CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + // Running Windows Vista or later (major version >= 6). + Button_SetElevationRequiredState(GetDlgItem(hDlg, IDOK), !IsProcessElevated()); + else + { + CloseHandle(hFile); + DeleteFile(szPath); + } + } + RECT r; + GetClientRect(hwndList, &r); + + LVCOLUMN lvc = {0}; + // Initialize the LVCOLUMN structure. + // The mask specifies that the format, width, text, and + // subitem members of the structure are valid. + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; + lvc.fmt = LVCFMT_LEFT; + + lvc.iSubItem = 0; + lvc.pszText = TranslateT("Component Name"); + lvc.cx = 220; // width of column in pixels + ListView_InsertColumn(hwndList, 0, &lvc); + + lvc.iSubItem = 1; + lvc.pszText = TranslateT("State"); + lvc.cx = 120 - GetSystemMetrics(SM_CXVSCROLL); // width of column in pixels + ListView_InsertColumn(hwndList, 1, &lvc); + + //enumerate plugins, fill in list + //bool one_enabled = false; + ListView_DeleteAllItems(hwndList); + + // Some code to create the list-view control. + // Initialize LVITEM members that are common to all items. + LVITEM lvI = {0}; + lvI.mask = LVIF_TEXT | LVIF_PARAM | LVIF_NORECOMPUTE;// | LVIF_IMAGE; + + OBJLIST &todo = *(OBJLIST *)lParam; + for (int i = 0; i < todo.getCount(); ++i) { + lvI.mask = LVIF_TEXT | LVIF_PARAM;// | LVIF_IMAGE; + lvI.iSubItem = 0; + lvI.lParam = (LPARAM)&todo[i]; + lvI.pszText = todo[i].tszOldName; + lvI.iItem = i; + ListView_InsertItem(hwndList, &lvI); + + // remember whether the user has decided not to update this component with this particular new version + todo[i].bEnabled = db_get_b(NULL, MODNAME "Files", _T2A(todo[i].tszOldName), true); + ListView_SetCheckState(hwndList, lvI.iItem, todo[i].bEnabled); + } + HWND hwOk = GetDlgItem(hDlg, IDOK); + EnableWindow(hwOk, true); + } + + bShowDetails = false; + ResizeVert(hDlg, 60); + + // do this after filling list - enables 'ITEMCHANGED' below + SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam); + Utils_RestoreWindowPositionNoSize(hDlg, 0, MODNAME, "ConfirmWindow"); + return TRUE; + + case WM_NOTIFY: + if (((LPNMHDR) lParam)->hwndFrom == hwndList) { + switch (((LPNMHDR) lParam)->code) { + case LVN_ITEMCHANGED: + if (GetWindowLongPtr(hDlg, GWLP_USERDATA)) { + NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; + + LVITEM lvI = {0}; + lvI.iItem = nmlv->iItem; + lvI.iSubItem = 0; + lvI.mask = LVIF_PARAM; + ListView_GetItem(hwndList, &lvI); + + OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + if ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) { + todo[lvI.iItem].bEnabled = ListView_GetCheckState(hwndList, nmlv->iItem); + db_set_b(NULL, MODNAME "Files", _T2A(todo[lvI.iItem].tszOldName), todo[lvI.iItem].bEnabled); + + bool enableOk = false; + for (int i=0; i < todo.getCount(); ++i) { + if (todo[i].bEnabled) { + enableOk = true; + break; + } + } + HWND hwOk = GetDlgItem(hDlg, IDOK); + EnableWindow(hwOk, enableOk ? TRUE : FALSE); + } + } + break; + } + } + break; + + case WM_COMMAND: + if (HIWORD( wParam ) == BN_CLICKED) { + switch(LOWORD(wParam)) { + case IDOK: + EnableWindow( GetDlgItem(hDlg, IDOK), FALSE); + EnableWindow( GetDlgItem(hDlg, IDC_SELALL), FALSE); + EnableWindow( GetDlgItem(hDlg, IDC_SELNONE), FALSE); + + mir_forkthread(ApplyUpdates, hDlg); + return TRUE; + + case IDC_DETAILS: + bShowDetails = !bShowDetails; + ResizeVert(hDlg, bShowDetails ? 242 : 60); + break; + + case IDC_SELALL: + SelectAll(hDlg, true); + break; + + case IDC_SELNONE: + SelectAll(hDlg, false); + break; + + case IDCANCEL: + Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ConfirmWindow"); + DestroyWindow(hDlg); + return TRUE; + } + } + break; + + case WM_DESTROY: + Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ConfirmWindow"); + hwndDialog = NULL; + delete (OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); + SetWindowLongPtr(hDlg, GWLP_USERDATA, 0); + break; + } + + return FALSE; +} + +static void __stdcall LaunchDialog(void *param) +{ + CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_UPDATE), GetDesktopWindow(), DlgUpdate, (LPARAM)param); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// building file list in the separate thread + +struct +{ + TCHAR *oldName, *newName; +} +static renameTable[] = +{ + { _T("svc_dbepp.dll"), _T("Plugins\\dbeditorpp.dll") }, + { _T("svc_crshdmp.dll"), _T("Plugins\\crashdumper.dll") }, + { _T("svc_vi.dll"), _T("Plugins\\versioninfo.dll") }, + { _T("crashrpt.dll"), _T("Plugins\\crashdumper.dll") }, + { _T("advsplashscreen.dll"), _T("Plugins\\splashscreen.dll") }, + { _T("import_sa.dll"), _T("Plugins\\import.dll") }, + { _T("newnr.dll"), _T("Plugins\\notesreminders.dll") }, + { _T("dbtool.exe"), _T("Plugins\\dbchecker.dll") }, + { _T("dbtool_sa.exe"), _T("Plugins\\dbchecker.dll") }, + { _T("bclist.dll"), _T("Plugins\\clist_blind.dll") }, + { _T("otr.dll"), _T("Plugins\\MirOTR.dll") }, + { _T("ttnotify.dll"), _T("Plugins\\TooltipNotify.dll") }, + { _T("NewStatusNotify.dll"), _T("Plugins\\NewXStatusNotify.dll") }, + + { _T("proto_newsaggr.dll"), _T("Icons\\proto_newsaggregator.dll") }, + { _T("clienticons_general.dll"), _T("Icons\\fp_icons.dll") }, + { _T("clienticons_miranda.dll"), _T("Icons\\fp_icons.dll") }, + { _T("fp_icq.dll"), _T("Icons\\fp_icons.dll") }, + { _T("fp_jabber.dll"), _T("Icons\\fp_icons.dll") }, + { _T("clienticons_aim.dll"), _T("") }, + { _T("clienticons_gadu.dll"), _T("") }, + { _T("clienticons_gg.dll"), _T("") }, + { _T("clienticons_icq.dll"), _T("") }, + { _T("clienticons_irc.dll"), _T("") }, + { _T("clienticons_jabber.dll"), _T("") }, + { _T("clienticons_mra.dll"), _T("") }, + { _T("clienticons_msn.dll"), _T("") }, + { _T("clienticons_multiproto.dll"), _T("") }, + { _T("clienticons_multiprotocols.dll"), _T("") }, + { _T("clienticons_others.dll"), _T("") }, + { _T("clienticons_overlays.dll"), _T("") }, + { _T("clienticons_packs.dll"), _T("") }, + { _T("clienticons_qq.dll"), _T("") }, + { _T("clienticons_rss.dll"), _T("") }, + { _T("clienticons_skype.dll"), _T("") }, + { _T("clienticons_tlen.dll"), _T("") }, + { _T("clienticons_voip.dll"), _T("") }, + { _T("clienticons_weather.dll"), _T("") }, + { _T("clienticons_yahoo.dll"), _T("") }, + { _T("fp_aim.dll"), _T("") }, + { _T("fp_c6_mra_skype.dll"), _T("") }, + { _T("fp_gg.dll"), _T("") }, + { _T("fp_irc.dll"), _T("") }, + { _T("fp_msn.dll"), _T("") }, + { _T("fp_packs.dll"), _T("") }, + { _T("fp_qq.dll"), _T("") }, + { _T("fp_rss.dll"), _T("") }, + { _T("fp_tlen.dll"), _T("") }, + { _T("fp_weather.dll"), _T("") }, + { _T("fp_yahoo.dll"), _T("") }, + + { _T("clist_classic.dll"), _T("") }, + { _T("chat.dll"), _T("") }, + { _T("gender.dll"), _T("") }, + { _T("srmm.dll"), _T("") }, + { _T("extraicons.dll"), _T("") }, +}; + +static bool CheckFileRename(const TCHAR *ptszOldName, TCHAR *pNewName) +{ + for (int i=0; i < SIZEOF(renameTable); i++) + if ( !_tcsicmp(ptszOldName, renameTable[i].oldName)) { + _tcscpy(pNewName, renameTable[i].newName); + return true; + } + + return false; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +static int CompareHashes(const ServListEntry *p1, const ServListEntry *p2) +{ + return _tcsicmp(p1->m_name, p2->m_name); +} + +static bool isValidExtension(const TCHAR *ptszFileName) +{ + const TCHAR *pExt = _tcsrchr(ptszFileName, '.'); + if (pExt == NULL) + return false; + + if ( !_tcsicmp(pExt, _T(".dll"))) return true; + if ( !_tcsicmp(pExt, _T(".exe"))) return true; + if ( !_tcsicmp(pExt, _T(".txt"))) return true; + return false; +} + +static void ScanFolder(const TCHAR *tszFolder, size_t cbBaseLen, int level, const TCHAR *tszBaseUrl, SERVLIST& hashes, OBJLIST *UpdateFiles) +{ + // skip updater's own folder + if ( !_tcsicmp(tszFolder, tszRoot)) + return; + + TCHAR tszBuf[MAX_PATH]; + mir_sntprintf(tszBuf, SIZEOF(tszBuf), _T("%s\\*"), tszFolder); + + WIN32_FIND_DATA ffd; + HANDLE hFind = FindFirstFile(tszBuf, &ffd); + if (hFind == INVALID_HANDLE_VALUE) + return; + + do { + if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if ( !_tcscmp(ffd.cFileName, _T(".")) || !_tcscmp(ffd.cFileName, _T(".."))) + continue; + + // we need to skip profile folder + TCHAR tszProfilePath[MAX_PATH]; + CallService(MS_DB_GETPROFILEPATHT, SIZEOF(tszProfilePath), (LPARAM)tszProfilePath); + + mir_sntprintf(tszBuf, SIZEOF(tszBuf), _T("%s\\%s"), tszFolder, ffd.cFileName); + if (0 != _tcsicmp(tszBuf, tszProfilePath)) + ScanFolder(tszBuf, cbBaseLen, level+1, tszBaseUrl, hashes, UpdateFiles); + continue; + } + + if ( !isValidExtension(ffd.cFileName)) + continue; + + // calculate the current file's relative name and store it into tszNewName + TCHAR tszNewName[MAX_PATH]; + if ( !CheckFileRename(ffd.cFileName, tszNewName)) { + if (level == 0) + _tcscpy(tszNewName, ffd.cFileName); + else + mir_sntprintf(tszNewName, SIZEOF(tszNewName), _T("%s\\%s"), tszFolder+cbBaseLen, ffd.cFileName); + } + + bool bHasNewVersion = false; + TCHAR *ptszUrl; + int MyCRC = 0; + mir_sntprintf(tszBuf, SIZEOF(tszBuf), _T("%s\\%s"), tszFolder, ffd.cFileName); + + // this file is not marked for deletion + if (tszNewName[0]) { + ServListEntry tmp(tszNewName); + ServListEntry *item = hashes.find(&tmp); + if (item == NULL) { + TCHAR *p = _tcsrchr(tszNewName, '.'); + if (p[-1] != 'w' && p[-1] != 'W') + continue; + + int iPos = int(p - tszNewName)-1; + strdel(p-1, 1); + if ((item = hashes.find(&tmp)) == NULL) + continue; + + strdel(tszNewName+iPos, 1); + } + + ptszUrl = item->m_name; + + char szMyHash[33]; + CalculateModuleHash(tszBuf, szMyHash); + + MyCRC = item->m_crc; + bHasNewVersion = strcmp(szMyHash, item->m_szHash) != 0; + } + else { // file was marked for deletion, add it to the list anyway + bHasNewVersion = true; + ptszUrl = _T(""); + } + + // Compare versions + if (bHasNewVersion) { // Yeah, we've got new version. + FILEINFO *FileInfo = new FILEINFO; + _tcscpy(FileInfo->tszOldName, tszBuf+cbBaseLen); // copy the relative old name + if (tszNewName[0] == 0) { + FileInfo->bDeleteOnly = TRUE; + _tcscpy(FileInfo->tszNewName, tszBuf); // save the full old name for deletion + } + else { + FileInfo->bDeleteOnly = FALSE; + _tcsncpy(FileInfo->tszNewName, ptszUrl, SIZEOF(FileInfo->tszNewName)); + } + + _tcscpy(tszBuf, ptszUrl); + TCHAR *p = _tcsrchr(tszBuf, '.'); + if (p) *p = 0; + p = _tcsrchr(tszBuf, '\\'); + p = (p) ? p+1 : tszBuf; + _tcslwr(p); + + mir_sntprintf(FileInfo->File.tszDiskPath, SIZEOF(FileInfo->File.tszDiskPath), _T("%s\\Temp\\%s.zip"), tszRoot, p); + mir_sntprintf(FileInfo->File.tszDownloadURL, SIZEOF(FileInfo->File.tszDownloadURL), _T("%s/%s.zip"), tszBaseUrl, tszBuf); + for (p = _tcschr(FileInfo->File.tszDownloadURL, '\\'); p != 0; p = _tcschr(p, '\\')) + *p++ = '/'; + + FileInfo->File.CRCsum = MyCRC; + UpdateFiles->insert(FileInfo); + } // end compare versions + } + while (FindNextFile(hFind, &ffd) != 0); + + FindClose(hFind); +} + +static void CheckUpdates(void *) +{ + char szKey[64] = {0}; + DBVARIANT dbVar = {0}; + + TCHAR tszTempPath[MAX_PATH]; + DWORD dwLen = GetTempPath(SIZEOF(tszTempPath), tszTempPath); + if (tszTempPath[dwLen-1] == '\\') + tszTempPath[dwLen-1] = 0; + + // Load files info + if (db_get_ts(NULL, MODNAME, "UpdateURL", &dbVar)) { // URL is not set + db_set_ts(NULL, MODNAME, "UpdateURL", _T(DEFAULT_UPDATE_URL)); + db_get_ts(NULL, MODNAME, "UpdateURL", &dbVar); + } + + REPLACEVARSARRAY vars[2]; + vars[0].lptzKey = _T("platform"); + #ifdef WIN64 + vars[0].lptzValue = _T("64"); + #else + vars[0].lptzValue = _T("32"); + #endif + vars[1].lptzKey = vars[1].lptzValue = 0; + + REPLACEVARSDATA dat = { sizeof(REPLACEVARSDATA) }; + dat.dwFlags = RVF_TCHAR; + dat.variables = vars; + ptrT tszBaseUrl((TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)dbVar.ptszVal, (LPARAM)&dat)); + db_free(&dbVar); + + // Download version info + ShowPopup(NULL, TranslateT("Plugin Updater"), TranslateT("Downloading version info..."), 4, 0); + + FILEURL pFileUrl; + mir_sntprintf(pFileUrl.tszDownloadURL, SIZEOF(pFileUrl.tszDownloadURL), _T("%s/hashes.zip"), (TCHAR*)tszBaseUrl); + mir_sntprintf(pFileUrl.tszDiskPath, SIZEOF(pFileUrl.tszDiskPath), _T("%s\\hashes.zip"), tszTempPath); + if (!DownloadFile(pFileUrl.tszDownloadURL, pFileUrl.tszDiskPath, 0)) { + ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("An error occured while downloading the update."), 1, 0); + hCheckThread = NULL; + return; + } + + unzip(pFileUrl.tszDiskPath, tszTempPath, NULL); + DeleteFile(pFileUrl.tszDiskPath); + + TCHAR tszTmpIni[MAX_PATH] = {0}; + mir_sntprintf(tszTmpIni, SIZEOF(tszTmpIni), _T("%s\\hashes.txt"), tszTempPath); + FILE *fp = _tfopen(tszTmpIni, _T("r")); + if (!fp) { + hCheckThread = NULL; + return; + } + + SERVLIST hashes(50, CompareHashes); + char str[200]; + while(fgets(str, SIZEOF(str), fp) != NULL) { + rtrim(str); + char *p = strchr(str, ' '); + if (p == NULL) + continue; + + *p++ = 0; + if ( !opts.bUpdateIcons && !_strnicmp(str, "icons\\", 6)) + continue; + + _strlwr(p); + + int dwCrc32; + char *p1 = strchr(p, ' '); + if (p1 == NULL) + dwCrc32 = 0; + else { + *p1++ = 0; + sscanf(p1, "%08x", &dwCrc32); + } + hashes.insert(new ServListEntry(str, p, dwCrc32)); + } + fclose(fp); + DeleteFile(tszTmpIni); + + FILELIST *UpdateFiles = new FILELIST(20); + TCHAR *dirname = Utils_ReplaceVarsT(_T("%miranda_path%")); + ScanFolder(dirname, lstrlen(dirname)+1, 0, tszBaseUrl, hashes, UpdateFiles); + mir_free(dirname); + + // Show dialog + if (UpdateFiles->getCount() == 0) { + if ( !opts.bSilent) + ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("No updates found."), 2, 0); + } + else CallFunctionAsync(LaunchDialog, UpdateFiles); + + hCheckThread = NULL; +} + +void DoCheck(int iFlag) +{ + if (hCheckThread) + ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("Update checking already started!"), 2, 0); + else if (hwndDialog) { + ShowWindow(hwndDialog, SW_SHOW); + SetForegroundWindow(hwndDialog); + SetFocus(hwndDialog); + } + else if (iFlag) { + hCheckThread = mir_forkthread(CheckUpdates, 0); + db_set_dw(NULL, MODNAME, "LastUpdate", time(NULL)); + } +} diff --git a/plugins/PluginUpdater/src/Notifications.cpp b/plugins/PluginUpdater/src/Notifications.cpp index 762cfb0170..b054f76a04 100644 --- a/plugins/PluginUpdater/src/Notifications.cpp +++ b/plugins/PluginUpdater/src/Notifications.cpp @@ -21,7 +21,6 @@ Boston, MA 02111-1307, USA. HANDLE hPipe = NULL; HWND hwndDialog = NULL; -static bool bShowDetails; void PopupAction(HWND hWnd, BYTE action) { @@ -263,219 +262,6 @@ bool PrepareEscalation() return false; } -void SelectAll(HWND hDlg, bool bEnable) -{ - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - - for (int i=0; i < todo.getCount(); i++) { - ListView_SetCheckState(hwndList, i, bEnable); - todo[i].bEnabled = bEnable; - } -} - -static void SetStringText(HWND hWnd, size_t i, TCHAR *ptszText) -{ - ListView_SetItemText(hWnd, i, 1, ptszText); -} - -static void ApplyUpdates(void *param) -{ - HWND hDlg = (HWND)param; - - ////////////////////////////////////////////////////////////////////////////////////// - // if we need to escalate priviledges, launch a atub - - if ( !PrepareEscalation()) { - DestroyWindow(hDlg); - return; - } - - ////////////////////////////////////////////////////////////////////////////////////// - // ok, let's unpack all zips - - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - TCHAR tszBuff[2048], tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH]; - - mir_sntprintf(tszFileBack, SIZEOF(tszFileBack), _T("%s\\Backups"), tszRoot); - SafeCreateDirectory(tszFileBack); - - mir_sntprintf(tszFileTemp, SIZEOF(tszFileTemp), _T("%s\\Temp"), tszRoot); - SafeCreateDirectory(tszFileTemp); - - for (int i=0; i < todo.getCount(); ++i) { - ListView_EnsureVisible(hwndList, i, FALSE); - if ( !todo[i].bEnabled) { - SetStringText(hwndList, i, TranslateT("Skipped.")); - continue; - } - if (todo[i].bDeleteOnly) { - SetStringText(hwndList, i, TranslateT("Will be deleted!")); - continue; - } - - // download update - SetStringText(hwndList, i, TranslateT("Downloading...")); - - FILEURL *pFileUrl = &todo[i].File; - if ( !DownloadFile(pFileUrl->tszDownloadURL, pFileUrl->tszDiskPath, pFileUrl->CRCsum)) - SetStringText(hwndList, i, TranslateT("Failed!")); - else - SetStringText(hwndList, i, TranslateT("Succeeded.")); - } - - if (todo.getCount() == 0) { -LBL_Exit: - if (hPipe) - CloseHandle(hPipe); - DestroyWindow(hDlg); - return; - } - - PopupDataText temp; - temp.Title = TranslateT("Plugin Updater"); - temp.Text = tszBuff; - lstrcpyn(tszBuff, TranslateT("Download complete. Start updating? All your data will be saved and Miranda NG will be closed."), SIZEOF(tszBuff)); - int rc = MessageBox(NULL, temp.Text, temp.Title, MB_YESNO | MB_ICONQUESTION); - if (rc != IDYES) { - mir_sntprintf(tszBuff, SIZEOF(tszBuff), TranslateT("You have chosen not to install the plugin updates immediately.\nYou can install it manually from this location:\n\n%s"), tszFileTemp); - ShowPopup(0, LPGENT("Plugin Updater"), tszBuff, 2, 0); - goto LBL_Exit; - } - - TCHAR *tszMirandaPath = Utils_ReplaceVarsT(_T("%miranda_path%")); - - for (int i = 0; i < todo.getCount(); i++) { - if ( !todo[i].bEnabled) - continue; - - TCHAR tszBackFile[MAX_PATH]; - FILEINFO& p = todo[i]; - if (p.bDeleteOnly) { // we need only to backup the old file - TCHAR *ptszRelPath = p.tszNewName + _tcslen(tszMirandaPath) + 1; - mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, ptszRelPath); - BackupFile(p.tszNewName, tszBackFile); - continue; - } - - // if file name differs, we also need to backup the old file here - // otherwise it would be replaced by unzip - if ( _tcsicmp(p.tszOldName, p.tszNewName)) { - TCHAR tszSrcPath[MAX_PATH]; - mir_sntprintf(tszSrcPath, SIZEOF(tszSrcPath), _T("%s\\%s"), tszMirandaPath, p.tszOldName); - mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, p.tszOldName); - BackupFile(tszSrcPath, tszBackFile); - } - - if ( unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack)) - SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update - } - - db_set_b(NULL, MODNAME, "RestartCount", 2); - CallFunctionAsync(RestartMe, 0); - goto LBL_Exit; -} - -static void ApplyDownloads(void *param) -{ - HWND hDlg = (HWND)param; - - ////////////////////////////////////////////////////////////////////////////////////// - // if we need to escalate priviledges, launch a atub - - if ( !PrepareEscalation()) { - DestroyWindow(hDlg); - return; - } - - ////////////////////////////////////////////////////////////////////////////////////// - // ok, let's unpack all zips - - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - TCHAR tszBuff[2048], tszFileTemp[MAX_PATH], tszFileBack[MAX_PATH]; - - mir_sntprintf(tszFileBack, SIZEOF(tszFileBack), _T("%s\\Backups"), tszRoot); - SafeCreateDirectory(tszFileBack); - - mir_sntprintf(tszFileTemp, SIZEOF(tszFileTemp), _T("%s\\Temp"), tszRoot); - SafeCreateDirectory(tszFileTemp); - - for (int i=0; i < todo.getCount(); ++i) { - ListView_EnsureVisible(hwndList, i, FALSE); - if ( !todo[i].bEnabled) { - ListView_SetItemText(hwndList, i, 2, TranslateT("Skipped.")); - continue; - } - - // download update - ListView_SetItemText(hwndList, i, 2, TranslateT("Downloading...")); - - FILEURL *pFileUrl = &todo[i].File; - if ( !DownloadFile(pFileUrl->tszDownloadURL, pFileUrl->tszDiskPath, pFileUrl->CRCsum)){ - ListView_SetItemText(hwndList, i, 2, TranslateT("Failed!")); - } - else - ListView_SetItemText(hwndList, i, 2, TranslateT("Succeeded.")); - } - - if (todo.getCount() > 0) { - ShowPopup(0, LPGENT("Plugin Updater"), TranslateT("Download complete"), 2, 0); - - TCHAR *tszMirandaPath = Utils_ReplaceVarsT(_T("%miranda_path%")); - - for (int i = 0; i < todo.getCount(); i++) { - if ( !todo[i].bEnabled) - continue; - - TCHAR tszBackFile[MAX_PATH]; - FILEINFO& p = todo[i]; - if (p.bDeleteOnly) { // we need only to backup the old file - TCHAR *ptszRelPath = p.tszNewName + _tcslen(tszMirandaPath) + 1; - mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, ptszRelPath); - BackupFile(p.tszNewName, tszBackFile); - continue; - } - - // if file name differs, we also need to backup the old file here - // otherwise it would be replaced by unzip - if ( _tcsicmp(p.tszOldName, p.tszNewName)) { - TCHAR tszSrcPath[MAX_PATH]; - mir_sntprintf(tszSrcPath, SIZEOF(tszSrcPath), _T("%s\\%s"), tszMirandaPath, p.tszOldName); - mir_sntprintf(tszBackFile, SIZEOF(tszBackFile), _T("%s\\%s"), tszFileBack, p.tszOldName); - BackupFile(tszSrcPath, tszBackFile); - } - - if ( unzip(p.File.tszDiskPath, tszMirandaPath, tszFileBack)) - SafeDeleteFile(p.File.tszDiskPath); // remove .zip after successful update - } - } - - PopupDataText temp; - temp.Title = TranslateT("Plugin Updater"); - temp.Text = tszBuff; - lstrcpyn(tszBuff, TranslateT("Download complete. Do you want go to plugins option page?"), SIZEOF(tszBuff)); - int rc = MessageBox(NULL, temp.Text, temp.Title, MB_YESNO | MB_ICONQUESTION); - if (rc == IDYES) - CallFunctionAsync(OpenPluginOptions, 0); - - if (hPipe) - CloseHandle(hPipe); - CloseWindow(hDlg); - DestroyWindow(hDlg); - hwndDialog = NULL; - return; -} - -static void ResizeVert(HWND hDlg, int yy) -{ - RECT r = { 0, 0, 244, yy }; - MapDialogRect(hDlg, &r); - r.bottom += GetSystemMetrics(SM_CYSMCAPTION); - SetWindowPos(hDlg, 0, 0, 0, r.right, r.bottom, SWP_NOMOVE | SWP_NOZORDER); -} - int ImageList_AddIconFromIconLib(HIMAGELIST hIml, const char *name) { HICON icon = Skin_GetIconByHandle(Skin_GetIconHandle(name)); @@ -484,412 +270,6 @@ int ImageList_AddIconFromIconLib(HIMAGELIST hIml, const char *name) return res; } -INT_PTR CALLBACK DlgUpdate(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - - switch (message) { - case WM_INITDIALOG: - hwndDialog = hDlg; - TranslateDialogDefault( hDlg ); - SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); - { - OSVERSIONINFO osver = { sizeof(osver) }; - if (GetVersionEx(&osver) && osver.dwMajorVersion >= 6) - { - wchar_t szPath[MAX_PATH]; - GetModuleFileName(NULL, szPath, SIZEOF(szPath)); - TCHAR *ext = _tcsrchr(szPath, '.'); - if (ext != NULL) - *ext = '\0'; - _tcscat(szPath, _T(".test")); - HANDLE hFile = CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - // Running Windows Vista or later (major version >= 6). - Button_SetElevationRequiredState(GetDlgItem(hDlg, IDOK), !IsProcessElevated()); - else - { - CloseHandle(hFile); - DeleteFile(szPath); - } - } - RECT r; - GetClientRect(hwndList, &r); - - LVCOLUMN lvc = {0}; - // Initialize the LVCOLUMN structure. - // The mask specifies that the format, width, text, and - // subitem members of the structure are valid. - lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; - lvc.fmt = LVCFMT_LEFT; - - lvc.iSubItem = 0; - lvc.pszText = TranslateT("Component Name"); - lvc.cx = 220; // width of column in pixels - ListView_InsertColumn(hwndList, 0, &lvc); - - lvc.iSubItem = 1; - lvc.pszText = TranslateT("State"); - lvc.cx = 120 - GetSystemMetrics(SM_CXVSCROLL); // width of column in pixels - ListView_InsertColumn(hwndList, 1, &lvc); - - //enumerate plugins, fill in list - //bool one_enabled = false; - ListView_DeleteAllItems(hwndList); - - // Some code to create the list-view control. - // Initialize LVITEM members that are common to all - // items. - LVITEM lvI = {0}; - lvI.mask = LVIF_TEXT | LVIF_PARAM | LVIF_NORECOMPUTE;// | LVIF_IMAGE; - - OBJLIST &todo = *(OBJLIST *)lParam; - for (int i = 0; i < todo.getCount(); ++i) { - lvI.mask = LVIF_TEXT | LVIF_PARAM;// | LVIF_IMAGE; - lvI.iSubItem = 0; - lvI.lParam = (LPARAM)&todo[i]; - lvI.pszText = todo[i].tszOldName; - lvI.iItem = i; - ListView_InsertItem(hwndList, &lvI); - - // remember whether the user has decided not to update this component with this particular new version - ListView_SetCheckState(hwndList, lvI.iItem, true); - todo[i].bEnabled = true; - } - HWND hwOk = GetDlgItem(hDlg, IDOK); - EnableWindow(hwOk, true); - } - - bShowDetails = false; - ResizeVert(hDlg, 60); - - // do this after filling list - enables 'ITEMCHANGED' below - SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam); - Utils_RestoreWindowPositionNoSize(hDlg, 0, MODNAME, "ConfirmWindow"); - return TRUE; - - case WM_NOTIFY: - if (((LPNMHDR) lParam)->hwndFrom == hwndList) { - switch (((LPNMHDR) lParam)->code) { - case LVN_ITEMCHANGED: - if (GetWindowLongPtr(hDlg, GWLP_USERDATA)) { - NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; - - LVITEM lvI = {0}; - lvI.iItem = nmlv->iItem; - lvI.iSubItem = 0; - lvI.mask = LVIF_PARAM; - ListView_GetItem(hwndList, &lvI); - - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - if ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) { - todo[lvI.iItem].bEnabled = ListView_GetCheckState(hwndList, nmlv->iItem); - - bool enableOk = false; - for (int i=0; i < todo.getCount(); ++i) { - if (todo[i].bEnabled) { - enableOk = true; - break; - } - } - HWND hwOk = GetDlgItem(hDlg, IDOK); - EnableWindow(hwOk, enableOk ? TRUE : FALSE); - } - } - break; - } - } - break; - - case WM_COMMAND: - if (HIWORD( wParam ) == BN_CLICKED) { - switch(LOWORD(wParam)) { - case IDOK: - EnableWindow( GetDlgItem(hDlg, IDOK), FALSE); - EnableWindow( GetDlgItem(hDlg, IDC_SELALL), FALSE); - EnableWindow( GetDlgItem(hDlg, IDC_SELNONE), FALSE); - - mir_forkthread(ApplyUpdates, hDlg); - return TRUE; - - case IDC_DETAILS: - bShowDetails = !bShowDetails; - ResizeVert(hDlg, bShowDetails ? 242 : 60); - break; - - case IDC_SELALL: - SelectAll(hDlg, true); - break; - - case IDC_SELNONE: - SelectAll(hDlg, false); - break; - - case IDCANCEL: - Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ConfirmWindow"); - DestroyWindow(hDlg); - return TRUE; - } - } - break; - - case WM_DESTROY: - Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ConfirmWindow"); - hwndDialog = NULL; - delete (OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - SetWindowLongPtr(hDlg, GWLP_USERDATA, 0); - break; - } - - return FALSE; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -static LRESULT CALLBACK PluginListWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (msg == WM_LBUTTONDOWN) { - LVHITTESTINFO hi; - hi.pt.x = LOWORD(lParam); hi.pt.y = HIWORD(lParam); - ListView_SubItemHitTest(hwnd, &hi); - if (hi.iSubItem == 1) { - LVITEM lvi = {0}; - lvi.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_GROUPID; - lvi.stateMask = -1; - lvi.iItem = hi.iItem; - if (ListView_GetItem(hwnd, &lvi) && lvi.iGroupId == 1) { - TCHAR link[MAX_PATH]; - FILEINFO *info = (FILEINFO *)lvi.lParam; - - TCHAR tszFileName[MAX_PATH]; - _tcscpy(tszFileName, _tcsrchr(info->tszNewName, L'\\') + 1); - TCHAR *p = _tcschr(tszFileName, L'.'); *p = 0; - - mir_sntprintf(link, MAX_PATH, L"http://wiki.miranda-ng.org/index.php?title=Plugin:%s", tszFileName); - CallService(MS_UTILS_OPENURL, OUF_TCHAR, (LPARAM) link); - } - } - } - - return mir_callNextSubclass(hwnd, PluginListWndProc, msg, wParam, lParam); -} - -static int ListDlg_Resize(HWND, LPARAM, UTILRESIZECONTROL *urc) -{ - switch (urc->wId) { - case IDC_SELALL: - case IDC_SELNONE: - return RD_ANCHORX_LEFT | RD_ANCHORY_BOTTOM; - - case IDOK: - return RD_ANCHORX_RIGHT | RD_ANCHORY_BOTTOM; - } - return RD_ANCHORX_LEFT | RD_ANCHORY_TOP | RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; -} - -INT_PTR CALLBACK DlgList(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES); - - switch (message) { - case WM_INITDIALOG: - hwndDialog = hDlg; - TranslateDialogDefault( hDlg ); - mir_subclassWindow(hwndList, PluginListWndProc); - - SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)Skin_GetIcon("plg_list", 1)); - SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)Skin_GetIcon("plg_list")); - { - HIMAGELIST hIml = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 4, 0); - ImageList_AddIconFromIconLib(hIml, "info"); - ListView_SetImageList(hwndList, hIml, LVSIL_SMALL); - - OSVERSIONINFO osver = { sizeof(osver) }; - if (GetVersionEx(&osver) && osver.dwMajorVersion >= 6) { - wchar_t szPath[MAX_PATH]; - GetModuleFileName(NULL, szPath, SIZEOF(szPath)); - TCHAR *ext = _tcsrchr(szPath, '.'); - if (ext != NULL) - *ext = '\0'; - _tcscat(szPath, _T(".test")); - HANDLE hFile = CreateFile(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - // Running Windows Vista or later (major version >= 6). - Button_SetElevationRequiredState(GetDlgItem(hDlg, IDOK), !IsProcessElevated()); - else { - CloseHandle(hFile); - DeleteFile(szPath); - } - } - RECT r; - GetClientRect(hwndList, &r); - - /// - LVCOLUMN lvc = {0}; - lvc.mask = LVCF_WIDTH | LVCF_TEXT; - //lvc.fmt = LVCFMT_LEFT; - - lvc.pszText = TranslateT("Component Name"); - lvc.cx = 220; // width of column in pixels - ListView_InsertColumn(hwndList, 0, &lvc); - - lvc.pszText = L""; - lvc.cx = 32 - GetSystemMetrics(SM_CXVSCROLL); // width of column in pixels - ListView_InsertColumn(hwndList, 1, &lvc); - - lvc.pszText = TranslateT("State"); - lvc.cx = 100 - GetSystemMetrics(SM_CXVSCROLL); // width of column in pixels - ListView_InsertColumn(hwndList, 2, &lvc); - - /// - LVGROUP lvg; - lvg.cbSize = sizeof(LVGROUP); - lvg.mask = LVGF_HEADER | LVGF_GROUPID; - - lvg.pszHeader = TranslateT("Plugins"); - lvg.iGroupId = 1; - ListView_InsertGroup(hwndList, 0, &lvg); - - lvg.pszHeader = TranslateT("Icons"); - lvg.iGroupId = 2; - ListView_InsertGroup(hwndList, 0, &lvg); - - lvg.pszHeader = TranslateT("Other"); - lvg.iGroupId = 3; - ListView_InsertGroup(hwndList, 0, &lvg); - - ListView_EnableGroupView(hwndList, TRUE); - - /// - SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES | LVS_EX_CHECKBOXES | LVS_EX_LABELTIP); - ListView_DeleteAllItems(hwndList); - - /// - OBJLIST &todo = *(OBJLIST *)lParam; - for (int i = 0; i < todo.getCount(); ++i) { - int groupId = 3; - LVITEM lvi = {0}; - lvi.mask = LVIF_PARAM | LVIF_GROUPID | LVIF_TEXT | LVIF_IMAGE; - - if (_tcschr(todo[i].tszOldName, L'\\') != NULL) - groupId = _tcsstr(todo[i].tszOldName, L"Plugins") != NULL ? 1 : 2; - - lvi.iItem = i; - lvi.lParam = (LPARAM)&todo[i]; - lvi.iGroupId = groupId; - lvi.iImage = -1; - lvi.pszText = todo[i].tszOldName; - int iRow = ListView_InsertItem(hwndList, &lvi); - - - if (iRow != -1) { - lvi.iItem = iRow; - if (groupId == 1) { - lvi.mask = LVIF_IMAGE; - lvi.iSubItem = 1; - lvi.iImage = 0; - ListView_SetItem(hwndList, &lvi); - } - } - todo[i].bEnabled = false; - } - HWND hwOk = GetDlgItem(hDlg, IDOK); - EnableWindow(hwOk, false); - } - - // do this after filling list - enables 'ITEMCHANGED' below - SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam); - Utils_RestoreWindowPosition(hDlg, 0, MODNAME, "ListWindow"); - return TRUE; - - case WM_NOTIFY: - if (((LPNMHDR) lParam)->hwndFrom == hwndList) { - switch (((LPNMHDR) lParam)->code) { - case LVN_ITEMCHANGED: - if (GetWindowLongPtr(hDlg, GWLP_USERDATA)) { - NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; - - LVITEM lvI = {0}; - lvI.iItem = nmlv->iItem; - lvI.iSubItem = 0; - lvI.mask = LVIF_PARAM; - ListView_GetItem(hwndList, &lvI); - - OBJLIST &todo = *(OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - if ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) { - todo[lvI.iItem].bEnabled = ListView_GetCheckState(hwndList, nmlv->iItem); - - bool enableOk = false; - for (int i=0; i < todo.getCount(); ++i) { - if (todo[i].bEnabled) { - enableOk = true; - break; - } - } - HWND hwOk = GetDlgItem(hDlg, IDOK); - EnableWindow(hwOk, enableOk ? TRUE : FALSE); - } - } - break; - } - } - break; - - case WM_COMMAND: - if (HIWORD( wParam ) == BN_CLICKED) { - switch(LOWORD(wParam)) { - case IDOK: - EnableWindow( GetDlgItem(hDlg, IDOK), FALSE); - EnableWindow( GetDlgItem(hDlg, IDC_SELALL), FALSE); - EnableWindow( GetDlgItem(hDlg, IDC_SELNONE), FALSE); - - mir_forkthread(ApplyDownloads, hDlg); - return TRUE; - - case IDC_DETAILS: - bShowDetails = !bShowDetails; - ResizeVert(hDlg, bShowDetails ? 242 : 60); - break; - - case IDC_SELALL: - SelectAll(hDlg, true); - break; - - case IDC_SELNONE: - SelectAll(hDlg, false); - break; - - case IDCANCEL: - DestroyWindow(hDlg); - return TRUE; - } - } - break; - - case WM_SIZE: // make the dlg resizeable - if ( !IsIconic(hDlg)) { - UTILRESIZEDIALOG urd = { sizeof(urd) }; - urd.hInstance = hInst; - urd.hwndDlg = hDlg; - urd.lpTemplate = MAKEINTRESOURCEA(IDD_LIST); - urd.pfnResizer = ListDlg_Resize; - CallService(MS_UTILS_RESIZEDIALOG, 0, (LPARAM)&urd); - } - break; - - case WM_DESTROY: - Utils_SaveWindowPosition(hDlg, NULL, MODNAME, "ListWindow"); - Skin_ReleaseIcon((HICON)SendMessage(hDlg, WM_SETICON, ICON_BIG, 0)); - Skin_ReleaseIcon((HICON)SendMessage(hDlg, WM_SETICON, ICON_SMALL, 0)); - hwndDialog = NULL; - delete (OBJLIST *)GetWindowLongPtr(hDlg, GWLP_USERDATA); - SetWindowLongPtr(hDlg, GWLP_USERDATA, 0); - break; - } - - return FALSE; -} - INT_PTR CALLBACK DlgMsgPop(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { diff --git a/plugins/PluginUpdater/src/Scanner.cpp b/plugins/PluginUpdater/src/Scanner.cpp deleted file mode 100644 index eebd69cd62..0000000000 --- a/plugins/PluginUpdater/src/Scanner.cpp +++ /dev/null @@ -1,571 +0,0 @@ -/* -Copyright (C) 2010 Mataes - -This is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this file; see the file license.txt. If -not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. -*/ - -#include "Common.h" - -int CalculateModuleHash(const TCHAR *tszFileName, char *dest); - -static BYTE IsPluginDisabled(const char *filename) -{ - return db_get_b(NULL, "PluginDisable", filename, 0); -} - -static bool Exists(LPCTSTR strName) -{ - return GetFileAttributes(strName) != INVALID_FILE_ATTRIBUTES; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -struct ServListEntry -{ - ServListEntry(const char* _name, const char* _hash, int _crc) : - m_name( mir_a2t(_name)), - m_bNeedFree(true), - m_crc(_crc) - { - strncpy(m_szHash, _hash, sizeof(m_szHash)); - } - - ServListEntry(TCHAR* _name) : - m_name(_name), - m_bNeedFree(false) - { - } - - ~ServListEntry() - { - if (m_bNeedFree) - mir_free(m_name); - } - - TCHAR *m_name; - char m_szHash[32+1]; - bool m_bNeedFree; - int m_crc; -}; - -static int CompareHashes(const ServListEntry *p1, const ServListEntry *p2) -{ - return _tcsicmp(p1->m_name, p2->m_name); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -struct -{ - TCHAR *oldName, *newName; -} -static renameTable[] = -{ - { _T("svc_dbepp.dll"), _T("Plugins\\dbeditorpp.dll") }, - { _T("svc_crshdmp.dll"), _T("Plugins\\crashdumper.dll") }, - { _T("svc_vi.dll"), _T("Plugins\\versioninfo.dll") }, - { _T("crashrpt.dll"), _T("Plugins\\crashdumper.dll") }, - { _T("advsplashscreen.dll"), _T("Plugins\\splashscreen.dll") }, - { _T("import_sa.dll"), _T("Plugins\\import.dll") }, - { _T("newnr.dll"), _T("Plugins\\notesreminders.dll") }, - { _T("dbtool.exe"), _T("Plugins\\dbchecker.dll") }, - { _T("dbtool_sa.exe"), _T("Plugins\\dbchecker.dll") }, - { _T("bclist.dll"), _T("Plugins\\clist_blind.dll") }, - { _T("otr.dll"), _T("Plugins\\MirOTR.dll") }, - { _T("ttnotify.dll"), _T("Plugins\\TooltipNotify.dll") }, - { _T("NewStatusNotify.dll"), _T("Plugins\\NewXStatusNotify.dll") }, - - { _T("proto_newsaggr.dll"), _T("Icons\\proto_newsaggregator.dll") }, - { _T("clienticons_general.dll"), _T("Icons\\fp_icons.dll") }, - { _T("clienticons_miranda.dll"), _T("Icons\\fp_icons.dll") }, - { _T("fp_icq.dll"), _T("Icons\\fp_icons.dll") }, - { _T("fp_jabber.dll"), _T("Icons\\fp_icons.dll") }, - { _T("clienticons_aim.dll"), _T("") }, - { _T("clienticons_gadu.dll"), _T("") }, - { _T("clienticons_gg.dll"), _T("") }, - { _T("clienticons_icq.dll"), _T("") }, - { _T("clienticons_irc.dll"), _T("") }, - { _T("clienticons_jabber.dll"), _T("") }, - { _T("clienticons_mra.dll"), _T("") }, - { _T("clienticons_msn.dll"), _T("") }, - { _T("clienticons_multiproto.dll"), _T("") }, - { _T("clienticons_multiprotocols.dll"), _T("") }, - { _T("clienticons_others.dll"), _T("") }, - { _T("clienticons_overlays.dll"), _T("") }, - { _T("clienticons_packs.dll"), _T("") }, - { _T("clienticons_qq.dll"), _T("") }, - { _T("clienticons_rss.dll"), _T("") }, - { _T("clienticons_skype.dll"), _T("") }, - { _T("clienticons_tlen.dll"), _T("") }, - { _T("clienticons_voip.dll"), _T("") }, - { _T("clienticons_weather.dll"), _T("") }, - { _T("clienticons_yahoo.dll"), _T("") }, - { _T("fp_aim.dll"), _T("") }, - { _T("fp_c6_mra_skype.dll"), _T("") }, - { _T("fp_gg.dll"), _T("") }, - { _T("fp_irc.dll"), _T("") }, - { _T("fp_msn.dll"), _T("") }, - { _T("fp_packs.dll"), _T("") }, - { _T("fp_qq.dll"), _T("") }, - { _T("fp_rss.dll"), _T("") }, - { _T("fp_tlen.dll"), _T("") }, - { _T("fp_weather.dll"), _T("") }, - { _T("fp_yahoo.dll"), _T("") }, - - { _T("clist_classic.dll"), _T("") }, - { _T("chat.dll"), _T("") }, - { _T("gender.dll"), _T("") }, - { _T("srmm.dll"), _T("") }, - { _T("extraicons.dll"), _T("") }, -}; - -static bool CheckFileRename(const TCHAR *ptszOldName, TCHAR *pNewName) -{ - for (int i=0; i < SIZEOF(renameTable); i++) - if ( !_tcsicmp(ptszOldName, renameTable[i].oldName)) { - _tcscpy(pNewName, renameTable[i].newName); - return true; - } - - return false; -} - -typedef OBJLIST SERVLIST; - -static bool isValidExtension(const TCHAR *ptszFileName) -{ - const TCHAR *pExt = _tcsrchr(ptszFileName, '.'); - if (pExt == NULL) - return false; - - if ( !_tcsicmp(pExt, _T(".dll"))) return true; - if ( !_tcsicmp(pExt, _T(".exe"))) return true; - if ( !_tcsicmp(pExt, _T(".txt"))) return true; - return false; -} - -static void ScanFolder(const TCHAR *tszFolder, size_t cbBaseLen, int level, const TCHAR *tszBaseUrl, SERVLIST& hashes, OBJLIST *UpdateFiles) -{ - // skip updater's own folder - if ( !_tcsicmp(tszFolder, tszRoot)) - return; - - TCHAR tszBuf[MAX_PATH]; - mir_sntprintf(tszBuf, SIZEOF(tszBuf), _T("%s\\*"), tszFolder); - - WIN32_FIND_DATA ffd; - HANDLE hFind = FindFirstFile(tszBuf, &ffd); - if (hFind == INVALID_HANDLE_VALUE) - return; - - do { - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if ( !_tcscmp(ffd.cFileName, _T(".")) || !_tcscmp(ffd.cFileName, _T(".."))) - continue; - - // we need to skip profile folder - TCHAR tszProfilePath[MAX_PATH]; - CallService(MS_DB_GETPROFILEPATHT, SIZEOF(tszProfilePath), (LPARAM)tszProfilePath); - - mir_sntprintf(tszBuf, SIZEOF(tszBuf), _T("%s\\%s"), tszFolder, ffd.cFileName); - if (0 != _tcsicmp(tszBuf, tszProfilePath)) - ScanFolder(tszBuf, cbBaseLen, level+1, tszBaseUrl, hashes, UpdateFiles); - continue; - } - - if ( !isValidExtension(ffd.cFileName)) - continue; - - // calculate the current file's relative name and store it into tszNewName - TCHAR tszNewName[MAX_PATH]; - if ( !CheckFileRename(ffd.cFileName, tszNewName)) { - if (level == 0) - _tcscpy(tszNewName, ffd.cFileName); - else - mir_sntprintf(tszNewName, SIZEOF(tszNewName), _T("%s\\%s"), tszFolder+cbBaseLen, ffd.cFileName); - } - - bool bHasNewVersion = false; - TCHAR *ptszUrl; - int MyCRC = 0; - mir_sntprintf(tszBuf, SIZEOF(tszBuf), _T("%s\\%s"), tszFolder, ffd.cFileName); - - // this file is not marked for deletion - if (tszNewName[0]) { - ServListEntry tmp(tszNewName); - ServListEntry *item = hashes.find(&tmp); - if (item == NULL) { - TCHAR *p = _tcsrchr(tszNewName, '.'); - if (p[-1] != 'w' && p[-1] != 'W') - continue; - - int iPos = int(p - tszNewName)-1; - strdel(p-1, 1); - if ((item = hashes.find(&tmp)) == NULL) - continue; - - strdel(tszNewName+iPos, 1); - } - - ptszUrl = item->m_name; - - char szMyHash[33]; - CalculateModuleHash(tszBuf, szMyHash); - - MyCRC = item->m_crc; - bHasNewVersion = strcmp(szMyHash, item->m_szHash) != 0; - } - else { // file was marked for deletion, add it to the list anyway - bHasNewVersion = true; - ptszUrl = _T(""); - } - - // Compare versions - if (bHasNewVersion) { // Yeah, we've got new version. - FILEINFO *FileInfo = new FILEINFO; - _tcscpy(FileInfo->tszOldName, tszBuf+cbBaseLen); // copy the relative old name - if (tszNewName[0] == 0) { - FileInfo->bDeleteOnly = TRUE; - _tcscpy(FileInfo->tszNewName, tszBuf); // save the full old name for deletion - } - else { - FileInfo->bDeleteOnly = FALSE; - _tcsncpy(FileInfo->tszNewName, ptszUrl, SIZEOF(FileInfo->tszNewName)); - } - - _tcscpy(tszBuf, ptszUrl); - TCHAR *p = _tcsrchr(tszBuf, '.'); - if (p) *p = 0; - p = _tcsrchr(tszBuf, '\\'); - p = (p) ? p+1 : tszBuf; - _tcslwr(p); - - mir_sntprintf(FileInfo->File.tszDiskPath, SIZEOF(FileInfo->File.tszDiskPath), _T("%s\\Temp\\%s.zip"), tszRoot, p); - mir_sntprintf(FileInfo->File.tszDownloadURL, SIZEOF(FileInfo->File.tszDownloadURL), _T("%s/%s.zip"), tszBaseUrl, tszBuf); - for (p = _tcschr(FileInfo->File.tszDownloadURL, '\\'); p != 0; p = _tcschr(p, '\\')) - *p++ = '/'; - - FileInfo->File.CRCsum = MyCRC; - UpdateFiles->insert(FileInfo); - } // end compare versions - } - while (FindNextFile(hFind, &ffd) != 0); - - FindClose(hFind); -} - -static void GetFullComponent(const TCHAR *tszFolder, const TCHAR *tszBaseUrl, SERVLIST& hashes, OBJLIST *UpdateFiles) -{ - // skip updater's own folder - if ( !_tcsicmp(tszFolder, tszRoot)) - return; - - TCHAR tszPath[MAX_PATH]; - for (int i = 0 ; i < hashes.getCount(); i++) - { - mir_sntprintf(tszPath, SIZEOF(tszPath), _T("%s\\%s"), tszFolder, hashes[i].m_name); - - // this file exist on disk - if (GetFileAttributes(tszPath) != DWORD(-1)) - continue; - - { - ServListEntry tmp(hashes[i].m_name); - ServListEntry *item = hashes.find(&tmp); - - FILEINFO *FileInfo = new FILEINFO; - FileInfo->bDeleteOnly = FALSE; - _tcscpy(FileInfo->tszOldName, item->m_name); // copy the relative old name - _tcscpy(FileInfo->tszNewName, item->m_name); - - TCHAR tszFileName[MAX_PATH]; - _tcscpy(tszFileName, _tcsrchr(tszPath, L'\\') + 1); - TCHAR *p = _tcschr(tszFileName, L'.'); *p = 0; - - TCHAR tszRelFileName[MAX_PATH]; - _tcscpy(tszRelFileName, item->m_name); - p = _tcschr(tszRelFileName, L'.'); *p = 0; - p = _tcschr(tszRelFileName, L'\\'); - p = (p) ? p+1 : tszRelFileName; - _tcslwr(p); - - - mir_sntprintf(FileInfo->File.tszDiskPath, SIZEOF(FileInfo->File.tszDiskPath), _T("%s\\Temp\\%s.zip"), tszRoot, tszFileName); - mir_sntprintf(FileInfo->File.tszDownloadURL, SIZEOF(FileInfo->File.tszDownloadURL), _T("%s/%s.zip"), tszBaseUrl, tszRelFileName); - for (p = _tcschr(FileInfo->File.tszDownloadURL, '\\'); p != 0; p = _tcschr(p, '\\')) - *p++ = '/'; - FileInfo->File.CRCsum = item->m_crc; - UpdateFiles->insert(FileInfo); - } // end compare versions - } -} - -static void __stdcall LaunchDialog(void *param) -{ - CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_UPDATE), GetDesktopWindow(), DlgUpdate, (LPARAM)param); -} - -static void __stdcall LaunchListDialog(void *param) -{ - CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_LIST), GetDesktopWindow(), DlgList, (LPARAM)param); -} - -static void CheckUpdates(void *) -{ - char szKey[64] = {0}; - DBVARIANT dbVar = {0}; - - TCHAR tszTempPath[MAX_PATH]; - DWORD dwLen = GetTempPath(SIZEOF(tszTempPath), tszTempPath); - if (tszTempPath[dwLen-1] == '\\') - tszTempPath[dwLen-1] = 0; - - // Load files info - if (db_get_ts(NULL, MODNAME, "UpdateURL", &dbVar)) { // URL is not set - db_set_ts(NULL, MODNAME, "UpdateURL", _T(DEFAULT_UPDATE_URL)); - db_get_ts(NULL, MODNAME, "UpdateURL", &dbVar); - } - - REPLACEVARSARRAY vars[2]; - vars[0].lptzKey = _T("platform"); - #ifdef WIN64 - vars[0].lptzValue = _T("64"); - #else - vars[0].lptzValue = _T("32"); - #endif - vars[1].lptzKey = vars[1].lptzValue = 0; - - REPLACEVARSDATA dat = { sizeof(REPLACEVARSDATA) }; - dat.dwFlags = RVF_TCHAR; - dat.variables = vars; - ptrT tszBaseUrl((TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)dbVar.ptszVal, (LPARAM)&dat)); - db_free(&dbVar); - - // Download version info - ShowPopup(NULL, TranslateT("Plugin Updater"), TranslateT("Downloading version info..."), 4, 0); - - FILEURL pFileUrl; - mir_sntprintf(pFileUrl.tszDownloadURL, SIZEOF(pFileUrl.tszDownloadURL), _T("%s/hashes.zip"), (TCHAR*)tszBaseUrl); - mir_sntprintf(pFileUrl.tszDiskPath, SIZEOF(pFileUrl.tszDiskPath), _T("%s\\hashes.zip"), tszTempPath); - if (!DownloadFile(pFileUrl.tszDownloadURL, pFileUrl.tszDiskPath, 0)) { - ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("An error occured while downloading the update."), 1, 0); - hCheckThread = NULL; - return; - } - - unzip(pFileUrl.tszDiskPath, tszTempPath, NULL); - DeleteFile(pFileUrl.tszDiskPath); - - TCHAR tszTmpIni[MAX_PATH] = {0}; - mir_sntprintf(tszTmpIni, SIZEOF(tszTmpIni), _T("%s\\hashes.txt"), tszTempPath); - FILE *fp = _tfopen(tszTmpIni, _T("r")); - if (!fp) { - hCheckThread = NULL; - return; - } - - SERVLIST hashes(50, CompareHashes); - char str[200]; - while(fgets(str, SIZEOF(str), fp) != NULL) { - rtrim(str); - char *p = strchr(str, ' '); - if (p == NULL) - continue; - - *p++ = 0; - if ( !opts.bUpdateIcons && !_strnicmp(str, "icons\\", 6)) - continue; - - _strlwr(p); - - int dwCrc32; - char *p1 = strchr(p, ' '); - if (p1 == NULL) - dwCrc32 = 0; - else { - *p1++ = 0; - sscanf(p1, "%08x", &dwCrc32); - } - hashes.insert(new ServListEntry(str, p, dwCrc32)); - } - fclose(fp); - DeleteFile(tszTmpIni); - - FILELIST *UpdateFiles = new FILELIST(20); - TCHAR *dirname = Utils_ReplaceVarsT(_T("%miranda_path%")); - ScanFolder(dirname, lstrlen(dirname)+1, 0, tszBaseUrl, hashes, UpdateFiles); - mir_free(dirname); - - // Show dialog - if (UpdateFiles->getCount() == 0) { - if ( !opts.bSilent) - ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("No updates found."), 2, 0); - } - else CallFunctionAsync(LaunchDialog, UpdateFiles); - - hCheckThread = NULL; -} - -static void GetList(void *) -{ - char szKey[64] = {0}; - DBVARIANT dbVar = {0}; - - TCHAR tszTempPath[MAX_PATH]; - DWORD dwLen = GetTempPath(SIZEOF(tszTempPath), tszTempPath); - if (tszTempPath[dwLen-1] == '\\') - tszTempPath[dwLen-1] = 0; - - // Load files info - if (db_get_ts(NULL, MODNAME, "UpdateURL", &dbVar)) { // URL is not set - db_set_ts(NULL, MODNAME, "UpdateURL", _T(DEFAULT_UPDATE_URL)); - db_get_ts(NULL, MODNAME, "UpdateURL", &dbVar); - } - - REPLACEVARSARRAY vars[2]; - vars[0].lptzKey = _T("platform"); - #ifdef WIN64 - vars[0].lptzValue = _T("64"); - #else - vars[0].lptzValue = _T("32"); - #endif - vars[1].lptzKey = vars[1].lptzValue = 0; - - REPLACEVARSDATA dat = { sizeof(REPLACEVARSDATA) }; - dat.dwFlags = RVF_TCHAR; - dat.variables = vars; - mir_ptr tszBaseUrl((TCHAR*)CallService(MS_UTILS_REPLACEVARS, (WPARAM)dbVar.ptszVal, (LPARAM)&dat)); - db_free(&dbVar); - - // Download version info - ShowPopup(NULL, TranslateT("Plugin Updater"), TranslateT("Downloading version info..."), 4, 0); - - FILEURL pFileUrl; - mir_sntprintf(pFileUrl.tszDownloadURL, SIZEOF(pFileUrl.tszDownloadURL), _T("%s/hashes.zip"), (TCHAR*)tszBaseUrl); - mir_sntprintf(pFileUrl.tszDiskPath, SIZEOF(pFileUrl.tszDiskPath), _T("%s\\hashes.zip"), tszTempPath); - if (!DownloadFile(pFileUrl.tszDownloadURL, pFileUrl.tszDiskPath, 0)) { - ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("An error occured while downloading the update."), 1, 0); - hListThread = NULL; - return; - } - - unzip(pFileUrl.tszDiskPath, tszTempPath, NULL); - DeleteFile(pFileUrl.tszDiskPath); - - TCHAR tszTmpIni[MAX_PATH] = {0}; - mir_sntprintf(tszTmpIni, SIZEOF(tszTmpIni), _T("%s\\hashes.txt"), tszTempPath); - FILE *fp = _tfopen(tszTmpIni, _T("r")); - if (!fp) { - hListThread = NULL; - return; - } - - //SERVLIST hashes(50, CompareHashes); - FILELIST *UpdateFiles = new FILELIST(20); - char str[200]; - TCHAR *dirname = Utils_ReplaceVarsT(_T("%miranda_path%")); - while(fgets(str, SIZEOF(str), fp) != NULL) { - rtrim(str); - char *p = strchr(str, ' '); - if (p == NULL) - continue; - - *p++ = 0; - /*if ( !opts.bUpdateIcons && !_strnicmp(str, "icons\\", 6)) - continue;*/ - - _strlwr(p); - - int dwCrc32; - char *p1 = strchr(p, ' '); - if (p1 == NULL) - dwCrc32 = 0; - else { - *p1++ = 0; - sscanf(p1, "%08x", &dwCrc32); - } - ServListEntry hash(str, p, dwCrc32); - - TCHAR tszPath[MAX_PATH]; - mir_sntprintf(tszPath, SIZEOF(tszPath), _T("%s\\%s"), dirname, hash.m_name); - - if (GetFileAttributes(tszPath) != DWORD(-1)) - continue; - - FILEINFO *FileInfo = new FILEINFO; - FileInfo->bDeleteOnly = FALSE; - _tcscpy(FileInfo->tszOldName, hash.m_name); // copy the relative old name - _tcscpy(FileInfo->tszNewName, hash.m_name); - - TCHAR tszFileName[MAX_PATH]; - _tcscpy(tszFileName, _tcsrchr(tszPath, L'\\') + 1); - TCHAR *tp = _tcschr(tszFileName, L'.'); *tp = 0; - - TCHAR tszRelFileName[MAX_PATH]; - _tcscpy(tszRelFileName, hash.m_name); - tp = _tcsrchr(tszRelFileName, L'.'); if (tp) *tp = 0; - tp = _tcschr(tszRelFileName, L'\\'); if (tp) tp++; else tp = tszRelFileName; - _tcslwr(tp); - - mir_sntprintf(FileInfo->File.tszDiskPath, SIZEOF(FileInfo->File.tszDiskPath), _T("%s\\Temp\\%s.zip"), tszRoot, tszFileName); - mir_sntprintf(FileInfo->File.tszDownloadURL, SIZEOF(FileInfo->File.tszDownloadURL), _T("%s/%s.zip"), tszBaseUrl, tszRelFileName); - for (tp = _tcschr(FileInfo->File.tszDownloadURL, '\\'); tp != 0; tp = _tcschr(tp, '\\')) - *tp++ = '/'; - FileInfo->File.CRCsum = hash.m_crc; - UpdateFiles->insert(FileInfo); - } - fclose(fp); - DeleteFile(tszTmpIni); - - mir_free(dirname); - - // Show dialog - if (UpdateFiles->getCount() == 0) { - if ( !opts.bSilent) - ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("List is empty."), 2, 0); - } - else CallFunctionAsync(LaunchListDialog, UpdateFiles); - - hListThread = NULL; -} - -void DoCheck(int iFlag) -{ - if (hCheckThread) - ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("Update checking already started!"), 2, 0); - else if (hwndDialog) { - ShowWindow(hwndDialog, SW_SHOW); - SetForegroundWindow(hwndDialog); - SetFocus(hwndDialog); - } - else if (iFlag) { - hCheckThread = mir_forkthread(CheckUpdates, 0); - db_set_dw(NULL, MODNAME, "LastUpdate", time(NULL)); - } -} - -void DoGetList(int iFlag) -{ - if (hListThread) - ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("List loading already started!"), 2, 0); - else if (hwndDialog) { - ShowWindow(hwndDialog, SW_SHOW); - SetForegroundWindow(hwndDialog); - SetFocus(hwndDialog); - } - else if (iFlag) - hListThread = mir_forkthread(GetList, 0); -} -- cgit v1.2.3