diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt index 267d99d..22389ee 100644 --- a/extensions/CMakeLists.txt +++ b/extensions/CMakeLists.txt @@ -1,5 +1,8 @@ cmake_policy(SET CMP0037 OLD) + add_library(1_Remove\ Repetition_nexthooker_extension SHARED removerepeat.cpp) add_library(2_Copy\ to\ Clipboard_nexthooker_extension SHARED copyclipboard.cpp) -#add_library("3_Google\ Translate_nexthooker_extension" SHARED googletranslate.cpp) -add_library(4_Extra\ Newlines_nexthooker_extension SHARED extranewlines.cpp) \ No newline at end of file +add_library(3_Google\ Translate_nexthooker_extension SHARED googletranslate.cpp) +add_library(4_Extra\ Newlines_nexthooker_extension SHARED extranewlines.cpp) + +target_link_libraries(3_Google\ Translate_nexthooker_extension winhttp.lib) \ No newline at end of file diff --git a/extensions/googletranslate.cpp b/extensions/googletranslate.cpp index 8dd04d4..20bf5af 100644 --- a/extensions/googletranslate.cpp +++ b/extensions/googletranslate.cpp @@ -1,4 +1,32 @@ #include "extensions.h" +#include +#include + +std::wstring GetTranslationUri(const wchar_t* text, unsigned int TKK) +{ + // If no TKK available, use this uri. Can't use too much or google will detect unauthorized access. + if (!TKK) return std::wstring(L"/translate_a/single?client=gtx&dt=ld&dt=rm&dt=tq=") + text; + + // Artikash 8/19/2018: reverse engineered from translate.google.com + char* utf8text = new char[wcslen(text) * 4]; + WideCharToMultiByte(CP_UTF8, 0, text, -1, utf8text, wcslen(text) * 4, NULL, NULL); + + unsigned int a = (unsigned int)(_time64(NULL) / 3600), b = a; // <- the first part of TKK + for (int i = 0; utf8text[i];) + { + a += (unsigned char)utf8text[i++]; + a += a << 10; + a ^= a >> 6; + } + a += a << 3; + a ^= a >> 11; + a += a << 15; + a ^= TKK; + a %= 1000000; + b ^= a; + + return std::wstring(L"/translate_a/single?client=t&dt=ld&dt=rm&dt=t&tk=") + std::to_wstring(a) + L"." + std::to_wstring(b) + L"&q=" + std::wstring(text); +} extern "C" { @@ -13,5 +41,57 @@ extern "C" */ __declspec(dllexport) const wchar_t* OnNewSentence(const wchar_t* sentence, const InfoForExtension* miscInfo) { + static HINTERNET internet = NULL; + if (!internet) internet = WinHttpOpen(L"Mozilla/5.0 NextHooker", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL, 0); + static unsigned int TKK = 0; + + wchar_t error[] = L"Error while translating."; + wchar_t translation[10000] = {}; + wchar_t* message = error; + + if (wcslen(sentence) > 2000 || GetProperty("text number", miscInfo) == 0 || GetProperty("current select", miscInfo) == 0) return sentence; + + if (internet) + { + if (HINTERNET connection = WinHttpConnect(internet, L"translate.google.com", INTERNET_DEFAULT_HTTPS_PORT, 0)) + { + if (HINTERNET request = WinHttpOpenRequest(connection, L"GET", L"/", NULL, NULL, NULL, WINHTTP_FLAG_SECURE)) + { + if (WinHttpSendRequest(request, NULL, 0, NULL, 0, 0, NULL)) + { + DWORD bytesRead; + char buffer[100000]; // Google Translate page is ~64kb + WinHttpReceiveResponse(request, NULL); + WinHttpReadData(request, buffer, 100000, &bytesRead); + TKK = strtoll(strstr(buffer, "a\\x3d") + 5, nullptr, 10) + strtoll(strstr(buffer, "b\\x3d") + 5, nullptr, 10); + } + WinHttpCloseHandle(request); + } + WinHttpCloseHandle(connection); + } + if (HINTERNET connection = WinHttpConnect(internet, L"translate.google.com", INTERNET_DEFAULT_HTTPS_PORT, 0)) + { + if (HINTERNET request = WinHttpOpenRequest(connection, L"GET", GetTranslationUri(sentence, TKK).c_str(), NULL, NULL, NULL, WINHTTP_FLAG_ESCAPE_DISABLE | WINHTTP_FLAG_SECURE)) + { + if (WinHttpSendRequest(request, NULL, 0, NULL, 0, 0, NULL)) + { + DWORD bytesRead; + char buffer[0x10000] = {}; + WinHttpReceiveResponse(request, NULL); + WinHttpReadData(request, buffer, 0x10000, &bytesRead); + // Response formatted as JSON: starts with '[[["' + MultiByteToWideChar(CP_UTF8, 0, buffer + 4, (int)((strstr(buffer, "\",\"")) - (buffer + 4)), translation, 10000); + message = translation; + for (int i = -1; translation[++i];) if (translation[i] == L'\\') translation[i] = 0x200b; + } + WinHttpCloseHandle(request); + } + WinHttpCloseHandle(connection); + } + } + + wchar_t* newSentence = (wchar_t*)malloc((wcslen(sentence) + 3 + wcslen(message)) * sizeof(wchar_t)); + swprintf(newSentence, wcslen(sentence) + 3 + wcslen(message), L"%s%s%s", sentence, L"\r\n", message); + return newSentence; } } \ No newline at end of file