From 927add1b301c9f38808f3d35854d3ce896bff095 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Sat, 19 May 2012 11:12:34 +0000 Subject: adding SpellChecker plugin git-svn-id: http://svn.miranda-ng.org/main/trunk@69 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Updater/socket.cpp | 355 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 355 insertions(+) create mode 100644 plugins/Updater/socket.cpp (limited to 'plugins/Updater/socket.cpp') diff --git a/plugins/Updater/socket.cpp b/plugins/Updater/socket.cpp new file mode 100644 index 0000000000..52a82bd6b1 --- /dev/null +++ b/plugins/Updater/socket.cpp @@ -0,0 +1,355 @@ +#include "common.h" +#include "socket.h" + +void unzip_mem(char* buf, int len, TCHAR* dest); + +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; +} + +char *CheckVersionURL(char *url, BYTE *pbPrefixBytes, int cpbPrefixBytes, BYTE *pbVersionBytes, int cpbVersionBytes) +{ + if (url == 0 || pbPrefixBytes == 0 || cpbPrefixBytes == 0 || pbVersionBytes == 0 || cpbVersionBytes == 0) + return 0; + + char *ret = NULL; + NETLIBHTTPREQUEST req = {0}; + + req.cbSize = sizeof(req); + req.requestType = REQUEST_GET; + req.szUrl = url; + req.flags = NLHRF_DUMPASTEXT | 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) + { + // find the location of the prefix + char* ver = (char*)memmem(resp->pData, resp->dataLength, pbPrefixBytes, cpbPrefixBytes); + if (ver) + { + int len = resp->dataLength - ((ver += cpbPrefixBytes) - resp->pData); + if (cpbVersionBytes <= len && memcmp(ver, pbVersionBytes, cpbVersionBytes) == 0) + { + // same version as current + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); + return 0; + } + else + { + DWORD ver_current, ver_potential; + char *buff = (char *)alloca(cpbVersionBytes + 1); + memcpy(buff, (char *)pbVersionBytes, cpbVersionBytes); + buff[cpbVersionBytes] = 0; + + // this is safe because pData finishes with a zero always (according to m_netlib.h docs) + if (VersionFromString(buff, &ver_current) && VersionFromString(ver, &ver_potential)) + { + switch(options.ver_req) + { + case VR_MAJOR: + ver_current &= 0xFF000000; + ver_potential &= 0xFF000000; + break; + case VR_MINOR: + ver_current &= 0xFFFF0000; + ver_potential &= 0xFFFF0000; + break; + case VR_RELEASE: + ver_current &= 0xFFFFFF00; + ver_potential &= 0xFFFFFF00; + break; + case VR_BUILD: + break; + } + + // we can covert the versions to DWORDS, so compare... + if (ver_current < ver_potential) + { + char buff2[16]; + CreateVersionString(ver_potential, buff2); + ret = _strdup(buff2); + } + } + else // invalid version(s), but different from current - assume it's an update + ret = _strdup(Translate("Yes")); + } + } + } + else if (resp->resultCode == 302) // redirect + { + // get new location + for (int i = 0; i < resp->headersCount; i++) + { + if(_stricmp(resp->headers[i].szName, "Location") == 0) + { + ret = CheckVersionURL(resp->headers[i].szValue, pbPrefixBytes, cpbPrefixBytes, pbVersionBytes, cpbVersionBytes); + break; + } + } + } + else + NLogF("CheckVersionURL: error, http result code %d", resp->resultCode); + + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); + } + else + { + hNetlibHttp = NULL; + int err = GetLastError(); + if (err) + NLogF("CheckVersionURL: error code %d", err); + } + + return ret; +} + +char *UpdateRequired(UpdateInternal &update_internal, bool *beta) +{ + // determine whether update is required + + char *ret = NULL, *ret_beta = NULL; + + if (options.use_xml_backend && update_internal.file_id != -1) + { + const char * res; + if (update_internal.cat == MC_UNKNOWN) + { + if (XMLDataAvailable(MC_PLUGINS) && + (res = FindVersion(update_internal.file_id, update_internal.update.pbVersion, update_internal.update.cpbVersion, MC_PLUGINS))) + { + update_internal.cat = MC_PLUGINS; + if (strcmp(res, "same")) ret = _strdup(res); + } + else if (XMLDataAvailable(MC_LOCALIZATION) && + (res = FindVersion(update_internal.file_id, update_internal.update.pbVersion, update_internal.update.cpbVersion, MC_LOCALIZATION))) + { + update_internal.cat = MC_LOCALIZATION; + if (strcmp(res, "same")) ret = _strdup(res); + } + } + else + { + res = FindVersion(update_internal.file_id, update_internal.update.pbVersion, update_internal.update.cpbVersion, update_internal.cat); + if (res && strcmp(res, "same")) ret = _strdup(res); + } + } + else + { + ret = CheckVersionURL(update_internal.update.szVersionURL, update_internal.update.pbVersionPrefix, + update_internal.update.cpbVersionPrefix, update_internal.update.pbVersion, update_internal.update.cpbVersion); + } + + if (update_internal.update_options.use_beta) + { + ret_beta = CheckVersionURL(update_internal.update.szBetaVersionURL, update_internal.update.pbBetaVersionPrefix, + update_internal.update.cpbBetaVersionPrefix, update_internal.update.pbVersion, update_internal.update.cpbVersion); + } + + if (ret && !ret_beta) + { + if(beta) *beta = false; + return ret; + } + else if (!ret && ret_beta) + { + if (beta) *beta = true; + return ret_beta; + } + else if (ret && ret_beta) + { + // find highest version of ret and ret_beta + + DWORD vRet, vRetBeta; + VersionFromString(ret, &vRet); + VersionFromString(ret_beta, &vRetBeta); + + if (vRetBeta > vRet) + { + free(ret); + if (beta) *beta = true; + return ret_beta; + } + else + { + free(ret_beta); + if (beta) *beta = false; + return ret; + } + } + + return 0; +} -- cgit v1.2.3