long OldXMLDataAge(const Category cat) { TCHAR xml_data_filename[MAX_PATH]; TCHAR *ts; mir_sntprintf(xml_data_filename, SIZEOF(xml_data_filename), _T("%s\\%s.xml"), options.data_folder, (ts = GetTString(category_files[cat]))); mir_free(ts); HANDLE hDataFile = CreateFile(xml_data_filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if(hDataFile != INVALID_HANDLE_VALUE) { FILETIME ft_then, ft_now; GetFileTime(hDataFile, 0, 0, &ft_then); CloseHandle(hDataFile); SYSTEMTIME now; GetSystemTime(&now); SystemTimeToFileTime(&now, &ft_now); ULARGE_INTEGER uli_now, uli_then, diff; uli_now.HighPart = ft_now.dwHighDateTime; uli_now.LowPart = ft_now.dwLowDateTime; uli_then.HighPart = ft_then.dwHighDateTime; uli_then.LowPart = ft_then.dwLowDateTime; diff.QuadPart = uli_now.QuadPart - uli_then.QuadPart; long minutes = (long)(diff.QuadPart / mult.QuadPart); // rounded down // convert to hours (add 30 so we round up properly) return (minutes + 30) / 60; } return -1; }
INT_PTR SetUpdateOptions(WPARAM wParam, LPARAM lParam) { char *szComponentName = (char *)wParam; UpdateOptions *uo = (UpdateOptions *)lParam; TCHAR *temp1 = 0; bool found = false; EnterCriticalSection(&list_cs); for (int i=0; i<update_list.getCount(); ++i) { if(strcmp(update_list[i].update.szComponentName, szComponentName) == 0 || _tcscmp(temp1 = GetTString(update_list[i].update.szComponentName), (TCHAR *)szComponentName) == 0) // when set via options, szComponentName is translated and potentially already converted to unicode { found = true; update_list[i].update_options = *uo; SaveUpdateOptions(update_list[i].update.szComponentName, &update_list[i].update_options); if(update_list[i].file_id == -1 && !uo->use_beta) { update_list[i].file_id = CheckForFileID(update_list[i].update.szUpdateURL, update_list[i].update.szVersionURL, update_list[i].update.szComponentName); } break; } } LeaveCriticalSection(&list_cs); mir_free(temp1); return found ? 0 : 1; }
bool OldXMLDataExists(const Category cat) { TCHAR xml_data_filename[MAX_PATH]; TCHAR *ts; mir_sntprintf(xml_data_filename, SIZEOF(xml_data_filename), _T("%s\\%s.xml"), options.data_folder, (ts = GetTString(category_files[cat]))); mir_free(ts); HANDLE hDataFile = CreateFile(xml_data_filename, 0, 0, 0, OPEN_EXISTING, 0, 0); if(hDataFile != INVALID_HANDLE_VALUE) { CloseHandle(hDataFile); return true; } return false; }
bool LoadOldXMLData(const Category cat, bool update_age) { TCHAR xml_data_filename[MAX_PATH]; TCHAR *ts; mir_sntprintf(xml_data_filename, SIZEOF(xml_data_filename), _T("%s\\%s.xml"), options.data_folder, (ts = GetTString(category_files[cat]))); mir_free(ts); if(pData[cat]) free(pData[cat]); pData[cat] = 0; dataLength[cat] = 0; // load HANDLE hDataFile = CreateFile(xml_data_filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if(hDataFile != INVALID_HANDLE_VALUE) { dataLength[cat] = GetFileSize(hDataFile, 0); if(dataLength[cat]) { unsigned long bytes_read; pData[cat] = (BYTE *)malloc(dataLength[cat]); if(ReadFile(hDataFile, pData[cat], dataLength[cat], &bytes_read, 0)) dataLength[cat] = bytes_read; else { free(pData[cat]); pData[cat] = 0; dataLength[cat] = 0; } } if(update_age) { FILETIME ft_now; SYSTEMTIME now; GetSystemTime(&now); SystemTimeToFileTime(&now, &ft_now); SetFileTime(hDataFile, 0, 0, &ft_now); } CloseHandle(hDataFile); } if(pData[cat] && dataLength[cat]) { doc[cat] = ezxml_parse_str((char*)pData[cat], dataLength[cat]); return doc[cat] != NULL; } return false; }
INT_PTR GetUpdateOptions(WPARAM wParam, LPARAM lParam) { char *szComponentName = (char *)wParam; UpdateOptions *uo = (UpdateOptions *)lParam; TCHAR *temp1 = 0; bool found = false; EnterCriticalSection(&list_cs); for (int i=0; i<update_list.getCount(); ++i) { if(strcmp(update_list[i].update.szComponentName, szComponentName) == 0 || _tcscmp((temp1 = GetTString(update_list[i].update.szComponentName)), (TCHAR *)szComponentName) == 0) // when set via options, szComponentName is translated and potentially already converted to unicode { found = true; *uo = update_list[i].update_options; break; } } LeaveCriticalSection(&list_cs); mir_free(temp1); return found ? 0 : 1; }
bool SaveXMLData(const Category cat) { TCHAR xml_data_filename[MAX_PATH]; TCHAR *ts; mir_sntprintf(xml_data_filename, SIZEOF(xml_data_filename), _T("%s\\%s.xml"), options.data_folder, (ts = GetTString(category_files[cat]))); mir_free(ts); if(!CreatePath(options.data_folder)) { return false; } // save data if(pData[cat] && dataLength[cat]) { HANDLE hDataFile = CreateFile(xml_data_filename, GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); if(hDataFile != INVALID_HANDLE_VALUE) { unsigned long bytes_written; WriteFile(hDataFile, pData[cat], dataLength[cat], &bytes_written, 0); CloseHandle(hDataFile); return true; } } return false; }
bool GetFileString::GetString(LPWSTR* DestStr, size_t& Length) { if(Peek) { Peek = false; *DestStr = LastString; Length = LastLength; return LastResult; } switch (m_CodePage) { case CP_UNICODE: case CP_REVERSEBOM: if (GetTString(m_wReadBuf, m_wStr, m_CodePage == CP_REVERSEBOM)) { *DestStr = m_wStr.data(); Length = m_wStr.size() - 1; return true; } return false; case CP_UTF8: case CP_UTF7: { std::vector<char> CharStr; CharStr.reserve(DELTA); bool ExitCode = GetTString(m_ReadBuf, CharStr); if (ExitCode) { Utf::Errs errs; int len = Utf::ToWideChar(m_CodePage, CharStr.data(), static_cast<int>(CharStr.size())-1, m_wStr.data(), static_cast<int>(m_wStr.size()), &errs); SomeDataLost = SomeDataLost || errs.count > 0; if (errs.small_buff) { std::vector<wchar_t>(len + 1).swap(m_wStr); Utf::ToWideChar(m_CodePage, CharStr.data(), static_cast<int>(CharStr.size())-1, m_wStr.data(), len, nullptr); } m_wStr.resize(len+1); m_wStr[len] = L'\0'; *DestStr = m_wStr.data(); Length = m_wStr.size() - 1; } return ExitCode; } default: { std::vector<char> CharStr; CharStr.reserve(DELTA); bool ExitCode = GetTString(m_ReadBuf, CharStr); if (ExitCode) { DWORD Result = ERROR_SUCCESS; int nResultLength = 0; bool bGet = false; m_wStr.resize(CharStr.size()); if (!SomeDataLost) { nResultLength = MultiByteToWideChar(m_CodePage, SomeDataLost ? 0 : MB_ERR_INVALID_CHARS, CharStr.data(), static_cast<int>(CharStr.size()), m_wStr.data(), static_cast<int>(m_wStr.size())); if (!nResultLength) { Result = GetLastError(); if (Result == ERROR_NO_UNICODE_TRANSLATION) { SomeDataLost = true; bGet = true; } } } else { bGet = true; } if (bGet) { nResultLength = MultiByteToWideChar(m_CodePage, 0, CharStr.data(), static_cast<int>(CharStr.size()), m_wStr.data(), static_cast<int>(m_wStr.size())); if (!nResultLength) { Result = GetLastError(); } } if (Result == ERROR_INSUFFICIENT_BUFFER) { nResultLength = MultiByteToWideChar(m_CodePage, 0, CharStr.data(), static_cast<int>(CharStr.size()), nullptr, 0); std::vector<wchar_t>(nResultLength + 1).swap(m_wStr); nResultLength = MultiByteToWideChar(m_CodePage, 0, CharStr.data(), static_cast<int>(CharStr.size()), m_wStr.data(), nResultLength); } m_wStr.resize(nResultLength); *DestStr = m_wStr.data(); Length = m_wStr.size() - 1; } return ExitCode; } } }
// returns true if any downloaded dll is active bool DownloadUpdates(UpdateList &todo, FilenameMap *map, bool dlls_only) { bool dll_enabled_or_langpack = false; bool use_popup = options.popup_notify && ArePopupsEnabled(); // iterate through the updates we need to check if (use_popup) { ShowPopup(0, TranslateT("Downloading Updates"), _T(""), POPFLAG_SAVEHWND, -1); } else { CreateProgressWindow(); SendMessage(hwndProgress, WM_SETTEXT, 0, (LPARAM)TranslateT("Progress - Downloading updates...")); SendMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Downloading"), 0); } TCHAR msg[512]; TCHAR *temp_str; bool a_download_succeeded = false; for (int index = 0; index < todo.getCount(); index++) { // remember if the user has decided not to install this version char stored_setting[256]; mir_snprintf(stored_setting, SIZEOF(stored_setting), "DisabledVer%s", todo[index].update.szComponentName); DBVARIANT dbv; bool download = todo[index].update_options.enabled; if(!DBGetContactSettingString(0, "Updater", stored_setting, &dbv)) { if(dbv.pszVal && strcmp(dbv.pszVal, todo[index].newVersion) == 0) download = false; else DBDeleteContactSetting(0, "Updater", stored_setting); DBFreeVariant(&dbv); } if(download) { mir_sntprintf(msg, SIZEOF(msg), TranslateT("Downloading plugin: %s"), (temp_str = GetTString(todo[index].update.szComponentName))); mir_free(temp_str); } else { mir_sntprintf(msg, SIZEOF(msg), TranslateT("Skipping plugin: %s"), (temp_str = GetTString(todo[index].update.szComponentName))); mir_free(temp_str); } if (!use_popup) { SendMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)msg, 0); PostMessage(hwndProgress, WMU_SETPROGRESS, (WPARAM)(int)(index * 100.0 / todo.getCount()), 0); } //else if(hwndPop) // disabled - just annoying //ChangePopupText(hwndPop, msg); if (download) { bool got_file = false; if(todo[index].update_options.use_beta) { // download from i->update.szBetaUpdateURL to temp folder got_file = GetFile(todo[index].update.szBetaUpdateURL, options.temp_folder, todo[index].update.szComponentName, todo[index].newVersion, dlls_only); } else { got_file = GetFile(todo[index].update.szUpdateURL, options.temp_folder, todo[index].update.szComponentName, todo[index].newVersion, dlls_only); } if(got_file) { a_download_succeeded = true; if (todo[index].file_id != -1) { FileNameStruct* fns = map->find((FileNameStruct*)&todo[index].file_id); if (todo[index].cat == MC_PLUGINS || todo[index].cat == MC_UNKNOWN) dll_enabled_or_langpack |= RearrangeDlls(todo[index].shortName, fns->list); else if(todo[index].cat == MC_LOCALIZATION) { RearrangeLangpacks(todo[index].shortName, fns->list); dll_enabled_or_langpack = true; } } else { dll_enabled_or_langpack = true; } } } if (!use_popup && hwndProgress == 0) { RemoveFolder(options.temp_folder); break; // user closed progress window - cancel } } ProgressWindowDone(); // postmessage here causes a lockup on exit! bah popups!! //if(hwndPop) PostMessage(hwndPop, WMU_CLOSEPOP, 0, 0); if (hwndPop) SendMessage(hwndPop, WMU_CLOSEPOP, 0, 0); if(!a_download_succeeded) { for(int i = 0; i < todo.getCount(); ++i) free(todo[i].newVersion); todo.destroy(); } return dll_enabled_or_langpack; }
void CheckForUpdatesWorker(void *param) { if (checking) return; /* // this check doesn't work on some systems - not sure which or why if(!(GetSystemMetrics(SM_NETWORK) & 1)) { ShowError(TranslateT("No network - aborting update check")); NLog("worker thread aborting - no network"); return 1; // no network } */ NLog("CheckForUpdatesWorker thread starting"); checking = true; WriteLastCheckTime(); bool confirm = !(((DWORD)param & 1) == 1); bool restart = !(((DWORD)param & 2) == 2); // if restart is false, then we're doing an 'update and shutdown' if(hwndOptions) PostMessage(hwndOptions, WMU_CHECKING, 0, 0); bool use_popup = options.popup_notify && ArePopupsEnabled(); FilenameMap fn_map(5, CompareFileNameStruct); if (use_popup) { ShowPopup(0, TranslateT("Checking for Updates"), _T(""), POPFLAG_SAVEHWND, -1); } else { CreateProgressWindow(); SendMessage(hwndProgress, WM_SETTEXT, 0, (LPARAM)TranslateT("Progress - Checking for updates...")); if (options.use_xml_backend) SendMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Downloading XML data"), 0); else SendMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Checking for updates"), 0); } EnterCriticalSection(&list_cs); if (options.use_xml_backend) { if (UpdateXMLData(MC_PLUGINS)) // prevent double error messages (in some cases) { // iterate through the registered plugins if (!use_popup) SendMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Scanning plugins folder"), 0); ScanPlugins(&fn_map, &update_list); if (UpdateXMLData(MC_LOCALIZATION)) { if (!use_popup) SendMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Scanning language packs"), 0); ScanLangpacks(&fn_map, &update_list); } if(!use_popup) SendMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Updating component file listing ids"), 0); UpdateFLIDs(update_list); } if (!use_popup) SendMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)TranslateT("Checking for updates"), 0); } UpdateList update_list2(update_list); LeaveCriticalSection(&list_cs); int count = update_list2.getCount(), index = 0; TCHAR msg[512]; TCHAR *temp_str; UpdateList todo; for(index = 0; index < count; index++) { if(update_list2[index].update_options.enabled) { mir_sntprintf(msg, SIZEOF(msg), TranslateT("Checking plugin: %s"), (temp_str = GetTString(update_list2[index].update.szComponentName))); mir_free(temp_str); } else { mir_sntprintf(msg, SIZEOF(msg), TranslateT("Skipping plugin: %s"), (temp_str = GetTString(update_list2[index].update.szComponentName))); mir_free(temp_str); } if(!use_popup) { SendMessage(hwndProgress, WMU_SETMESSAGE, (WPARAM)msg, 0); SendMessage(hwndProgress, WMU_SETPROGRESS, (WPARAM)(int)(index * 100.0 / count), 0); } //else if(hwndPop) // disabled - just annoying //ChangePopupText(hwndPop, msg); if (update_list2[index].update_options.enabled) { char *nv; bool beta; if (nv = UpdateRequired(update_list2[index], &beta)) { todo.insert(new UpdateInternal(update_list2[index])); todo[todo.getCount()-1].newVersion = nv; todo[todo.getCount()-1].update_options.use_beta = beta; } } if (!use_popup && hwndProgress == NULL) { RemoveFolder(options.temp_folder); break; // user closed progress window - cancel } } ProgressWindowDone(); if (hwndPop) PostMessage(hwndPop, WMU_CLOSEPOP, 0 , 0); if(options.use_xml_backend) { FreeXMLData(MC_PLUGINS); FreeXMLData(MC_LOCALIZATION); } bool restore_status = true; if (todo.getCount()) { int cd_ret = CD_OK; if (confirm) { if (use_popup) { ShowPopup(0, TranslateT("Updates Available"), TranslateT("Updated Miranda components detected.\nClick here to install."), POPFLAG_SAVEHWND, -1); DWORD ret; while ((ret = WaitForSingleObject(hEventPop, 200)) == WAIT_TIMEOUT && !Miranda_Terminated()); if (!pop_cancelled && ret == WAIT_OBJECT_0 && !Miranda_Terminated()) { cd_ret = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_CONFIRMUPDATES), GetDesktopWindow(), DlgProcConfirm, (LPARAM)&todo); } else { if(hwndOptions) PostMessage(hwndOptions, WMU_DONECHECKING, 0, 0); RestoreStatus(); for(int i=0; i<todo.getCount(); ++i) free(todo[i].newVersion); checking = false; Netlib_CloseHandle(hNetlibHttp); hNetlibHttp = NULL; return; } } else cd_ret = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_CONFIRMUPDATES), GetDesktopWindow(), DlgProcConfirm, (LPARAM)&todo); } if (!confirm || cd_ret == CD_CONFALL || cd_ret == CD_NOINSTALL || cd_ret == CD_OK) { bool conf_all = (cd_ret == CD_CONFALL), no_install = (cd_ret == CD_NOINSTALL); // ensure the backup folder exists (either create it or return non-zero signifying error) if (options.backup && !CreatePath(options.backup_folder)) { //MessageBox(0, Translate("Could not create backup folder"), Translate("Error"), MB_OK | MB_ICONERROR); ShowError(TranslateT("Could not create backup folder")); if (hwndOptions) PostMessage(hwndOptions, WMU_DONECHECKING, 0, 0); RestoreStatus(); for (int i=0; i<todo.getCount(); ++i) free(todo[i].newVersion); checking = false; Netlib_CloseHandle(hNetlibHttp); hNetlibHttp = NULL; return; } bool dll_enabled_or_langpack = DownloadUpdates(todo, &fn_map, confirm ? false : options.auto_dll_only); if (todo.getCount() && !no_install) { if (!conf_all || DialogBox(hInst, MAKEINTRESOURCE(IDD_CONFIRMCOMPONENTS), GetDesktopWindow(), DlgProcConfirmComponents) == IDOK) { if (!dll_enabled_or_langpack && restart) { // we're not doing an 'update and shutdown', and we're not updating any active dlls...so just install // get folders TCHAR root_folder[MAX_PATH], plugins_folder[MAX_PATH]; GetRootDir(root_folder); _tcscpy(plugins_folder, root_folder); _tcscat(plugins_folder, _T("\\Plugins")); // move files MoveFiles(0, options.temp_folder, plugins_folder, options.backup_folder, root_folder); // rescan to get correct version numbers ScanPlugins(0, 0); } else { if (ExternProcess(restart) == 0) // if restarting, don't restore status restore_status = false; } } } } for (int i=0; i<todo.getCount(); ++i) free(todo[i].newVersion); } else if (!restart) { PostMessage((HWND)CallService(MS_CLUI_GETHWND, 0, 0), WM_COMMAND, ID_ICQ_EXIT, 0); } if (restore_status && restart) // restore status if we're not doing an 'update and shutdown', and the update was unsuccessful (or there was nothing to update, or no need to shutdown) { checking = false; if (hwndOptions) PostMessage(hwndOptions, WMU_DONECHECKING, 0, 0); RestoreStatus(); } Netlib_CloseHandle(hNetlibHttp); hNetlibHttp = NULL; }
bool enum_file_lines::GetString(string_view& Str, eol::type& Eol) const { switch (m_CodePage) { case CP_UNICODE: case CP_REVERSEBOM: if (!GetTString(m_wReadBuf, m_wStr, Eol, m_CodePage == CP_REVERSEBOM)) return false; Str = m_wStr; return true; case CP_UTF8: case CP_UTF7: { std::string CharStr; CharStr.reserve(DELTA); if (!GetTString(m_ReadBuf, CharStr, Eol)) return false; if (!CharStr.empty()) { Utf::errors Errors; m_wStr.resize(m_wStr.capacity()); for (auto Overflow = true; Overflow;) { const auto Size = Utf::get_chars(m_CodePage, CharStr, m_wStr, &Errors); Overflow = Size > m_wStr.size(); m_wStr.resize(Size); } m_ConversionError = m_ConversionError || Errors.Conversion.Error; } else { m_wStr.clear(); } Str = m_wStr; return true; } default: { std::string CharStr; CharStr.reserve(DELTA); if (!GetTString(m_ReadBuf, CharStr, Eol)) return false; if (!CharStr.empty()) { DWORD Result = ERROR_SUCCESS; bool bGet = false; m_wStr.resize(CharStr.size()); size_t nResultLength = 0; if (!m_ConversionError) { nResultLength = MultiByteToWideChar(m_CodePage, MB_ERR_INVALID_CHARS, CharStr.data(), static_cast<int>(CharStr.size()), m_wStr.data(), static_cast<int>(m_wStr.size())); if (!nResultLength) { Result = GetLastError(); if (Result == ERROR_NO_UNICODE_TRANSLATION || (Result == ERROR_INVALID_FLAGS && IsNoFlagsCodepage(m_CodePage))) { m_ConversionError = true; bGet = true; } } } else { bGet = true; } if (bGet) { nResultLength = encoding::get_chars(m_CodePage, CharStr, m_wStr); if (nResultLength > m_wStr.size()) { Result = ERROR_INSUFFICIENT_BUFFER; } } if (Result == ERROR_INSUFFICIENT_BUFFER) { nResultLength = encoding::get_chars_count(m_CodePage, CharStr); m_wStr.resize(nResultLength); encoding::get_chars(m_CodePage, CharStr, m_wStr); } if (!nResultLength) return false; m_wStr.resize(nResultLength); } else { m_wStr.clear(); } Str = m_wStr; return true; } } }
bool GetFileString::GetString(LPWSTR* DestStr, size_t& Length) { if(Peek) { Peek = false; *DestStr = LastString; Length = LastLength; return LastResult; } switch (m_CodePage) { case CP_UNICODE: case CP_REVERSEBOM: if (GetTString(m_wReadBuf, m_wStr, m_CodePage == CP_REVERSEBOM)) { *DestStr = m_wStr.data(); Length = m_wStr.size() - 1; return true; } return false; default: { std::vector<char> CharStr; CharStr.reserve(DELTA); bool ExitCode = GetTString(m_ReadBuf, CharStr); if (ExitCode) { DWORD Result = ERROR_SUCCESS; int nResultLength = 0; bool bGet = false; m_wStr.resize(CharStr.size()); if (!SomeDataLost) { // при CP_UTF7 dwFlags должен быть 0, см. MSDN nResultLength = MultiByteToWideChar(m_CodePage, (SomeDataLost || m_CodePage == CP_UTF7) ? 0 : MB_ERR_INVALID_CHARS, CharStr.data(), static_cast<int>(CharStr.size()), m_wStr.data(), static_cast<int>(m_wStr.size())); if (!nResultLength) { Result = GetLastError(); if (Result == ERROR_NO_UNICODE_TRANSLATION) { SomeDataLost = true; bGet = true; } } } else { bGet = true; } if (bGet) { nResultLength = MultiByteToWideChar(m_CodePage, 0, CharStr.data(), static_cast<int>(CharStr.size()), m_wStr.data(), static_cast<int>(m_wStr.size())); if (!nResultLength) { Result = GetLastError(); } } if (Result == ERROR_INSUFFICIENT_BUFFER) { nResultLength = MultiByteToWideChar(m_CodePage, 0, CharStr.data(), static_cast<int>(CharStr.size()), nullptr, 0); std::vector<wchar_t>(nResultLength + 1).swap(m_wStr); nResultLength = MultiByteToWideChar(m_CodePage, 0, CharStr.data(), static_cast<int>(CharStr.size()), m_wStr.data(), nResultLength); } m_wStr.resize(nResultLength); *DestStr = m_wStr.data(); Length = m_wStr.size() - 1; } return ExitCode; } } }
bool GetFile(char *url, TCHAR *temp_folder, char *plugin_name, char *version, bool dlls_only, int recurse_count /*=0*/) { if(recurse_count > MAX_REDIRECT_RECURSE) { NLog("GetFile: error, too many redirects"); return false; } TCHAR save_file[MAX_PATH]; if(url == 0 || temp_folder == 0 || plugin_name == 0) return false; // ensure temp_folder exists if(!CreatePath(options.temp_folder)) { NLogF("GetFile: error creating temp folder, code %u", GetLastError()); return false; } // ensure zip_folder exists, if necessary if(options.save_zips && !CreatePath(options.zip_folder)) { NLogF("GetFile: error creating zip folder, code %u", GetLastError()); return false; } TCHAR *temp_str = GetTString(plugin_name); mir_sntprintf(save_file, SIZEOF(save_file), _T("%s\\%s"), temp_folder, temp_str); mir_free(temp_str); if (version) { temp_str = GetTString(version); _tcscat(save_file, _T("_")); _tcscat(save_file, temp_str); mir_free(temp_str); } // copt extension from url char *ext = strrchr(url, '.'); if(ext && *ext && strcmp(ext, ".dll") == 0) { _tcscat(save_file, _T(".dll")); } else { // default to zip extension (e.g. miranda fl) _tcscat(save_file, _T(".zip")); ext = ".zip"; } // replace version text in URL char tmp_url[1024]; if (version != NULL) { char *p; size_t pos = 0; size_t version_len = strlen(version); while ((p = strstr(url, "%VERSION%")) != NULL && (p - url + version_len < sizeof(tmp_url) - 1)) { strncpy(&tmp_url[pos], url, p - url); pos += p - url; strcpy(&tmp_url[pos], version); pos += version_len; url += p - url + 9; // 9 == strlen("%VERSION%") } if (strlen(url) < sizeof(tmp_url) - 1) { strcpy(&tmp_url[pos], url); pos += strlen(url); } tmp_url[pos] = 0; url = tmp_url; } NETLIBHTTPREQUEST req = {0}; req.cbSize = sizeof(req); req.requestType = REQUEST_GET; req.szUrl = url; req.flags = NLHRF_NODUMP | NLHRF_HTTP11; req.nlc = hNetlibHttp; if (CallService(MS_SYSTEM_GETVERSION, 0, 0) >= PLUGIN_MAKE_VERSION(0,9,0,5)) req.flags |= NLHRF_PERSISTENT | NLHRF_REDIRECT; NETLIBHTTPREQUEST *resp = (NETLIBHTTPREQUEST *)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUser, (LPARAM)&req); if (resp) { hNetlibHttp = resp->nlc; if (resp->resultCode == 200) { if (ext && *ext && _stricmp(ext, ".zip") == 0) { if (!options.no_unzip) unzip_mem(resp->pData, resp->dataLength, temp_folder); if (options.save_zips) { TCHAR save_archive[MAX_PATH]; mir_sntprintf(save_archive, SIZEOF(save_archive), _T("%s%s"), options.zip_folder, _tcsrchr(save_file, '\\')); HANDLE hSaveFile = CreateFile(save_archive, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (hSaveFile != INVALID_HANDLE_VALUE) { unsigned long bytes_written; WriteFile(hSaveFile, resp->pData, resp->dataLength, &bytes_written, NULL); CloseHandle(hSaveFile); } else NLogF("GetFile: error creating file, code %u", GetLastError()); } if(dlls_only) { NLog("Deleting non-dlls"); DeleteNonDlls(temp_folder); } } else { HANDLE hSaveFile = CreateFile(save_file, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (hSaveFile != INVALID_HANDLE_VALUE) { unsigned long bytes_written; WriteFile(hSaveFile, resp->pData, resp->dataLength, &bytes_written, NULL); CloseHandle(hSaveFile); } else NLogF("GetFile: error creating file, code %u", GetLastError()); } CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); return true; } else if (resp->resultCode >= 300 && resp->resultCode < 400) { // get new location bool ret = false; for (int i = 0; i < resp->headersCount; i++) { if (_stricmp(resp->headers[i].szName, "Location") == 0) { ret = GetFile(resp->headers[i].szValue, temp_folder, plugin_name, version, dlls_only, recurse_count + 1); break; } } CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); return ret; } else { TCHAR buff[1024], *tmp; mir_sntprintf(buff, SIZEOF(buff), TranslateT("Failed to download \"%s\" - Invalid response, code %d"), (tmp = mir_a2t(plugin_name)), resp->resultCode); ShowError(buff); mir_free(tmp); } CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); } else { hNetlibHttp = NULL; int err = GetLastError(); if (err && !Miranda_Terminated()) { TCHAR buff[1024], *tmp; int len = mir_sntprintf(buff, SIZEOF(buff), TranslateT("Failed to download \"%s\": "), (tmp = mir_a2t(plugin_name))); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, err, 0, buff + len, 512 - len, 0); ShowError(buff); mir_free(tmp); } } return false; }