summaryrefslogtreecommitdiff
path: root/tools/IM-NG Updater/src/Scanner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/IM-NG Updater/src/Scanner.cpp')
-rw-r--r--tools/IM-NG Updater/src/Scanner.cpp234
1 files changed, 234 insertions, 0 deletions
diff --git a/tools/IM-NG Updater/src/Scanner.cpp b/tools/IM-NG Updater/src/Scanner.cpp
new file mode 100644
index 0000000000..f1696738fd
--- /dev/null
+++ b/tools/IM-NG Updater/src/Scanner.cpp
@@ -0,0 +1,234 @@
+/*
+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 DBGetContactSettingByte(NULL, "PluginDisable", filename, 0);
+}
+
+static bool Exists(LPCTSTR strName)
+{
+ return GetFileAttributes(strName) != INVALID_FILE_ATTRIBUTES;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct ServListEntry
+{
+ ~ServListEntry()
+ { mir_free(m_name);
+ }
+
+ TCHAR *m_name, *m_searchName;
+ char m_szHash[32+1];
+};
+
+static int CompareHashes(const ServListEntry* p1, const ServListEntry* p2)
+{
+ return _tcscmp(p1->m_searchName, p2->m_searchName);
+}
+
+typedef OBJLIST<ServListEntry> SERVLIST;
+
+static void ScanFolder(const TCHAR* tszFolder, const TCHAR* tszBaseUrl, SERVLIST& hashes, OBJLIST<FILEINFO>* UpdateFiles)
+{
+ // skip updater's own folder
+ if ( !_tcsicmp(tszFolder, tszRoot))
+ return;
+
+ TCHAR tszMask[MAX_PATH];
+ mir_sntprintf(tszMask, SIZEOF(tszMask), _T("%s\\*"), tszFolder);
+
+ WIN32_FIND_DATA ffd;
+ HANDLE hFind = FindFirstFile(tszMask, &ffd);
+ if (hFind == INVALID_HANDLE_VALUE)
+ return;
+
+ do {
+ if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ if ( !_tcscmp(ffd.cFileName, _T(".")) || !_tcscmp(ffd.cFileName, _T("..")))
+ continue;
+ if ( !_tcsicmp(ffd.cFileName, _T("Profiles")))
+ continue;
+
+ mir_sntprintf(tszMask, SIZEOF(tszMask), _T("%s\\%s"), tszFolder, ffd.cFileName);
+ ScanFolder(tszMask, tszBaseUrl, hashes, UpdateFiles);
+ continue;
+ }
+
+ TCHAR *pExt = _tcsrchr(ffd.cFileName, '.');
+ if (pExt == NULL) continue;
+ if ( _tcsicmp(pExt, _T(".dll")) && _tcsicmp(pExt, _T(".exe")))
+ continue;
+
+ // Read version info
+ TCHAR key[MAX_PATH];
+ _tcscpy(key, ffd.cFileName);
+ _tcslwr(key);
+ ServListEntry tmp = {NULL, key};
+ ServListEntry* item = hashes.find(&tmp);
+ if (item == NULL)
+ continue;
+
+ size_t cbLenOrig = _tcslen(item->m_name);
+ size_t cbLen = (size_t)mir_sntprintf(tszMask, SIZEOF(tszMask), _T("%s\\%s"), tszFolder, ffd.cFileName);
+ if (cbLenOrig > cbLen) // wtf?
+ continue;
+ for (TCHAR *p = _tcschr(tszMask, '\\'); p != NULL; p = _tcschr(p+1, '\\'))
+ *p = '/';
+ if ( _tcsicmp(tszMask + cbLen - cbLenOrig, item->m_name)) // now verify the rest
+ continue;
+
+ char szMyHash[33];
+ CalculateModuleHash(tszMask, szMyHash);
+
+ // Compare versions
+ if ( strcmp(szMyHash, item->m_szHash)) { // Yeah, we've got new version.
+ FILEINFO* FileInfo = new FILEINFO;
+ strncpy(FileInfo->newhash, item->m_szHash, SIZEOF(FileInfo->newhash));
+ strncpy(FileInfo->curhash, szMyHash, SIZEOF(FileInfo->newhash));
+ _tcscpy(FileInfo->tszDescr, ffd.cFileName);
+
+ *pExt = 0;
+ mir_sntprintf(FileInfo->File.tszDiskPath, SIZEOF(FileInfo->File.tszDiskPath), _T("%s\\Temp\\%s.zip"), tszRoot, ffd.cFileName);
+
+ mir_sntprintf(FileInfo->File.tszDownloadURL, SIZEOF(FileInfo->File.tszDownloadURL), _T("%s/%s"), tszBaseUrl, item->m_name);
+ if ((pExt = _tcsrchr(FileInfo->File.tszDownloadURL, '.')) != NULL)
+ _tcscpy(pExt, _T(".zip"));
+
+ UpdateFiles->insert(FileInfo);
+ } // end compare versions
+ }
+ while (FindNextFile(hFind, &ffd) != 0);
+
+ FindClose(hFind);
+}
+
+static void __stdcall LaunchDialog(void* param)
+{
+ CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_UPDATE), GetDesktopWindow(), DlgUpdate, (LPARAM)param);
+}
+
+static void CheckUpdates(void *)
+{
+ char szKey[64] = {0};
+ DBVARIANT dbVar = {0};
+
+ if (!Exists(tszRoot))
+ CreateDirectoryTreeT(tszRoot);
+
+ // Load files info
+ if (DBGetContactSettingTString(NULL, MODNAME, "UpdateURL", &dbVar)) { // URL is not set
+ DBWriteContactSettingTString(NULL, MODNAME, "UpdateURL", _T(DEFAULT_UPDATE_URL));
+ DBGetContactSettingTString(NULL, MODNAME, "UpdateURL", &dbVar);
+ }
+ else {
+ #ifdef WIN64
+ if (_tcsstr(dbVar.ptszVal, _T("x32"))) {
+ DBWriteContactSettingTString(NULL, MODNAME, "UpdateURL", _T(DEFAULT_UPDATE_URL));
+ DBGetContactSettingTString(NULL, MODNAME, "UpdateURL", &dbVar);
+ }
+ #endif
+ }
+ TCHAR* tszBaseUrl = NEWTSTR_ALLOCA(dbVar.ptszVal);
+ DBFreeVariant(&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"), tszBaseUrl);
+ mir_sntprintf(pFileUrl.tszDiskPath, SIZEOF(pFileUrl.tszDiskPath), _T("%s\\hashes.zip"), tszRoot);
+ if (!DownloadFile(pFileUrl.tszDownloadURL, pFileUrl.tszDiskPath)) {
+ ShowPopup(0, LPGENT("Plugin Updater"), LPGENT("An error occured while downloading the update."), 1, 0);
+ CheckThread = NULL;
+ return;
+ }
+
+ unzip(pFileUrl.tszDiskPath, tszRoot, tszRoot);
+ DeleteFile(pFileUrl.tszDiskPath);
+
+ TCHAR tszTmpIni[MAX_PATH] = {0};
+ mir_sntprintf(tszTmpIni, SIZEOF(tszTmpIni), _T("%s\\hashes.txt"), tszRoot);
+ FILE* fp = _tfopen(tszTmpIni, _T("r"));
+ if (!fp)
+ 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;
+
+ ServListEntry* newItem = new ServListEntry;
+ _strlwr(p);
+ strncpy(newItem->m_szHash, p, sizeof(newItem->m_szHash));
+
+ for (p = strchr(str, '\\'); p != NULL; p = strchr(p+1, '\\'))
+ *p = '/';
+
+ newItem->m_name = mir_a2t(str);
+
+ TCHAR* szName = _tcsrchr(newItem->m_name, '/');
+ newItem->m_searchName = (szName == NULL) ? newItem->m_name : szName+1;
+ _tcslwr(newItem->m_searchName);
+ hashes.insert(newItem);
+ }
+ fclose(fp);
+ DeleteFile(tszTmpIni);
+
+ FILELIST *UpdateFiles = new FILELIST(20);
+ TCHAR *dirname = Utils_ReplaceVarsT(_T("%miranda_path%"));
+ ScanFolder(dirname, 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);
+
+ CheckThread = NULL;
+}
+
+void DoCheck(int iFlag)
+{
+ if (CheckThread)
+ 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) {
+ CheckThread = mir_forkthread(CheckUpdates, 0);
+ DBWriteContactSettingDword(NULL, MODNAME, "LastUpdate", time(NULL));
+ }
+}