summaryrefslogtreecommitdiff
path: root/plugins/PluginUpdater
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2013-05-19 18:19:42 +0000
committerGeorge Hazan <george.hazan@gmail.com>2013-05-19 18:19:42 +0000
commit3489e949e30e75d1f93610b2c6015b4ff95aefa2 (patch)
tree2ff6cda94a034b89358eea8279524be544b826f9 /plugins/PluginUpdater
parentfaceb04e370ff43eb8b2096d08f7375a9c292f2f (diff)
universal plugin downloader for the PluginUpdater plugin
git-svn-id: http://svn.miranda-ng.org/main/trunk@4745 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/PluginUpdater')
-rw-r--r--plugins/PluginUpdater/PluginUpdater_11.vcxproj10
-rw-r--r--plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters14
-rw-r--r--plugins/PluginUpdater/res/Resource.rc25
-rw-r--r--plugins/PluginUpdater/res/info.icobin0 -> 1150 bytes
-rw-r--r--plugins/PluginUpdater/src/Common.h6
-rw-r--r--plugins/PluginUpdater/src/Events.cpp7
-rw-r--r--plugins/PluginUpdater/src/Notifications.cpp345
-rw-r--r--plugins/PluginUpdater/src/PluginUpdater.cpp20
-rw-r--r--plugins/PluginUpdater/src/Scanner.cpp190
-rw-r--r--plugins/PluginUpdater/src/Utils.cpp15
-rw-r--r--plugins/PluginUpdater/src/resource.h12
11 files changed, 631 insertions, 13 deletions
diff --git a/plugins/PluginUpdater/PluginUpdater_11.vcxproj b/plugins/PluginUpdater/PluginUpdater_11.vcxproj
index c66da3da88..88241dbec3 100644
--- a/plugins/PluginUpdater/PluginUpdater_11.vcxproj
+++ b/plugins/PluginUpdater/PluginUpdater_11.vcxproj
@@ -92,6 +92,7 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<AdditionalLibraryDirectories>$(ProfileDir)..\..\bin11\lib</AdditionalLibraryDirectories>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
@@ -115,6 +116,7 @@
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<AdditionalLibraryDirectories>$(ProfileDir)..\..\bin11\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
@@ -140,6 +142,7 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(ProfileDir)..\..\bin11\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
@@ -165,6 +168,7 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(ProfileDir)..\..\bin11\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>..\..\include\msapi</AdditionalIncludeDirectories>
@@ -224,6 +228,12 @@
<Project>{e2a369cd-eda3-414f-8ad0-e732cd7ee68c}</Project>
</ProjectReference>
</ItemGroup>
+ <ItemGroup>
+ <Image Include="res\btnClose.ico" />
+ <Image Include="res\btnOk.ico" />
+ <Image Include="res\info.ico" />
+ <Image Include="res\menu.ico" />
+ </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
diff --git a/plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters b/plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters
index 8f5a421d1a..4f6cd1a2b0 100644
--- a/plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters
+++ b/plugins/PluginUpdater/PluginUpdater_11.vcxproj.filters
@@ -98,4 +98,18 @@
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
+ <ItemGroup>
+ <Image Include="res\menu.ico">
+ <Filter>Resource Files</Filter>
+ </Image>
+ <Image Include="res\btnOk.ico">
+ <Filter>Resource Files</Filter>
+ </Image>
+ <Image Include="res\btnClose.ico">
+ <Filter>Resource Files</Filter>
+ </Image>
+ <Image Include="res\info.ico">
+ <Filter>Resource Files</Filter>
+ </Image>
+ </ItemGroup>
</Project> \ No newline at end of file
diff --git a/plugins/PluginUpdater/res/Resource.rc b/plugins/PluginUpdater/res/Resource.rc
index b4b0271a75..36884c96c5 100644
--- a/plugins/PluginUpdater/res/Resource.rc
+++ b/plugins/PluginUpdater/res/Resource.rc
@@ -29,6 +29,7 @@ LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
IDI_MENU ICON "menu.ico"
IDI_OK ICON "btnOk.ico"
IDI_CANCEL ICON "btnClose.ico"
+IDI_INFO ICON "info.ico"
/////////////////////////////////////////////////////////////////////////////
//
@@ -76,7 +77,7 @@ BEGIN
CONTROL "Stable version",IDC_STABLE,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,11,106,236,10
CONTROL "Development version (less stable)",IDC_TRUNK,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,11,121,236,10
CONTROL "Custom version",IDC_CUSTOM,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,11,136,236,10
- EDITTEXT IDC_CUSTOMURL,11,150,234,16,ES_AUTOHSCROLL | WS_TABSTOP
+ EDITTEXT IDC_CUSTOMURL,11,150,234,16,ES_AUTOHSCROLL
END
IDD_POPUP DIALOGEX 0, 0, 316, 182
@@ -125,6 +126,20 @@ BEGIN
CTEXT "Popups",IDC_STATIC,7,9,79,8
END
+IDD_LIST DIALOGEX 0, 0, 240, 236
+STYLE DS_SETFONT | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Component list"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CTEXT "Here is the complete list of missing Miranda NG components. \nCheck components that you want to download. \n\nClick on info icon to view component info page.",IDC_UPDATETEXT,9,9,223,44
+ DEFPUSHBUTTON "Download",IDOK,185,218,50,14
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,1,58,236,1
+ CONTROL "",IDC_LIST_UPDATES,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,6,64,229,149
+ PUSHBUTTON "Select &all",IDC_SELALL,6,218,50,14,NOT WS_TABSTOP
+ PUSHBUTTON "Select &none",IDC_SELNONE,59,218,50,14,NOT WS_TABSTOP
+END
+
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
@@ -169,6 +184,14 @@ BEGIN
BEGIN
BOTTOMMARGIN, 180
END
+
+ IDD_LIST, DIALOG
+ BEGIN
+ VERTGUIDE, 6
+ VERTGUIDE, 235
+ BOTTOMMARGIN, 234
+ HORZGUIDE, 232
+ END
END
#endif // APSTUDIO_INVOKED
diff --git a/plugins/PluginUpdater/res/info.ico b/plugins/PluginUpdater/res/info.ico
new file mode 100644
index 0000000000..296d8f8f3e
--- /dev/null
+++ b/plugins/PluginUpdater/res/info.ico
Binary files differ
diff --git a/plugins/PluginUpdater/src/Common.h b/plugins/PluginUpdater/src/Common.h
index 9a54f61846..8c101c5e84 100644
--- a/plugins/PluginUpdater/src/Common.h
+++ b/plugins/PluginUpdater/src/Common.h
@@ -114,7 +114,7 @@ extern HINSTANCE hInst;
extern TCHAR tszRoot[MAX_PATH], tszDialogMsg[2048], tszTempPath[MAX_PATH];
extern FILEINFO *pFileInfo;
-extern HANDLE hCheckThread, hPluginUpdaterFolder;
+extern HANDLE hCheckThread, hListThread, hPluginUpdaterFolder;
extern PlugOptions opts;
extern POPUP_OPTIONS PopupOptions;
extern aPopups PopupsList[POPUPS];
@@ -135,16 +135,20 @@ int OptInit(WPARAM, LPARAM);
void BackupFile(TCHAR *ptszSrcFileName, TCHAR *ptszBackFileName);
void DoCheck(int iFlag);
+void DoGetList(int iFlag);
BOOL DownloadFile(LPCTSTR tszURL, LPCTSTR tszLocal, int CRCsum);
void ShowPopup(HWND hDlg, LPCTSTR Title, LPCTSTR Text, int Number, int ActType);
void __stdcall RestartMe(void*);
+void __stdcall OpenPluginOptions(void*);
BOOL AllowUpdateOnStartup();
void InitTimer();
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);
bool unzip(const TCHAR *ptszZipFile, TCHAR *ptszDestPath, TCHAR *ptszBackPath);
diff --git a/plugins/PluginUpdater/src/Events.cpp b/plugins/PluginUpdater/src/Events.cpp
index a82e0261b8..d55ce08022 100644
--- a/plugins/PluginUpdater/src/Events.cpp
+++ b/plugins/PluginUpdater/src/Events.cpp
@@ -58,6 +58,13 @@ INT_PTR MenuCommand(WPARAM wParam,LPARAM lParam)
return 0;
}
+INT_PTR ShowListCommand(WPARAM wParam,LPARAM lParam)
+{
+ opts.bSilent = false;
+ DoGetList(1);
+ return 0;
+}
+
INT_PTR EmptyFolder(WPARAM wParam,LPARAM lParam)
{
SHFILEOPSTRUCT file_op = {
diff --git a/plugins/PluginUpdater/src/Notifications.cpp b/plugins/PluginUpdater/src/Notifications.cpp
index 94a93d5e43..746449a735 100644
--- a/plugins/PluginUpdater/src/Notifications.cpp
+++ b/plugins/PluginUpdater/src/Notifications.cpp
@@ -377,6 +377,97 @@ LBL_Exit:
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<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) {
+ 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 };
@@ -385,6 +476,14 @@ static void ResizeVert(HWND hDlg, int yy)
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));
+ int res = ImageList_AddIcon(hIml, icon);
+ Skin_ReleaseIcon(icon);
+ return res;
+}
+
INT_PTR CALLBACK DlgUpdate(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND hwndList = GetDlgItem(hDlg, IDC_LIST_UPDATES);
@@ -545,6 +644,252 @@ INT_PTR CALLBACK DlgUpdate(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam
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)LoadSkinnedIconBig(SKINICON_OTHER_OPTIONS));
+ SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadSkinnedIcon(SKINICON_OTHER_OPTIONS));
+ {
+ 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 = L"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 = LPGENT("Plugins");
+ lvg.iGroupId = 1;
+ ListView_InsertGroup(hwndList, 0, &lvg);
+
+ lvg.pszHeader = LPGENT("Icons");
+ lvg.iGroupId = 2;
+ ListView_InsertGroup(hwndList, 0, &lvg);
+
+ lvg.pszHeader = LPGENT("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<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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<FILEINFO> &todo = *(OBJLIST<FILEINFO> *)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<FILEINFO> *)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/PluginUpdater.cpp b/plugins/PluginUpdater/src/PluginUpdater.cpp
index fbd28aa8af..bf914fb48b 100644
--- a/plugins/PluginUpdater/src/PluginUpdater.cpp
+++ b/plugins/PluginUpdater/src/PluginUpdater.cpp
@@ -29,7 +29,7 @@ Boston, MA 02111-1307, USA.
UTF8_INTERFACE utfi;
#endif
-HANDLE hPluginUpdaterFolder = NULL, hCheckUpdates = NULL, hEmptyFolder = NULL;
+HANDLE hPluginUpdaterFolder = NULL, hEmptyFolder = NULL;
HINSTANCE hInst = NULL;
TCHAR tszRoot[MAX_PATH] = {0}, tszTempPath[MAX_PATH];
int hLangpack;
@@ -101,18 +101,24 @@ extern "C" __declspec(dllexport) int Load(void)
IcoLibInit();
// Add cheking update menu item
- hCheckUpdates = CreateServiceFunction(MODNAME"/CheckUpdates", MenuCommand);
+ CreateServiceFunction(MODNAME"/CheckUpdates", MenuCommand);
+ CreateServiceFunction(MODNAME"/ShowList", ShowListCommand);
CLISTMENUITEM mi = { sizeof(mi) };
- mi.position = -0x7FFFFFFF;
+ mi.position = 400010000;
mi.icolibItem = Skin_GetIconHandle("check_update");
mi.pszName = LPGEN("Check for plugin updates");
mi.pszService = MODNAME"/CheckUpdates";
Menu_AddMainMenuItem(&mi);
+ mi.position++;
+ mi.icolibItem = LoadSkinnedIconHandle(SKINICON_OTHER_OPTIONS);
+ mi.pszName = LPGEN("Show full plugin list");
+ mi.pszService = MODNAME"/ShowList";
+ Menu_AddMainMenuItem(&mi);
+
// Add hotkey
- HOTKEYDESC hkd = {0};
- hkd.cbSize = sizeof(hkd);
+ HOTKEYDESC hkd = { sizeof(hkd) };
hkd.pszName = "Check for plugin updates";
hkd.pszDescription = "Check for plugin updates";
hkd.pszSection = "Plugin Updater";
@@ -133,7 +139,9 @@ extern "C" __declspec(dllexport) int Unload(void)
if (hCheckThread)
hCheckThread = NULL;
+ if (hListThread)
+ hListThread = NULL;
+
NetlibUnInit();
- DestroyServiceFunction(hCheckUpdates);
return 0;
}
diff --git a/plugins/PluginUpdater/src/Scanner.cpp b/plugins/PluginUpdater/src/Scanner.cpp
index 3653adfd2f..c3659a6275 100644
--- a/plugins/PluginUpdater/src/Scanner.cpp
+++ b/plugins/PluginUpdater/src/Scanner.cpp
@@ -247,6 +247,7 @@ static void ScanFolder(const TCHAR *tszFolder, size_t cbBaseLen, int level, cons
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
@@ -256,11 +257,62 @@ static void ScanFolder(const TCHAR *tszFolder, size_t cbBaseLen, int level, cons
FindClose(hFind);
}
+static void GetFullComponent(const TCHAR *tszFolder, const TCHAR *tszBaseUrl, SERVLIST& hashes, OBJLIST<FILEINFO> *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};
@@ -357,6 +409,131 @@ static void CheckUpdates(void *)
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<TCHAR> 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 = _tcschr(tszRelFileName, L'.'); *tp = 0;
+ tp = _tcschr(tszRelFileName, L'\\');
+ tp = (p) ? tp+1 : 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 emply."), 2, 0);
+ }
+ else CallFunctionAsync(LaunchListDialog, UpdateFiles);
+
+ hListThread = NULL;
+}
+
void DoCheck(int iFlag)
{
if (hCheckThread)
@@ -371,3 +548,16 @@ void DoCheck(int iFlag)
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);
+}
diff --git a/plugins/PluginUpdater/src/Utils.cpp b/plugins/PluginUpdater/src/Utils.cpp
index 87f7cbedb7..43f27180de 100644
--- a/plugins/PluginUpdater/src/Utils.cpp
+++ b/plugins/PluginUpdater/src/Utils.cpp
@@ -23,7 +23,7 @@ BOOL DlgDld;
int Number = 0;
TCHAR tszDialogMsg[2048] = {0};
FILEINFO *pFileInfo = NULL;
-HANDLE hCheckThread = NULL, hNetlibUser = NULL;
+HANDLE hCheckThread = NULL, hListThread = NULL, hNetlibUser = NULL;
POPUP_OPTIONS PopupOptions = {0};
aPopups PopupsList[POPUPS];
@@ -39,8 +39,9 @@ struct
static iconList[] =
{
{ "check_update", LPGEN("Check for plugin updates"), IDI_MENU },
- { "btn_ok", LPGEN("'Yes' Button"), IDI_OK },
- { "btn_cancel", LPGEN("'No' Button"), IDI_CANCEL }
+ { "btn_ok", LPGEN("'Yes' Button"), IDI_OK },
+ { "btn_cancel", LPGEN("'No' Button"), IDI_CANCEL },
+ { "info", LPGEN("Plugin info"), IDI_INFO },
};
void IcoLibInit()
@@ -361,6 +362,14 @@ void __stdcall RestartMe(void*)
CallService(MS_SYSTEM_RESTART, db_get_b(NULL,MODNAME,"RestartCurrentProfile",1) ? 1 : 0, 0);
}
+void __stdcall OpenPluginOptions(void*)
+{
+ OPENOPTIONSDIALOG ood = {0};
+ ood.cbSize = sizeof(ood);
+ ood.pszPage = "Plugins";
+ Options_Open(&ood);
+}
+
#endif
// FUNCTION: IsRunAsAdmin()
diff --git a/plugins/PluginUpdater/src/resource.h b/plugins/PluginUpdater/src/resource.h
index 2f940e3fee..57416edb3e 100644
--- a/plugins/PluginUpdater/src/resource.h
+++ b/plugins/PluginUpdater/src/resource.h
@@ -1,14 +1,22 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
-// Used by C:\Myranda\plugins\PluginUpdater\res\Resource.rc
+// Used by e:\Projects\C++\MirandaNG\plugins\PluginUpdater\res\Resource.rc
//
#define IDI_MENU 101
#define IDD_UPDATE 102
#define IDD_OPT_UPDATENOTIFY 104
#define IDD_POPUP 105
#define IDD_POPUPDUMMI 106
+#define IDD_LIST 107
#define IDI_OK 108
#define IDI_CANCEL 109
+#define IDI_INFO 111
+#define IDI_DOWN_DEL 112
+#define IDI_DOWN_FAIL 113
+#define IDI_DOWN_LOAD 114
+#define IDI_DOWN_OK 115
+#define IDI_ICON5 116
+#define IDI_DOWN_SKIP 116
#define IDC_UPDATETEXT 1001
#define IDC_CURVER 1002
#define IDC_NEWVER 1003
@@ -69,7 +77,7 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 110
+#define _APS_NEXT_RESOURCE_VALUE 117
#define _APS_NEXT_COMMAND_VALUE 40075
#define _APS_NEXT_CONTROL_VALUE 1044
#define _APS_NEXT_SYMED_VALUE 101