summaryrefslogtreecommitdiff
path: root/plugins/PluginUpdater/src/DlgUpdate.cpp
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2013-05-22 21:06:15 +0000
committerGeorge Hazan <george.hazan@gmail.com>2013-05-22 21:06:15 +0000
commit36e1481e95302d388cc834405dd7b0e5eb27747b (patch)
tree8d1226ee91d905bf9c08e8862df0a432e27df967 /plugins/PluginUpdater/src/DlgUpdate.cpp
parent763c87a6be8344d1a3950d2ba133840c7c25c596 (diff)
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
Diffstat (limited to 'plugins/PluginUpdater/src/DlgUpdate.cpp')
-rw-r--r--plugins/PluginUpdater/src/DlgUpdate.cpp627
1 files changed, 627 insertions, 0 deletions
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<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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<FILEINFO> *)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<FILEINFO> *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));
+ }
+}