From cbe3cb21f5bca61a03bbd4ae811ee906e09b3f4f Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sat, 13 Jun 2015 16:55:17 +0000 Subject: - miranda32.exe now does nothing bug extends PATH to %miranda_root%\libs and loads mir_app.dll; - everything that was in miranda32.exe (including resources) moved to mir_app.dll; - exports from mir_app.dll now available for using directly, without perversions; - src/stdplug.h deleted; git-svn-id: http://svn.miranda-ng.org/main/trunk@14143 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/modules/netlib/netlib.cpp | 527 -------------- src/modules/netlib/netlib.h | 220 ------ src/modules/netlib/netlibautoproxy.cpp | 453 ------------- src/modules/netlib/netlibbind.cpp | 307 --------- src/modules/netlib/netlibhttp.cpp | 1168 -------------------------------- src/modules/netlib/netlibhttpproxy.cpp | 459 ------------- src/modules/netlib/netliblog.cpp | 532 --------------- src/modules/netlib/netlibopenconn.cpp | 890 ------------------------ src/modules/netlib/netlibopts.cpp | 530 --------------- src/modules/netlib/netlibpktrecver.cpp | 89 --- src/modules/netlib/netlibsecurity.cpp | 427 ------------ src/modules/netlib/netlibsock.cpp | 313 --------- src/modules/netlib/netlibupnp.cpp | 826 ---------------------- 13 files changed, 6741 deletions(-) delete mode 100644 src/modules/netlib/netlib.cpp delete mode 100644 src/modules/netlib/netlib.h delete mode 100644 src/modules/netlib/netlibautoproxy.cpp delete mode 100644 src/modules/netlib/netlibbind.cpp delete mode 100644 src/modules/netlib/netlibhttp.cpp delete mode 100644 src/modules/netlib/netlibhttpproxy.cpp delete mode 100644 src/modules/netlib/netliblog.cpp delete mode 100644 src/modules/netlib/netlibopenconn.cpp delete mode 100644 src/modules/netlib/netlibopts.cpp delete mode 100644 src/modules/netlib/netlibpktrecver.cpp delete mode 100644 src/modules/netlib/netlibsecurity.cpp delete mode 100644 src/modules/netlib/netlibsock.cpp delete mode 100644 src/modules/netlib/netlibupnp.cpp (limited to 'src/modules/netlib') diff --git a/src/modules/netlib/netlib.cpp b/src/modules/netlib/netlib.cpp deleted file mode 100644 index a900c77f93..0000000000 --- a/src/modules/netlib/netlib.cpp +++ /dev/null @@ -1,527 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "..\..\core\commonheaders.h" -#include "netlib.h" - -static BOOL bModuleInitialized = FALSE; - -HANDLE hConnectionHeaderMutex, hConnectionOpenMutex; -DWORD g_LastConnectionTick; -int connectionTimeout; -HANDLE hSendEvent = NULL, hRecvEvent = NULL; - -typedef BOOL (WINAPI *tGetProductInfo)(DWORD, DWORD, DWORD, DWORD, PDWORD); - -static int CompareNetlibUser(const NetlibUser* p1, const NetlibUser* p2) -{ - return mir_strcmp(p1->user.szSettingsModule, p2->user.szSettingsModule); -} - -LIST netlibUser(5, CompareNetlibUser); -mir_cs csNetlibUser; - -SSL_API si; - -void NetlibFreeUserSettingsStruct(NETLIBUSERSETTINGS *settings) -{ - mir_free(settings->szIncomingPorts); - mir_free(settings->szOutgoingPorts); - mir_free(settings->szProxyAuthPassword); - mir_free(settings->szProxyAuthUser); - mir_free(settings->szProxyServer); -} - -int GetNetlibHandleType(void *p) -{ - __try { - return *(int*)p; - } - __except(EXCEPTION_EXECUTE_HANDLER) - {} - - return NLH_INVALID; -} - -void NetlibInitializeNestedCS(NetlibNestedCriticalSection *nlncs) -{ - nlncs->dwOwningThreadId = 0; - nlncs->lockCount = 0; - nlncs->hMutex = CreateMutex(NULL, FALSE, NULL); -} - -void NetlibDeleteNestedCS(NetlibNestedCriticalSection *nlncs) -{ - CloseHandle(nlncs->hMutex); -} - -int NetlibEnterNestedCS(NetlibConnection *nlc, int which) -{ - NetlibNestedCriticalSection *nlncs; - DWORD dwCurrentThreadId = GetCurrentThreadId(); - - WaitForSingleObject(hConnectionHeaderMutex, INFINITE); - if (nlc == NULL || nlc->handleType != NLH_CONNECTION) { - ReleaseMutex(hConnectionHeaderMutex); - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - nlncs = (which == NLNCS_SEND) ? &nlc->ncsSend : &nlc->ncsRecv; - if (nlncs->lockCount && nlncs->dwOwningThreadId == dwCurrentThreadId) { - nlncs->lockCount++; - ReleaseMutex(hConnectionHeaderMutex); - return 1; - } - InterlockedIncrement(&nlc->dontCloseNow); - ResetEvent(nlc->hOkToCloseEvent); - ReleaseMutex(hConnectionHeaderMutex); - WaitForSingleObject(nlncs->hMutex, INFINITE); - nlncs->dwOwningThreadId = dwCurrentThreadId; - nlncs->lockCount = 1; - if (InterlockedDecrement(&nlc->dontCloseNow) == 0) - SetEvent(nlc->hOkToCloseEvent); - return 1; -} - -void NetlibLeaveNestedCS(NetlibNestedCriticalSection *nlncs) -{ - if (--nlncs->lockCount == 0) { - nlncs->dwOwningThreadId = 0; - ReleaseMutex(nlncs->hMutex); - } -} - -static INT_PTR GetNetlibUserSettingInt(const char *szUserModule, const char *szSetting, int defValue) -{ - DBVARIANT dbv; - if (db_get(NULL, szUserModule, szSetting, &dbv) && db_get(NULL, "Netlib", szSetting, &dbv)) - return defValue; - - if (dbv.type == DBVT_BYTE) return dbv.bVal; - if (dbv.type == DBVT_WORD) return dbv.wVal; - return dbv.dVal; -} - -static char *GetNetlibUserSettingString(const char *szUserModule, const char *szSetting) -{ - char *szRet = db_get_sa(NULL, szUserModule, szSetting); - if (szRet == NULL) - if ((szRet = db_get_sa(NULL, "Netlib", szSetting)) == NULL) - return NULL; - - return szRet; -} - -static INT_PTR NetlibRegisterUser(WPARAM, LPARAM lParam) -{ - NETLIBUSER *nlu = (NETLIBUSER*)lParam; - if (nlu == NULL || nlu->cbSize != sizeof(NETLIBUSER) || nlu->szSettingsModule == NULL || - (!(nlu->flags & NUF_NOOPTIONS) && nlu->szDescriptiveName == NULL) || - (nlu->flags & NUF_HTTPGATEWAY && (nlu->pfnHttpGatewayInit == NULL))) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - NetlibUser *thisUser = (NetlibUser*)mir_calloc(sizeof(NetlibUser)); - thisUser->handleType = NLH_USER; - thisUser->user = *nlu; - - int idx; - { - mir_cslock lck(csNetlibUser); - idx = netlibUser.getIndex(thisUser); - } - if (idx != -1) { - mir_free(thisUser); - SetLastError(ERROR_DUP_NAME); - return 0; - } - - if (nlu->szDescriptiveName) - thisUser->user.ptszDescriptiveName = (thisUser->user.flags&NUF_UNICODE ? mir_u2t((WCHAR*)nlu->ptszDescriptiveName) : mir_a2t(nlu->szDescriptiveName)); - - if ((thisUser->user.szSettingsModule = mir_strdup(nlu->szSettingsModule)) == NULL - || (nlu->szDescriptiveName && thisUser->user.ptszDescriptiveName == NULL) - || (nlu->szHttpGatewayUserAgent && (thisUser->user.szHttpGatewayUserAgent = mir_strdup(nlu->szHttpGatewayUserAgent)) == NULL)) - { - mir_free(thisUser); - SetLastError(ERROR_OUTOFMEMORY); - return 0; - } - if (nlu->szHttpGatewayHello) - thisUser->user.szHttpGatewayHello = mir_strdup(nlu->szHttpGatewayHello); - else - thisUser->user.szHttpGatewayHello = NULL; - - thisUser->settings.cbSize = sizeof(NETLIBUSERSETTINGS); - thisUser->settings.useProxy = GetNetlibUserSettingInt(thisUser->user.szSettingsModule, "NLUseProxy", 0); - thisUser->settings.proxyType = GetNetlibUserSettingInt(thisUser->user.szSettingsModule, "NLProxyType", PROXYTYPE_SOCKS5); - if (thisUser->user.flags&NUF_NOHTTPSOPTION && thisUser->settings.proxyType == PROXYTYPE_HTTPS) - thisUser->settings.proxyType = PROXYTYPE_HTTP; - if (!(thisUser->user.flags&(NUF_HTTPCONNS|NUF_HTTPGATEWAY)) && thisUser->settings.proxyType == PROXYTYPE_HTTP) { - thisUser->settings.useProxy = 0; - thisUser->settings.proxyType = PROXYTYPE_SOCKS5; - } - thisUser->settings.szProxyServer = GetNetlibUserSettingString(thisUser->user.szSettingsModule, "NLProxyServer"); - thisUser->settings.wProxyPort = GetNetlibUserSettingInt(thisUser->user.szSettingsModule, "NLProxyPort", 1080); - thisUser->settings.useProxyAuth = GetNetlibUserSettingInt(thisUser->user.szSettingsModule, "NLUseProxyAuth", 0); - thisUser->settings.szProxyAuthUser = GetNetlibUserSettingString(thisUser->user.szSettingsModule, "NLProxyAuthUser"); - thisUser->settings.szProxyAuthPassword = GetNetlibUserSettingString(thisUser->user.szSettingsModule, "NLProxyAuthPassword"); - thisUser->settings.dnsThroughProxy = GetNetlibUserSettingInt(thisUser->user.szSettingsModule, "NLDnsThroughProxy", 1); - thisUser->settings.specifyIncomingPorts = GetNetlibUserSettingInt(thisUser->user.szSettingsModule, "NLSpecifyIncomingPorts", 0); - thisUser->settings.szIncomingPorts = GetNetlibUserSettingString(thisUser->user.szSettingsModule, "NLIncomingPorts"); - thisUser->settings.specifyOutgoingPorts = GetNetlibUserSettingInt(thisUser->user.szSettingsModule, "NLSpecifyOutgoingPorts", 0); - thisUser->settings.szOutgoingPorts = GetNetlibUserSettingString(thisUser->user.szSettingsModule, "NLOutgoingPorts"); - thisUser->settings.enableUPnP = GetNetlibUserSettingInt(thisUser->user.szSettingsModule, "NLEnableUPnP", 1); //default to on - thisUser->settings.validateSSL = GetNetlibUserSettingInt(thisUser->user.szSettingsModule, "NLValidateSSL", 0); - - thisUser->toLog = GetNetlibUserSettingInt(thisUser->user.szSettingsModule, "NLlog", 1); - - mir_cslock lck(csNetlibUser); - netlibUser.insert(thisUser); - return (INT_PTR)thisUser; -} - -static INT_PTR NetlibGetUserSettings(WPARAM wParam, LPARAM lParam) -{ - NETLIBUSERSETTINGS *nlus = (NETLIBUSERSETTINGS*)lParam; - NetlibUser *nlu = (NetlibUser*)wParam; - - if (GetNetlibHandleType(nlu) != NLH_USER || nlus == NULL || nlus->cbSize != sizeof(NETLIBUSERSETTINGS)) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - *nlus = nlu->settings; - return 1; -} - -static INT_PTR NetlibSetUserSettings(WPARAM wParam, LPARAM lParam) -{ - NETLIBUSERSETTINGS *nlus = (NETLIBUSERSETTINGS*)lParam; - NetlibUser *nlu = (NetlibUser*)wParam; - - if (GetNetlibHandleType(nlu) != NLH_USER || nlus == NULL || nlus->cbSize != sizeof(NETLIBUSERSETTINGS)) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - NetlibSaveUserSettingsStruct(nlu->user.szSettingsModule, nlus); - return 1; -} - -void NetlibDoClose(NetlibConnection *nlc, bool noShutdown) -{ - if (nlc->s == INVALID_SOCKET) return; - - NetlibLogf(nlc->nlu, "(%p:%u) Connection closed internal", nlc, nlc->s); - if (nlc->hSsl) { - if (!noShutdown) si.shutdown(nlc->hSsl); - si.sfree(nlc->hSsl); - nlc->hSsl = NULL; - } - closesocket(nlc->s); - nlc->s = INVALID_SOCKET; -} - -INT_PTR NetlibCloseHandle(WPARAM wParam, LPARAM) -{ - if (wParam == NULL) - return 0; - - switch(GetNetlibHandleType((void*)wParam)) { - case NLH_USER: - { - NetlibUser *nlu = (NetlibUser*)wParam; - { - mir_cslock lck(csNetlibUser); - int i = netlibUser.getIndex(nlu); - if (i >= 0) - netlibUser.remove(i); - } - - NetlibFreeUserSettingsStruct(&nlu->settings); - mir_free(nlu->user.szSettingsModule); - mir_free(nlu->user.szDescriptiveName); - mir_free(nlu->user.szHttpGatewayHello); - mir_free(nlu->user.szHttpGatewayUserAgent); - mir_free(nlu->szStickyHeaders); - break; - } - case NLH_CONNECTION: - { - NetlibConnection *nlc = (struct NetlibConnection*)wParam; - HANDLE waitHandles[4]; - DWORD waitResult; - - WaitForSingleObject(hConnectionHeaderMutex, INFINITE); - if (nlc->usingHttpGateway) - HttpGatewayRemovePacket(nlc, -1); - else { - if (nlc->s != INVALID_SOCKET) - NetlibDoClose(nlc, nlc->termRequested); - if (nlc->s2 != INVALID_SOCKET) closesocket(nlc->s2); - nlc->s2 = INVALID_SOCKET; - } - ReleaseMutex(hConnectionHeaderMutex); - - waitHandles[0] = hConnectionHeaderMutex; - waitHandles[1] = nlc->hOkToCloseEvent; - waitHandles[2] = nlc->ncsRecv.hMutex; - waitHandles[3] = nlc->ncsSend.hMutex; - waitResult = WaitForMultipleObjects(SIZEOF(waitHandles), waitHandles, TRUE, INFINITE); - if (waitResult >= WAIT_OBJECT_0 + SIZEOF(waitHandles)) { - ReleaseMutex(hConnectionHeaderMutex); - SetLastError(ERROR_INVALID_PARAMETER); //already been closed - return 0; - } - nlc->handleType = 0; - mir_free(nlc->nlhpi.szHttpPostUrl); - mir_free(nlc->nlhpi.szHttpGetUrl); - mir_free(nlc->dataBuffer); - mir_free((char*)nlc->nloc.szHost); - mir_free(nlc->szNewUrl); - mir_free(nlc->szProxyServer); - NetlibDeleteNestedCS(&nlc->ncsRecv); - NetlibDeleteNestedCS(&nlc->ncsSend); - CloseHandle(nlc->hOkToCloseEvent); - DeleteCriticalSection(&nlc->csHttpSequenceNums); - ReleaseMutex(hConnectionHeaderMutex); - NetlibLogf(nlc->nlu, "(%p:%u) Connection closed", nlc, nlc->s); - } - break; - - case NLH_BOUNDPORT: - return NetlibFreeBoundPort((struct NetlibBoundPort*)wParam); - - case NLH_PACKETRECVER: - { - struct NetlibPacketRecver *nlpr = (struct NetlibPacketRecver*)wParam; - mir_free(nlpr->packetRecver.buffer); - } - break; - - default: - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - mir_free((void*)wParam); - return 1; -} - -static INT_PTR NetlibGetSocket(WPARAM wParam, LPARAM) -{ - SOCKET s; - if (wParam == 0) { - s = INVALID_SOCKET; - SetLastError(ERROR_INVALID_PARAMETER); - } - else { - WaitForSingleObject(hConnectionHeaderMutex, INFINITE); - switch (GetNetlibHandleType((void*)wParam)) { - case NLH_CONNECTION: - s = ((struct NetlibConnection*)wParam)->s; - break; - case NLH_BOUNDPORT: - s = ((struct NetlibBoundPort*)wParam)->s; - break; - default: - s = INVALID_SOCKET; - SetLastError(ERROR_INVALID_PARAMETER); - break; - } - ReleaseMutex(hConnectionHeaderMutex); - } - return s; -} - -INT_PTR NetlibStringToAddressSrv(WPARAM wParam, LPARAM lParam) -{ - return (INT_PTR)!NetlibStringToAddress((char*)wParam, (SOCKADDR_INET_M*)lParam); -} - -INT_PTR NetlibAddressToStringSrv(WPARAM wParam, LPARAM lParam) -{ - if (wParam) { - SOCKADDR_INET_M iaddr = {0}; - iaddr.Ipv4.sin_family = AF_INET; - iaddr.Ipv4.sin_addr.s_addr = htonl((unsigned)lParam); - return (INT_PTR)NetlibAddressToString(&iaddr); - } - return (INT_PTR)NetlibAddressToString((SOCKADDR_INET_M*)lParam); -} - -INT_PTR NetlibGetConnectionInfoSrv(WPARAM wParam, LPARAM lParam) -{ - NetlibGetConnectionInfo((NetlibConnection*)wParam, (NETLIBCONNINFO*)lParam); - return 0; -} - -INT_PTR NetlibGetMyIp(WPARAM wParam, LPARAM) -{ - return (INT_PTR)GetMyIp((unsigned)wParam); -} - -INT_PTR NetlibShutdown(WPARAM wParam, LPARAM) -{ - if (wParam) { - WaitForSingleObject(hConnectionHeaderMutex, INFINITE); - switch(GetNetlibHandleType((void*)wParam)) { - case NLH_CONNECTION: - { - NetlibConnection *nlc = (NetlibConnection*)wParam; - if (!nlc->termRequested) { - if (nlc->hSsl) si.shutdown(nlc->hSsl); - if (nlc->s != INVALID_SOCKET) shutdown(nlc->s, 2); - if (nlc->s2 != INVALID_SOCKET) shutdown(nlc->s2, 2); - nlc->termRequested = true; - } - } - break; - - case NLH_BOUNDPORT: - struct NetlibBoundPort* nlb = (struct NetlibBoundPort*)wParam; - if (nlb->s != INVALID_SOCKET) - shutdown(nlb->s, 2); - break; - } - ReleaseMutex(hConnectionHeaderMutex); - } - return 0; -} - -void UnloadNetlibModule(void) -{ - if (!bModuleInitialized || hConnectionHeaderMutex == NULL) return; - - NetlibUnloadIeProxy(); - NetlibUPnPDestroy(); - NetlibLogShutdown(); - - DestroyHookableEvent(hRecvEvent); hRecvEvent = NULL; - DestroyHookableEvent(hSendEvent); hSendEvent = NULL; - - for (int i = netlibUser.getCount(); i > 0; i--) - NetlibCloseHandle((WPARAM)netlibUser[i-1], 0); - - CloseHandle(hConnectionHeaderMutex); - if (hConnectionOpenMutex) - CloseHandle(hConnectionOpenMutex); - WSACleanup(); -} - -int LoadNetlibModule(void) -{ - WSADATA wsadata; - - bModuleInitialized = TRUE; - - WSAStartup(MAKEWORD(2, 2), &wsadata); - - HookEvent(ME_OPT_INITIALISE, NetlibOptInitialise); - - hConnectionHeaderMutex = CreateMutex(NULL, FALSE, NULL); - NetlibLogInit(); - - connectionTimeout = 0; - - OSVERSIONINFOEX osvi = {0}; - osvi.dwOSVersionInfoSize = sizeof(osvi); - if (GetVersionEx((LPOSVERSIONINFO)&osvi)) { - // Connection limiting was introduced in Windows XP SP2 and later and set to 10 / sec - if (osvi.dwMajorVersion == 5 && ((osvi.dwMinorVersion == 1 && osvi.wServicePackMajor >= 2) || osvi.dwMinorVersion > 1)) - connectionTimeout = 150; - // Connection limiting has limits based on addition Windows Vista pre SP2 - else if (osvi.dwMajorVersion == 6 && osvi.wServicePackMajor < 2) { - DWORD dwType = 0; - tGetProductInfo pGetProductInfo = (tGetProductInfo) GetProcAddress(GetModuleHandleA("kernel32"), "GetProductInfo"); - if (pGetProductInfo != NULL) pGetProductInfo(6, 0, 0, 0, &dwType); - switch(dwType) { - case 0x01: // Vista Ultimate edition have connection limit of 25 / sec - plenty for Miranda - case 0x1c: - break; - - case 0x02: // Vista Home Basic edition have connection limit of 2 / sec - case 0x05: - connectionTimeout = 1000; - break; - - default: // all other editions have connection limit of 10 / sec - connectionTimeout = 150; - break; - } - } - // Connection limiting is disabled by default and is controlled by registry setting in Windows Vista SP2 and later - else if (osvi.dwMajorVersion >= 6) { - static const char keyn[] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"; - static const char valn[] = "EnableConnectionRateLimiting"; - - HKEY hSettings; - if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyn, 0, KEY_QUERY_VALUE, &hSettings) == ERROR_SUCCESS) { - DWORD tValueLen, enabled; - tValueLen = sizeof(enabled); - if (RegQueryValueExA(hSettings, valn, NULL, NULL, (BYTE*)&enabled, &tValueLen) == ERROR_SUCCESS && enabled) - connectionTimeout = 150; // if enabled limit is set to 10 / sec - RegCloseKey(hSettings); - } - } - } - - hConnectionOpenMutex = connectionTimeout ? CreateMutex(NULL, FALSE, NULL) : NULL; - g_LastConnectionTick = GetTickCount(); - - CreateServiceFunction(MS_NETLIB_REGISTERUSER, NetlibRegisterUser); - CreateServiceFunction(MS_NETLIB_GETUSERSETTINGS, NetlibGetUserSettings); - CreateServiceFunction(MS_NETLIB_SETUSERSETTINGS, NetlibSetUserSettings); - CreateServiceFunction(MS_NETLIB_CLOSEHANDLE, NetlibCloseHandle); - CreateServiceFunction(MS_NETLIB_BINDPORT, NetlibBindPort); - CreateServiceFunction(MS_NETLIB_OPENCONNECTION, NetlibOpenConnection); - CreateServiceFunction(MS_NETLIB_SETHTTPPROXYINFO, NetlibHttpGatewaySetInfo); - CreateServiceFunction(MS_NETLIB_SETSTICKYHEADERS, NetlibHttpSetSticky); - CreateServiceFunction(MS_NETLIB_GETSOCKET, NetlibGetSocket); - CreateServiceFunction(MS_NETLIB_SENDHTTPREQUEST, NetlibHttpSendRequest); - CreateServiceFunction(MS_NETLIB_RECVHTTPHEADERS, NetlibHttpRecvHeaders); - CreateServiceFunction(MS_NETLIB_FREEHTTPREQUESTSTRUCT, NetlibHttpFreeRequestStruct); - CreateServiceFunction(MS_NETLIB_HTTPTRANSACTION, NetlibHttpTransaction); - CreateServiceFunction(MS_NETLIB_SEND, NetlibSend); - CreateServiceFunction(MS_NETLIB_RECV, NetlibRecv); - CreateServiceFunction(MS_NETLIB_SELECT, NetlibSelect); - CreateServiceFunction(MS_NETLIB_SELECTEX, NetlibSelectEx); - CreateServiceFunction(MS_NETLIB_SHUTDOWN, NetlibShutdown); - CreateServiceFunction(MS_NETLIB_CREATEPACKETRECVER, NetlibPacketRecverCreate); - CreateServiceFunction(MS_NETLIB_GETMOREPACKETS, NetlibPacketRecverGetMore); - CreateServiceFunction(MS_NETLIB_SETPOLLINGTIMEOUT, NetlibHttpSetPollingTimeout); - CreateServiceFunction(MS_NETLIB_STARTSSL, NetlibStartSsl); - CreateServiceFunction(MS_NETLIB_STRINGTOADDRESS, NetlibStringToAddressSrv); - CreateServiceFunction(MS_NETLIB_ADDRESSTOSTRING, NetlibAddressToStringSrv); - CreateServiceFunction(MS_NETLIB_GETCONNECTIONINFO, NetlibGetConnectionInfoSrv); - CreateServiceFunction(MS_NETLIB_GETMYIP, NetlibGetMyIp); - - hRecvEvent = CreateHookableEvent(ME_NETLIB_FASTRECV); - hSendEvent = CreateHookableEvent(ME_NETLIB_FASTSEND); - - NetlibUPnPInit(); - NetlibSecurityInit(); - NetlibLoadIeProxy(); - return 0; -} diff --git a/src/modules/netlib/netlib.h b/src/modules/netlib/netlib.h deleted file mode 100644 index 949d1755b2..0000000000 --- a/src/modules/netlib/netlib.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#define NLH_INVALID 0 -#define NLH_USER 'USER' -#define NLH_CONNECTION 'CONN' -#define NLH_BOUNDPORT 'BIND' -#define NLH_PACKETRECVER 'PCKT' -int GetNetlibHandleType(void*); - -struct NetlibUser -{ - int handleType; - NETLIBUSER user; - NETLIBUSERSETTINGS settings; - char * szStickyHeaders; - int toLog; - int inportnum; - int outportnum; -}; - -struct NetlibNestedCriticalSection -{ - HANDLE hMutex; - DWORD dwOwningThreadId; - int lockCount; -}; - -struct NetlibHTTPProxyPacketQueue -{ - NetlibHTTPProxyPacketQueue *next; - PBYTE dataBuffer; - int dataBufferLen; -}; - -typedef union _SOCKADDR_INET_M { - SOCKADDR_IN Ipv4; - SOCKADDR_IN6 Ipv6; - USHORT si_family; -} SOCKADDR_INET_M, *PSOCKADDR_INET_M; - -struct NetlibConnection -{ - int handleType; - SOCKET s, s2; - bool usingHttpGateway; - bool usingDirectHttpGateway; - bool proxyAuthNeeded; - bool dnsThroughProxy; - bool termRequested; - NetlibUser *nlu; - NETLIBHTTPPROXYINFO nlhpi; - PBYTE dataBuffer; - int dataBufferLen; - CRITICAL_SECTION csHttpSequenceNums; - HANDLE hOkToCloseEvent; - LONG dontCloseNow; - NetlibNestedCriticalSection ncsSend, ncsRecv; - HSSL hSsl; - NetlibHTTPProxyPacketQueue * pHttpProxyPacketQueue; - char *szNewUrl; - char *szProxyServer; - WORD wProxyPort; - int proxyType; - int pollingTimeout; - unsigned lastPost; - NETLIBOPENCONNECTION nloc; -}; - -struct NetlibBoundPort { - int handleType; - SOCKET s; - SOCKET s6; - WORD wPort; - WORD wExPort; - NetlibUser *nlu; - NETLIBNEWCONNECTIONPROC_V2 pfnNewConnectionV2; - HANDLE hThread; - void *pExtra; -}; - -struct NetlibPacketRecver { - int handleType; - NetlibConnection *nlc; - NETLIBPACKETRECVER packetRecver; -}; - -//netlib.c -void NetlibFreeUserSettingsStruct(NETLIBUSERSETTINGS *settings); -void NetlibDoClose(NetlibConnection *nlc, bool noShutdown = false); -INT_PTR NetlibCloseHandle(WPARAM wParam, LPARAM lParam); -void NetlibInitializeNestedCS(NetlibNestedCriticalSection *nlncs); -void NetlibDeleteNestedCS(NetlibNestedCriticalSection *nlncs); -#define NLNCS_SEND 0 -#define NLNCS_RECV 1 -int NetlibEnterNestedCS(NetlibConnection *nlc, int which); -void NetlibLeaveNestedCS(NetlibNestedCriticalSection *nlncs); -INT_PTR NetlibBase64Encode(WPARAM wParam, LPARAM lParam); -INT_PTR NetlibBase64Decode(WPARAM wParam, LPARAM lParam); -INT_PTR NetlibHttpUrlEncode(WPARAM wParam, LPARAM lParam); - -extern mir_cs csNetlibUser; -extern LIST netlibUser; - -//netlibautoproxy.c -void NetlibLoadIeProxy(void); -void NetlibUnloadIeProxy(void); -char* NetlibGetIeProxy(char *szUrl); -bool NetlibGetIeProxyConn(NetlibConnection *nlc, bool forceHttps); - -//netlibbind.c -int NetlibFreeBoundPort(NetlibBoundPort *nlbp); -INT_PTR NetlibBindPort(WPARAM wParam, LPARAM lParam); -bool BindSocketToPort(const char *szPorts, SOCKET s, SOCKET s6, int* portn); - -//netlibhttp.c -INT_PTR NetlibHttpSendRequest(WPARAM wParam, LPARAM lParam); -INT_PTR NetlibHttpRecvHeaders(WPARAM wParam, LPARAM lParam); -INT_PTR NetlibHttpFreeRequestStruct(WPARAM wParam, LPARAM lParam); -INT_PTR NetlibHttpTransaction(WPARAM wParam, LPARAM lParam); -void NetlibHttpSetLastErrorUsingHttpResult(int result); -NETLIBHTTPREQUEST* NetlibHttpRecv(NetlibConnection* nlc, DWORD hflags, DWORD dflags, bool isConnect = false); -void NetlibConnFromUrl(const char* szUrl, bool secur, NETLIBOPENCONNECTION &nloc); - -//netlibhttpproxy.c -int NetlibInitHttpConnection(NetlibConnection *nlc, NetlibUser *nlu, NETLIBOPENCONNECTION *nloc); -int NetlibHttpGatewayRecv(NetlibConnection *nlc, char *buf, int len, int flags); -int NetlibHttpGatewayPost(NetlibConnection *nlc, const char *buf, int len, int flags); -void HttpGatewayRemovePacket(NetlibConnection *nlc, int pck); - -INT_PTR NetlibHttpGatewaySetInfo(WPARAM wParam, LPARAM lParam); -INT_PTR NetlibHttpSetPollingTimeout(WPARAM wParam, LPARAM lParam); -INT_PTR NetlibHttpSetSticky(WPARAM wParam, LPARAM lParam); - -//netliblog.c -void NetlibLogShowOptions(void); -void NetlibDumpData(NetlibConnection *nlc, PBYTE buf, int len, int sent, int flags); -void NetlibLogf(NetlibUser* nlu, const char *fmt, ...); -void NetlibLogInit(void); -void NetlibLogShutdown(void); - -//netlibopenconn.c -DWORD DnsLookup(NetlibUser *nlu, const char *szHost); -int WaitUntilReadable(SOCKET s, DWORD dwTimeout, bool check = false); -int WaitUntilWritable(SOCKET s, DWORD dwTimeout); -bool NetlibDoConnect(NetlibConnection *nlc); -bool NetlibReconnect(NetlibConnection *nlc); -INT_PTR NetlibOpenConnection(WPARAM wParam, LPARAM lParam); -INT_PTR NetlibStartSsl(WPARAM wParam, LPARAM lParam); - -//netlibopts.c -int NetlibOptInitialise(WPARAM wParam, LPARAM lParam); -void NetlibSaveUserSettingsStruct(const char *szSettingsModule, NETLIBUSERSETTINGS *settings); - -//netlibpktrecver.c -INT_PTR NetlibPacketRecverCreate(WPARAM wParam, LPARAM lParam); -INT_PTR NetlibPacketRecverGetMore(WPARAM wParam, LPARAM lParam); - -//netlibsock.c -#define NL_SELECT_READ 0x0001 -#define NL_SELECT_WRITE 0x0002 -#define NL_SELECT_ALL (NL_SELECT_READ+NL_SELECT_WRITE) - -INT_PTR NetlibSend(WPARAM wParam, LPARAM lParam); -INT_PTR NetlibRecv(WPARAM wParam, LPARAM lParam); -INT_PTR NetlibSelect(WPARAM wParam, LPARAM lParam); -INT_PTR NetlibSelectEx(WPARAM wParam, LPARAM lParam); -INT_PTR NetlibShutdown(WPARAM wParam, LPARAM lParam); - -bool NetlibStringToAddress(const char* str, SOCKADDR_INET_M* addr); -char* NetlibAddressToString(SOCKADDR_INET_M* addr); -void NetlibGetConnectionInfo(NetlibConnection* nlc, NETLIBCONNINFO *connInfo); -NETLIBIPLIST* GetMyIp(unsigned flags); - -//netlibupnp.c -bool NetlibUPnPAddPortMapping(WORD intport, char *proto, - WORD *extport, DWORD *extip, bool search); -void NetlibUPnPDeletePortMapping(WORD extport, char* proto); -void NetlibUPnPCleanup(void*); -void NetlibUPnPInit(void); -void NetlibUPnPDestroy(void); - -//netlibsecurity.c -void NetlibSecurityInit(void); -void NetlibDestroySecurityProvider(HANDLE hSecurity); -HANDLE NetlibInitSecurityProvider(const TCHAR* szProvider, const TCHAR* szPrincipal); -HANDLE NetlibInitSecurityProvider(const char* szProvider, const char* szPrincipal); -char* NtlmCreateResponseFromChallenge(HANDLE hSecurity, const char *szChallenge, const TCHAR* login, const TCHAR* psw, - bool http, unsigned& complete); - -static __inline INT_PTR NLSend(NetlibConnection *nlc, const char *buf, int len, int flags) { - NETLIBBUFFER nlb = {(char*)buf, len, flags}; - return NetlibSend((WPARAM)nlc, (LPARAM)&nlb); -} - -static __inline INT_PTR NLRecv(NetlibConnection *nlc, char *buf, int len, int flags) { - NETLIBBUFFER nlb = {buf, len, flags}; - return NetlibRecv((WPARAM)nlc, (LPARAM)&nlb); -} diff --git a/src/modules/netlib/netlibautoproxy.cpp b/src/modules/netlib/netlibautoproxy.cpp deleted file mode 100644 index 6410c49e74..0000000000 --- a/src/modules/netlib/netlibautoproxy.cpp +++ /dev/null @@ -1,453 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "..\..\core\commonheaders.h" -#include "netlib.h" - -#include - -/* -///////////////////////////////////////////////////////////////////// -// ResolveHostName (a helper function) -///////////////////////////////////////////////////////////////////// -DWORD __stdcall ResolveHostName(LPSTR lpszHostName, - LPSTR lpszIPAddress, LPDWORD lpdwIPAddressSize) -{ - if (*lpdwIPAddressSize < 17 || lpszIPAddress == NULL) - { - *lpdwIPAddressSize = 17; - return ERROR_INSUFFICIENT_BUFFER; - } - - IN_ADDR ip; - ip.s_addr = inet_addr(lpszHostName); - if (ip.s_addr == INADDR_NONE) - { - PHOSTENT myhost = gethostbyname(lpszHostName); - if (myhost != NULL) - ip = *(PIN_ADDR)myhost->h_addr; - else - return SOCKET_ERROR; - } - mir_snprintf(lpszIPAddress, *lpdwIPAddressSize, "%u.%u.%u.%u", - ip.s_net, ip.s_host, ip.s_lh, ip.s_impno); - - return 0; -} - -///////////////////////////////////////////////////////////////////// -// IsResolvable (a helper function) -///////////////////////////////////////////////////////////////////// -BOOL __stdcall IsResolvable(LPSTR lpszHost) -{ - char szDummy[255]; - DWORD dwDummySize = sizeof (szDummy) - 1; - - if (ResolveHostName(lpszHost, szDummy, &dwDummySize)) - return FALSE; - return TRUE; -} - -///////////////////////////////////////////////////////////////////// -// GetIPAddress (a helper function) -///////////////////////////////////////////////////////////////////// -DWORD __stdcall GetIPAddress(LPSTR lpszIPAddress, LPDWORD lpdwIPAddressSize) -{ - char szHostBuffer[255]; - - if (gethostname(szHostBuffer, sizeof (szHostBuffer) - 1) != ERROR_SUCCESS) - return (ERROR_INTERNET_INTERNAL_ERROR); - return (ResolveHostName(szHostBuffer, lpszIPAddress, lpdwIPAddressSize)); -} - -///////////////////////////////////////////////////////////////////// -// IsInNet (a helper function) -///////////////////////////////////////////////////////////////////// -BOOL __stdcall IsInNet(LPSTR lpszIPAddress, LPSTR lpszDest, LPSTR lpszMask) -{ - DWORD dwDest; - DWORD dwIpAddr; - DWORD dwMask; - - dwIpAddr = inet_addr(lpszIPAddress); - dwDest = inet_addr(lpszDest); - dwMask = inet_addr(lpszMask); - - if ((dwDest == INADDR_NONE) || - (dwIpAddr == INADDR_NONE) || ((dwIpAddr & dwMask) != dwDest)) - return (FALSE); - - return (TRUE); -} - -static const AutoProxyHelperVtbl OurVtbl = -{ - IsResolvable, - GetIPAddress, - ResolveHostName, - IsInNet, - NULL, - NULL, - NULL, - NULL -}; - -static AutoProxyHelperFunctions HelperFunctions = { &OurVtbl }; -*/ - -static char *szProxyHost[3]; -static LIST proxyBypass(5); - -static HMODULE hModJS; - -static pfnInternetInitializeAutoProxyDll pInternetInitializeAutoProxyDll; -static pfnInternetDeInitializeAutoProxyDll pInternetDeInitializeAutoProxyDll; -static pfnInternetGetProxyInfo pInternetGetProxyInfo; - -static bool bEnabled, bOneProxy; - -static void GetFile(char* szUrl, AUTO_PROXY_SCRIPT_BUFFER &buf) -{ - NetlibUser nlu = {0}; - NETLIBHTTPREQUEST nlhr = {0}; - - nlu.handleType = NLH_USER; - nlu.user.flags = NUF_OUTGOING | NUF_HTTPCONNS; - nlu.user.szSettingsModule = "(NULL)"; - nlu.toLog = 1; - - // initialize the netlib request - nlhr.cbSize = sizeof(nlhr); - nlhr.requestType = REQUEST_GET; - nlhr.flags = NLHRF_HTTP11 | NLHRF_DUMPASTEXT | NLHRF_REDIRECT; - nlhr.szUrl = szUrl; - - // download the page - NETLIBHTTPREQUEST *nlhrReply = (NETLIBHTTPREQUEST*)NetlibHttpTransaction((WPARAM)&nlu, (LPARAM)&nlhr); - - if (nlhrReply) - { - if (nlhrReply->resultCode == 200) - { - buf.lpszScriptBuffer = nlhrReply->pData; - buf.dwScriptBufferSize = nlhrReply->dataLength + 1; - - nlhrReply->dataLength = 0; - nlhrReply->pData = NULL; - } - CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply); - } -} - -bool NetlibGetIeProxyConn(NetlibConnection *nlc, bool forceHttps) -{ - bool noHttp = false; - bool usingSsl = false; - char szUrl[256]; - - if ((nlc->nloc.flags & (NLOCF_HTTP | NLOCF_HTTPGATEWAY) && nlc->nloc.flags & NLOCF_SSL) || - nlc->nloc.wPort == 443 || forceHttps) - { - mir_snprintf(szUrl, "https://%s", nlc->nloc.szHost); - usingSsl = true; - } - else if (nlc->nloc.flags & (NLOCF_HTTPGATEWAY | NLOCF_HTTP) || nlc->usingHttpGateway) - mir_snprintf(szUrl, "http://%s", nlc->nloc.szHost); - else - { - strncpy_s(szUrl, nlc->nloc.szHost, _TRUNCATE); - noHttp = true; - } - - mir_free(nlc->szProxyServer); nlc->szProxyServer = NULL; - nlc->wProxyPort = 0; - nlc->proxyType = 0; - - char *mt = NetlibGetIeProxy(szUrl); - char *m = NEWSTR_ALLOCA(mt); - mir_free(mt); - - if (m == NULL) return false; - - // if multiple servers, use the first one - char *c = strchr(m, ';'); if (c) *c = 0; - - // if 'direct' no proxy - if (_stricmp(lrtrim(m), "direct") == 0) return false; - - // find proxy address - char *h = strchr(m, ' '); - if (h) { *h = 0; ++h; } else return false; - - // find proxy port - char *p = strchr(h, ':'); - if (p) { *p = 0; ++p; } - - lrtrim(h); ltrim(p); - if (_stricmp(m, "proxy") == 0 && h[0]) - { - nlc->proxyType = (usingSsl || noHttp) ? PROXYTYPE_HTTPS : PROXYTYPE_HTTP; - nlc->wProxyPort = p ? atol(p) : 8080; - nlc->szProxyServer = mir_strdup(h); - } - else if (_stricmp(m, "socks") == 0 && h[0]) - { - nlc->proxyType = PROXYTYPE_SOCKS4; - nlc->wProxyPort = p ? atol(p) : 1080; - nlc->szProxyServer = mir_strdup(h); - } - else if (_stricmp(m, "socks5") == 0 && h[0]) - { - nlc->proxyType = PROXYTYPE_SOCKS5; - nlc->wProxyPort = p ? atol(p) : 1080; - nlc->szProxyServer = mir_strdup(h); - } - else - return false; - - return true; -} - -static char szAutoUrlStr[MAX_PATH] = ""; -static AUTO_PROXY_SCRIPT_BUFFER abuf = {0}; -static HANDLE hIeProxyMutex; -static bool bAutoProxyInit; - -static void NetlibInitAutoProxy(void) -{ - if (bAutoProxyInit) return; - - if (!hModJS) - { - if (!(hModJS = LoadLibraryA("jsproxy.dll"))) - return; - - pInternetInitializeAutoProxyDll = (pfnInternetInitializeAutoProxyDll) - GetProcAddress(hModJS, "InternetInitializeAutoProxyDll"); - - pInternetDeInitializeAutoProxyDll = (pfnInternetDeInitializeAutoProxyDll) - GetProcAddress(hModJS, "InternetDeInitializeAutoProxyDll"); - - pInternetGetProxyInfo = (pfnInternetGetProxyInfo) - GetProcAddress(hModJS, "InternetGetProxyInfo"); - } - - if (strstr(szAutoUrlStr, "file://") == NULL && strstr(szAutoUrlStr, "://") != NULL) - { - abuf.dwStructSize = sizeof(abuf); - GetFile(szAutoUrlStr, abuf); - } - bAutoProxyInit = true; -} - -struct IeProxyParam -{ - char *szUrl; - char *szHost; - char *szProxy; -}; - -static void NetlibIeProxyThread(void *arg) -{ - IeProxyParam *param = (IeProxyParam*)arg; - param->szProxy = NULL; - - if (!bAutoProxyInit) { - WaitForSingleObject(hIeProxyMutex, INFINITE); - NetlibInitAutoProxy(); - ReleaseMutex(hIeProxyMutex); - } - - BOOL res; - char *loc = strstr(szAutoUrlStr, "file://"); - if (loc || strstr(szAutoUrlStr, "://") == NULL) { - NetlibLogf(NULL, "Autoproxy Init file: %s", loc); - loc = loc ? loc + 7 : szAutoUrlStr; - res = pInternetInitializeAutoProxyDll(0, loc, NULL, NULL /*&HelperFunctions*/, NULL); - } - else { - NetlibLogf(NULL, "Autoproxy Init %d", abuf.dwScriptBufferSize); - if (abuf.dwScriptBufferSize) - res = pInternetInitializeAutoProxyDll(0, NULL, NULL, NULL /*&HelperFunctions*/, &abuf); - else - res = false; - } - - if (res) { - char proxyBuffer[1024]; - char *proxy = proxyBuffer; - DWORD dwProxyLen = sizeof(proxyBuffer); - - if (pInternetGetProxyInfo(param->szUrl, (DWORD)mir_strlen(param->szUrl), - param->szHost, (DWORD)mir_strlen(param->szHost), &proxy, &dwProxyLen)) - param->szProxy = mir_strdup(lrtrim(proxy)); - - NetlibLogf(NULL, "Autoproxy got response %s, Param: %s %s", param->szProxy, param->szUrl, param->szHost); - pInternetDeInitializeAutoProxyDll(NULL, 0); - } - else NetlibLogf(NULL, "Autoproxy init failed"); -} - -char* NetlibGetIeProxy(char *szUrl) -{ - char *res = NULL; - char* p = strstr(szUrl, "://"); - if (p) p += 3; else p = szUrl; - - char *szHost = NEWSTR_ALLOCA(p); - p = strchr(szHost, '/'); if (p) *p = 0; - p = strchr(szHost, ':'); if (p) *p = 0; - _strlwr(szHost); - - if (bEnabled) - { - for (int i=0; i < proxyBypass.getCount(); i++) - { - if (mir_strcmp(proxyBypass[i], "") == 0) - { - if (strchr(szHost, '.') == NULL) return NULL; - } - else if (wildcmp(szHost, proxyBypass[i])) return NULL; - } - - int ind = -1; - if (strstr(szUrl, "http://")) - ind = szProxyHost[0] ? 0 : 2; - else if (strstr(szUrl, "https://")) - ind = bOneProxy ? 0 : (szProxyHost[1] ? 1 : 2); - else - ind = szProxyHost[2] ? 2 : (bOneProxy ? 0 : (szProxyHost[1] ? 1 : 2)); - - if (ind < 0 || !szProxyHost[ind]) return NULL; - - size_t len = mir_strlen(szHost) + 20; - res = (char*)mir_alloc(len); - mir_snprintf(res, len, "%s %s", ind == 2 ? "SOCKS" : "PROXY", szProxyHost[ind]); - return res; - } - - if (szAutoUrlStr[0]) { - IeProxyParam param = { szUrl, szHost, NULL }; - HANDLE hThread = mir_forkthread(NetlibIeProxyThread, ¶m); - WaitForSingleObject(hThread, INFINITE); - res = param.szProxy; - } - return res; -} - -void NetlibLoadIeProxy(void) -{ - HKEY hSettings; - if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", - 0, KEY_QUERY_VALUE, &hSettings)) - return; - - DWORD tValueLen, enabled = 0; - char szHostStr[256] = "", szProxyBypassStr[4096] = ""; - - tValueLen = sizeof(enabled); - int tResult = RegQueryValueExA(hSettings, "ProxyEnable", NULL, NULL, (BYTE*)&enabled, &tValueLen); - bEnabled = enabled && tResult == ERROR_SUCCESS; - - tValueLen = SIZEOF(szHostStr); - tResult = RegQueryValueExA(hSettings, "ProxyServer", NULL, NULL, (BYTE*)szHostStr, &tValueLen); - bEnabled = bEnabled && tResult == ERROR_SUCCESS; - - tValueLen = SIZEOF(szAutoUrlStr); - RegQueryValueExA(hSettings, "AutoConfigUrl", NULL, NULL, (BYTE*)szAutoUrlStr, &tValueLen); - - tValueLen = SIZEOF(szProxyBypassStr); - RegQueryValueExA(hSettings, "ProxyOverride", NULL, NULL, (BYTE*)szProxyBypassStr, &tValueLen); - - RegCloseKey(hSettings); - - if (bEnabled) - { - char* szProxy = ltrim(szHostStr); - if (szProxy[0] == 0) { enabled = false; return; } - - while(true) - { - char *szProxyEnd = strchr(szProxy, ';'); - if (szProxyEnd) *szProxyEnd = 0; - - int ind = -1; - if (strncmp(szProxy, "http = ", 5) == 0) { ind = 0; szProxy += 5; } - else if (strncmp(szProxy, "https = ", 6) == 0) { ind = 1; szProxy += 6; } - else if (strncmp(szProxy, "socks = ", 6) == 0) { ind = 2; szProxy += 6; } - else if (strchr(szProxy, '=')) ind = -2; - - if (ind != -2) - { - bOneProxy = ind < 0; if (ind < 0) ind = 0; - - lrtrim(szProxy); - - if (strchr(szProxy, ':')) - szProxyHost[ind] = mir_strdup(szProxy); - else - { - size_t len = mir_strlen(szProxy) + 10; - szProxyHost[ind] = (char*)mir_alloc(len); - mir_snprintf(szProxyHost[ind], len, "%s:%u", szProxy, ind == 2 ? 1080 : 8080); - } - if (bOneProxy) break; - } - if (szProxyEnd == NULL) break; - szProxy = szProxyEnd + 1; - } - - char* szProxyBypass = szProxyBypassStr; - while(true) - { - char *szProxyBypassEnd = strchr(szProxyBypass, ';'); - if (szProxyBypassEnd) *szProxyBypassEnd = 0; - - lrtrim(szProxyBypass); - - proxyBypass.insert(_strlwr(mir_strdup(szProxyBypass))); - if (szProxyBypassEnd == NULL) break; - - szProxyBypass = szProxyBypassEnd + 1; - } - } - - if (bEnabled || szAutoUrlStr[0]) - hIeProxyMutex = CreateMutex(NULL, FALSE, NULL); -} - -void NetlibUnloadIeProxy(void) -{ - int i; - - for (i=0; i < 3; i++) - mir_free(szProxyHost[i]); - - for (i=0; i < proxyBypass.getCount(); i++) - mir_free(proxyBypass[i]); - - mir_free(abuf.lpszScriptBuffer); - - CloseHandle(hIeProxyMutex); -} diff --git a/src/modules/netlib/netlibbind.cpp b/src/modules/netlib/netlibbind.cpp deleted file mode 100644 index 699799dd17..0000000000 --- a/src/modules/netlib/netlibbind.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "..\..\core\commonheaders.h" -#include "netlib.h" - -bool BindSocketToPort(const char *szPorts, SOCKET s, SOCKET s6, int* portn) -{ - SOCKADDR_IN sin = {0}; - sin.sin_family = AF_INET; - - SOCKADDR_IN6 sin6 = {0}; - sin6.sin6_family = AF_INET6; - - mir_cslock lck(csNetlibUser); - - if (--*portn < 0 && (s != INVALID_SOCKET || s6 != INVALID_SOCKET)) { - BindSocketToPort(szPorts, INVALID_SOCKET, INVALID_SOCKET, portn); - if (*portn == 0) - return false; - - WORD num; - CallService(MS_UTILS_GETRANDOM, sizeof(WORD), (LPARAM)&num); - *portn = num % *portn; - } - - bool before = false; - while (true) { - const char *psz; - char *pszEnd; - int portMin, portMax, port, portnum = 0; - - for (psz = szPorts;*psz;) { - while (*psz == ' ' || *psz == ',') psz++; - portMin = strtol(psz, &pszEnd, 0); - if (pszEnd == psz) - break; - while (*pszEnd == ' ') - pszEnd++; - if (*pszEnd == '-') { - psz = pszEnd + 1; - portMax = strtol(psz, &pszEnd, 0); - if (pszEnd == psz) portMax = 65535; - if (portMin > portMax) { - port = portMin; - portMin = portMax; - portMax = port; - } - } - else portMax = portMin; - if (portMax >= 1) { - if (portMin <= 0) portMin = 1; - for (port = portMin; port <= portMax; port++) { - if (port > 65535) - break; - - ++portnum; - - if (s == INVALID_SOCKET) continue; - if (!before && portnum <= *portn) continue; - if (before && portnum >= *portn) - return false; - - sin.sin_port = htons((WORD)port); - bool bV4Mapped = s == INVALID_SOCKET || bind(s, (SOCKADDR*)&sin, sizeof(sin)) == 0; - - sin6.sin6_port = htons((WORD)port); - bool bV6Mapped = s6 == INVALID_SOCKET || bind(s6, (PSOCKADDR)&sin6, sizeof(sin6)) == 0; - - if (bV4Mapped && bV6Mapped) { - *portn = portnum + 1; - return true; - } - } - } - psz = pszEnd; - } - - if (*portn < 0) { - *portn = portnum; - return true; - } - - if (*portn >= portnum) - *portn = 0; - else - before = true; - } -} - -int NetlibFreeBoundPort(struct NetlibBoundPort *nlbp) -{ - closesocket(nlbp->s); - closesocket(nlbp->s6); - if (nlbp->hThread) - WaitForSingleObject(nlbp->hThread, INFINITE); - NetlibLogf(nlbp->nlu, "(%u) Port %u closed for incoming connections", nlbp->s, nlbp->wPort); - mir_free(nlbp); - return 1; -} - -static void NetlibBindAcceptThread(void* param) -{ - NetlibBoundPort *nlbp = (NetlibBoundPort*)param; - NetlibLogf(nlbp->nlu, "(%u) Port %u opened for incoming connections", nlbp->s, nlbp->wPort); - - while (true) { - fd_set r; - FD_ZERO(&r); - if (nlbp->s != INVALID_SOCKET) - FD_SET(nlbp->s, &r); - if (nlbp->s6 != INVALID_SOCKET) - FD_SET(nlbp->s6, &r); - if (select(0, &r, NULL, NULL, NULL) == SOCKET_ERROR) { - NetlibLogf(nlbp->nlu, "NetlibBindAcceptThread (%p): select failed (%d)", nlbp->s, GetLastError()); - break; - } - - SOCKADDR_INET_M sin; - int sinLen = sizeof(sin); - memset(&sin, 0, sizeof(sin)); - - SOCKET s; - if (FD_ISSET(nlbp->s, &r)) { - s = accept(nlbp->s, (sockaddr*)&sin, &sinLen); - if (s == INVALID_SOCKET) { - NetlibLogf(nlbp->nlu, "NetlibBindAcceptThread (%p): accept V4 failed (%d)", nlbp->s, GetLastError()); - break; - } - } - else if (FD_ISSET(nlbp->s6, &r)) { - s = accept(nlbp->s6, (sockaddr*)&sin, &sinLen); - if (s == INVALID_SOCKET) { - NetlibLogf(nlbp->nlu, "NetlibBindAcceptThread (%p): accept V6 failed (%d)", nlbp->s, GetLastError()); - break; - } - } - - NetlibLogf(nlbp->nlu, "New incoming connection on port %u from %s (%p)", nlbp->wPort, ptrA(NetlibAddressToString(&sin)), s); - - NetlibConnection *nlc = (NetlibConnection*)mir_calloc(sizeof(NetlibConnection)); - nlc->handleType = NLH_CONNECTION; - nlc->nlu = nlbp->nlu; - nlc->s = s; - nlc->s2 = INVALID_SOCKET; - InitializeCriticalSection(&nlc->csHttpSequenceNums); - nlc->hOkToCloseEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - NetlibInitializeNestedCS(&nlc->ncsSend); - NetlibInitializeNestedCS(&nlc->ncsRecv); - - if (nlbp->pfnNewConnectionV2) - nlbp->pfnNewConnectionV2(nlc, ntohl(sin.Ipv4.sin_addr.S_un.S_addr), nlbp->pExtra); - } - - NetlibUPnPDeletePortMapping(nlbp->wExPort, "TCP"); - nlbp->hThread = 0; - - NetlibLogf(nlbp->nlu, "NetlibBindAcceptThread: (%p) thread for port %u closed", nlbp->s, nlbp->wPort); -} - -INT_PTR NetlibBindPort(WPARAM wParam, LPARAM lParam) -{ - NETLIBBIND *nlb = (NETLIBBIND*)lParam; - NetlibUser *nlu = (NetlibUser*)wParam; - struct NetlibBoundPort *nlbp; - SOCKADDR_IN sin = { 0 }; - SOCKADDR_IN6 sin6 = { 0 }; - int foundPort = 0; - - if (GetNetlibHandleType(nlu) != NLH_USER || !(nlu->user.flags & NUF_INCOMING) || - nlb == NULL || nlb->pfnNewConnection == NULL) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - if (nlb->cbSize != sizeof(NETLIBBIND)) - return 0; - - nlbp = (NetlibBoundPort*)mir_calloc(sizeof(NetlibBoundPort)); - nlbp->handleType = NLH_BOUNDPORT; - nlbp->nlu = nlu; - nlbp->pfnNewConnectionV2 = nlb->pfnNewConnectionV2; - - nlbp->s = socket(PF_INET, SOCK_STREAM, 0); - nlbp->s6 = socket(PF_INET6, SOCK_STREAM, 0); - nlbp->pExtra = nlb->pExtra; - if (nlbp->s == INVALID_SOCKET && nlbp->s6 == INVALID_SOCKET) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "socket", WSAGetLastError()); - mir_free(nlbp); - return 0; - } - sin.sin_family = AF_INET; - sin6.sin6_family = AF_INET6; - - /* if the netlib user wanted a free port given in the range, then - they better have given wPort == 0, let's hope so */ - if (nlu->settings.specifyIncomingPorts && nlu->settings.szIncomingPorts && nlb->wPort == 0) { - if (!BindSocketToPort(nlu->settings.szIncomingPorts, nlbp->s, nlbp->s6, &nlu->outportnum)) { - NetlibLogf(nlu, "Netlib bind: Not enough ports for incoming connections specified"); - SetLastError(WSAEADDRINUSE); - } - else foundPort = 1; - } - else { - /* if ->wPort == 0 then they'll get any free port, otherwise they'll - be asking for whatever was in nlb->wPort*/ - if (nlb->wPort != 0) { - NetlibLogf(nlu, "%s %d: trying to bind port %d, this 'feature' can be abused, please be sure you want to allow it.", __FILE__, __LINE__, nlb->wPort); - sin.sin_port = htons(nlb->wPort); - sin6.sin6_port = htons(nlb->wPort); - } - - if (nlbp->s != INVALID_SOCKET) - if (bind(nlbp->s, (PSOCKADDR)&sin, sizeof(sin)) == 0) { - SOCKADDR_IN sin = { 0 }; - int len = sizeof(sin); - if (!getsockname(nlbp->s, (PSOCKADDR)&sin, &len)) - sin6.sin6_port = sin.sin_port; - foundPort = 1; - } - - if (nlbp->s6 != INVALID_SOCKET) - if (bind(nlbp->s6, (PSOCKADDR)&sin6, sizeof(sin6)) == 0) - foundPort = 1; - } - if (!foundPort) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "bind", WSAGetLastError()); -LBL_Error: - closesocket(nlbp->s); - closesocket(nlbp->s6); - mir_free(nlbp); - return 0; - } - - if (nlbp->s != INVALID_SOCKET && listen(nlbp->s, 5)) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "listen", WSAGetLastError()); - goto LBL_Error; - } - - if (nlbp->s6 != INVALID_SOCKET && listen(nlbp->s6, 5)) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "listen", WSAGetLastError()); - goto LBL_Error; - } - - SOCKADDR_INET_M sinm = { 0 }; - int len = sizeof(sinm); - if (!getsockname(nlbp->s, (PSOCKADDR)&sinm, &len)) { - nlb->wPort = ntohs(sinm.Ipv4.sin_port); - nlb->dwInternalIP = ntohl(sinm.Ipv4.sin_addr.S_un.S_addr); - } - else if (!getsockname(nlbp->s6, (PSOCKADDR)&sinm, &len)) - nlb->wPort = ntohs(sinm.Ipv6.sin6_port); - else { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "getsockname", WSAGetLastError()); - goto LBL_Error; - } - nlbp->wPort = nlb->wPort; - - if (nlb->dwInternalIP == 0) { - char hostname[64] = ""; - gethostname(hostname, SIZEOF(hostname)); - - PHOSTENT he = gethostbyname(hostname); - if (he && he->h_addr) - nlb->dwInternalIP = ntohl(*(PDWORD)he->h_addr); - } - - DWORD extIP; - if (nlu->settings.enableUPnP && NetlibUPnPAddPortMapping(nlb->wPort, "TCP", &nlbp->wExPort, &extIP, true)) { - NetlibLogf(NULL, "UPnP port mapping succeeded. Internal Port: %u External Port: %u\n", nlb->wPort, nlbp->wExPort); - nlb->wExPort = nlbp->wExPort; - nlb->dwExternalIP = extIP; - } - else { - if (nlu->settings.enableUPnP) - NetlibLogf(NULL, "UPnP port mapping failed. Internal Port: %u\n", nlb->wPort); - else - NetlibLogf(NULL, "UPnP disabled. Internal Port: %u\n", nlb->wPort); - - nlbp->wExPort = 0; - nlb->wExPort = nlb->wPort; - nlb->dwExternalIP = nlb->dwInternalIP; - } - - nlbp->hThread = mir_forkthread(NetlibBindAcceptThread, nlbp); - return (INT_PTR)nlbp; -} diff --git a/src/modules/netlib/netlibhttp.cpp b/src/modules/netlib/netlibhttp.cpp deleted file mode 100644 index 3fe48d5dc1..0000000000 --- a/src/modules/netlib/netlibhttp.cpp +++ /dev/null @@ -1,1168 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "..\..\core\commonheaders.h" -#include "../plugins/zlib/src/zlib.h" -#include "netlib.h" - -#define HTTPRECVHEADERSTIMEOUT 30000 //in ms -#define HTTPRECVDATATIMEOUT 20000 - -struct ResizableCharBuffer -{ - char *sz; - int iEnd, cbAlloced; -}; - -struct ProxyAuth -{ - char *szServer; - char *szMethod; -// char *szUserName; -// char *szPassword; - - ProxyAuth(const char *pszServer, const char *pszMethod) - { - szServer = mir_strdup(pszServer); - szMethod = mir_strdup(pszMethod); - } - ~ProxyAuth() - { - mir_free(szServer); - mir_free(szMethod); - } - static int Compare(const ProxyAuth* p1, const ProxyAuth* p2) - { return mir_strcmpi(p1->szServer, p2->szServer); } -}; - -struct ProxyAuthList : OBJLIST -{ - ProxyAuthList() : OBJLIST(2, ProxyAuth::Compare) {} - - void add(const char *szServer, const char *szMethod) - { - if (szServer == NULL) return; - int i = getIndex((ProxyAuth*)&szServer); - if (i >= 0) { - ProxyAuth &rec = (*this)[i]; - if (szMethod == NULL) - remove(i); - else if (_stricmp(rec.szMethod, szMethod)) { - mir_free(rec.szMethod); - rec.szMethod = mir_strdup(szMethod); - } - } - else insert(new ProxyAuth(szServer, szMethod)); - } - - const char* find(const char *szServer) - { - ProxyAuth * rec = szServer ? OBJLIST::find((ProxyAuth*)&szServer) : NULL; - return rec ? rec->szMethod : NULL; - } -}; - -ProxyAuthList proxyAuthList; - -static void AppendToCharBuffer(struct ResizableCharBuffer *rcb, const char *fmt, ...) -{ - va_list va; - int charsDone; - - if (rcb->cbAlloced == 0) { - rcb->cbAlloced = 512; - rcb->sz = (char*)mir_alloc(rcb->cbAlloced); - } - va_start(va, fmt); - while (true) { - charsDone = mir_vsnprintf(rcb->sz + rcb->iEnd, rcb->cbAlloced-rcb->iEnd, fmt, va); - if (charsDone >= 0) break; - rcb->cbAlloced += 512; - rcb->sz = (char*)mir_realloc(rcb->sz, rcb->cbAlloced); - } - va_end(va); - rcb->iEnd += charsDone; -} - -static int RecvWithTimeoutTime(NetlibConnection *nlc, unsigned dwTimeoutTime, char *buf, int len, int flags) -{ - DWORD dwTimeNow; - - if (!si.pending(nlc->hSsl)) { - while ((dwTimeNow = GetTickCount()) < dwTimeoutTime) { - unsigned dwDeltaTime = min(dwTimeoutTime - dwTimeNow, 1000); - int res = WaitUntilReadable(nlc->s, dwDeltaTime); - - switch (res) { - case SOCKET_ERROR: - return SOCKET_ERROR; - - case 1: - return NLRecv(nlc, buf, len, flags); - } - - if (nlc->termRequested || Miranda_Terminated()) - return 0; - } - SetLastError(ERROR_TIMEOUT); - return SOCKET_ERROR; - } - return NLRecv(nlc, buf, len, flags); -} - -static char* NetlibHttpFindHeader(NETLIBHTTPREQUEST *nlhrReply, const char *hdr) -{ - for (int i=0; i < nlhrReply->headersCount; i++) { - NETLIBHTTPHEADER &p = nlhrReply->headers[i]; - if (_stricmp(p.szName, hdr) == 0) - return p.szValue; - } - - return NULL; -} - -static char* NetlibHttpFindAuthHeader(NETLIBHTTPREQUEST *nlhrReply, const char *hdr, const char *szProvider) -{ - char *szBasicHdr = NULL; - char *szNegoHdr = NULL; - char *szNtlmHdr = NULL; - - for (int i=0; i < nlhrReply->headersCount; i++) { - NETLIBHTTPHEADER &p = nlhrReply->headers[i]; - if (_stricmp(p.szName, hdr) == 0) { - if (_strnicmp(p.szValue, "Negotiate", 9) == 0) - szNegoHdr = p.szValue; - else if (_strnicmp(p.szValue, "NTLM", 4) == 0) - szNtlmHdr = p.szValue; - else if (_strnicmp(p.szValue, "Basic", 5) == 0) - szBasicHdr = p.szValue; - } - } - - if (szNegoHdr && (!szProvider || !_stricmp(szProvider, "Negotiate"))) return szNegoHdr; - if (szNtlmHdr && (!szProvider || !_stricmp(szProvider, "NTLM"))) return szNtlmHdr; - if (!szProvider || !_stricmp(szProvider, "Basic")) return szBasicHdr; - return NULL; -} - -void NetlibConnFromUrl(const char* szUrl, bool secur, NETLIBOPENCONNECTION &nloc) -{ - secur = secur || _strnicmp(szUrl, "https", 5) == 0; - const char* phost = strstr(szUrl, "://"); - - char* szHost = mir_strdup(phost ? phost + 3 : szUrl); - - char* ppath = strchr(szHost, '/'); - if (ppath) *ppath = '\0'; - - memset(&nloc, 0, sizeof(nloc)); - nloc.cbSize = sizeof(nloc); - nloc.szHost = szHost; - - char* pcolon = strrchr(szHost, ':'); - if (pcolon) { - *pcolon = '\0'; - nloc.wPort = (WORD)strtol(pcolon+1, NULL, 10); - } - else nloc.wPort = secur ? 443 : 80; - nloc.flags = (secur ? NLOCF_SSL : 0); -} - -static NetlibConnection* NetlibHttpProcessUrl(NETLIBHTTPREQUEST *nlhr, NetlibUser *nlu, NetlibConnection* nlc, const char* szUrl = NULL) -{ - NETLIBOPENCONNECTION nloc; - - if (szUrl == NULL) - NetlibConnFromUrl(nlhr->szUrl, (nlhr->flags & NLHRF_SSL) != 0, nloc); - else - NetlibConnFromUrl(szUrl, false, nloc); - - nloc.flags |= NLOCF_HTTP; - if (nloc.flags & NLOCF_SSL) nlhr->flags |= NLHRF_SSL; else nlhr->flags &= ~NLHRF_SSL; - - if (nlc != NULL) { - bool httpProxy = !(nloc.flags & NLOCF_SSL) && nlc->proxyType == PROXYTYPE_HTTP; - bool sameHost = mir_strcmp(nlc->nloc.szHost, nloc.szHost) == 0 && nlc->nloc.wPort == nloc.wPort; - - if (!httpProxy && !sameHost) { - NetlibDoClose(nlc); - - mir_free((char*)nlc->nloc.szHost); - nlc->nloc = nloc; - return NetlibDoConnect(nlc) ? nlc : NULL; - } - } - else nlc = (NetlibConnection*)NetlibOpenConnection((WPARAM)nlu, (LPARAM)&nloc); - - mir_free((char*)nloc.szHost); - - return nlc; -} - -struct HttpSecurityContext -{ - HANDLE m_hNtlmSecurity; - char *m_szHost; - char *m_szProvider; - - HttpSecurityContext() - { m_hNtlmSecurity = NULL; m_szHost = NULL; m_szProvider = NULL; } - - ~HttpSecurityContext() { Destroy(); } - - void Destroy(void) - { - if (!m_hNtlmSecurity) return; - - NetlibDestroySecurityProvider(m_hNtlmSecurity); - m_hNtlmSecurity = NULL; - mir_free(m_szHost); m_szHost = NULL; - mir_free(m_szProvider); m_szProvider = NULL; - } - - bool TryBasic(void) - { - return m_hNtlmSecurity && m_szProvider && _stricmp(m_szProvider, "Basic"); - } - - char* Execute(NetlibConnection *nlc, char* szHost, const char* szProvider, - const char* szChallenge, unsigned& complete) - { - char* szAuthHdr = NULL; - bool justCreated = false; - - if (m_hNtlmSecurity) { - bool newAuth = !m_szProvider || !szProvider || _stricmp(m_szProvider, szProvider); - newAuth = newAuth || (m_szHost != szHost && (!m_szHost || !szHost || _stricmp(m_szHost, szHost))); - if (newAuth) - Destroy(); - } - - if (m_hNtlmSecurity == NULL) { - char szSpnStr[256] = ""; - if (szHost && _stricmp(szProvider, "Basic")) { - unsigned long ip = inet_addr(szHost); - PHOSTENT host = (ip == INADDR_NONE) ? gethostbyname(szHost) : gethostbyaddr((char*)&ip, 4, AF_INET); - mir_snprintf(szSpnStr, SIZEOF(szSpnStr), "HTTP/%s", host && host->h_name ? host->h_name : szHost); - _strlwr(szSpnStr + 5); - NetlibLogf(nlc->nlu, "Host SPN: %s", szSpnStr); - } - m_hNtlmSecurity = NetlibInitSecurityProvider(szProvider, szSpnStr[0] ? szSpnStr : NULL); - if (m_hNtlmSecurity) { - m_szProvider = mir_strdup(szProvider); - m_szHost = mir_strdup(szHost); - justCreated = true; - } - } - - if (m_hNtlmSecurity) { - TCHAR *szLogin = NULL, *szPassw = NULL; - - if (nlc->nlu->settings.useProxyAuth) { - mir_cslock lck(csNetlibUser); - szLogin = mir_a2t(nlc->nlu->settings.szProxyAuthUser); - szPassw = mir_a2t(nlc->nlu->settings.szProxyAuthPassword); - } - - szAuthHdr = NtlmCreateResponseFromChallenge(m_hNtlmSecurity, - szChallenge, szLogin, szPassw, true, complete); - - if (!szAuthHdr) { - NetlibLogf(NULL, "Security login %s failed, user: %S pssw: %S", - szProvider, szLogin ? szLogin : _T("(no user)"), szPassw ? _T("(exist)") : _T("(no psw)")); - } - else if (justCreated) - proxyAuthList.add(m_szHost, m_szProvider); - - mir_free(szLogin); - mir_free(szPassw); - } - else complete = 1; - - return szAuthHdr; - } -}; - -static int HttpPeekFirstResponseLine(NetlibConnection *nlc, DWORD dwTimeoutTime, DWORD recvFlags, int *resultCode, char **ppszResultDescr, int *length) -{ - int bytesPeeked; - char buffer[2048]; - char *peol; - - while(true) { - bytesPeeked = RecvWithTimeoutTime(nlc, dwTimeoutTime, buffer, SIZEOF(buffer) - 1, MSG_PEEK | recvFlags); - - if (bytesPeeked == 0) { - SetLastError(ERROR_HANDLE_EOF); - return 0; - } - if (bytesPeeked == SOCKET_ERROR) - return 0; - - buffer[bytesPeeked] = '\0'; - if ((peol = strchr(buffer, '\n')) != NULL) - break; - - if ((int)mir_strlen(buffer) < bytesPeeked) { - SetLastError(ERROR_BAD_FORMAT); - return 0; - } - if (bytesPeeked == SIZEOF(buffer) - 1) { - SetLastError(ERROR_BUFFER_OVERFLOW); - return 0; - } - if (Miranda_Terminated()) return 0; - Sleep(10); - } - - if (peol == buffer) { - SetLastError(ERROR_BAD_FORMAT); - return 0; - } - - *peol = '\0'; - - if (_strnicmp(buffer, "HTTP/", 5)) { - SetLastError(ERROR_BAD_FORMAT); - return 0; - } - - size_t off = strcspn(buffer, " \t"); - if (off >= (unsigned)bytesPeeked) - return 0; - - char* pResultCode = buffer + off; - *(pResultCode++) = 0; - - char* pResultDescr; - *resultCode = strtol(pResultCode, &pResultDescr, 10); - - if (ppszResultDescr) - *ppszResultDescr = mir_strdup(lrtrimp(pResultDescr)); - - if (length) *length = peol - buffer + 1; - return 1; -} - -static int SendHttpRequestAndData(NetlibConnection *nlc, struct ResizableCharBuffer *httpRequest, NETLIBHTTPREQUEST *nlhr, int sendContentLengthHeader) -{ - bool sendData = (nlhr->requestType == REQUEST_POST || nlhr->requestType == REQUEST_PUT); - - if (sendContentLengthHeader && sendData) - AppendToCharBuffer(httpRequest, "Content-Length: %d\r\n\r\n", nlhr->dataLength); - else - AppendToCharBuffer(httpRequest, "\r\n"); - - DWORD hflags = (nlhr->flags & NLHRF_DUMPASTEXT ? MSG_DUMPASTEXT : 0) | - (nlhr->flags & (NLHRF_NODUMP | NLHRF_NODUMPSEND | NLHRF_NODUMPHEADERS) ? - MSG_NODUMP : (nlhr->flags & NLHRF_DUMPPROXY ? MSG_DUMPPROXY : 0)) | - (nlhr->flags & NLHRF_NOPROXY ? MSG_RAW : 0); - - int bytesSent = NLSend(nlc, httpRequest->sz, httpRequest->iEnd, hflags); - if (bytesSent != SOCKET_ERROR && sendData && nlhr->dataLength) { - DWORD sflags = (nlhr->flags & NLHRF_DUMPASTEXT ? MSG_DUMPASTEXT : 0) | - (nlhr->flags & (NLHRF_NODUMP | NLHRF_NODUMPSEND) ? - MSG_NODUMP : (nlhr->flags & NLHRF_DUMPPROXY ? MSG_DUMPPROXY : 0)) | - (nlhr->flags & NLHRF_NOPROXY ? MSG_RAW : 0); - - int sendResult = NLSend(nlc, nlhr->pData, nlhr->dataLength, sflags); - - bytesSent = sendResult != SOCKET_ERROR ? bytesSent + sendResult : SOCKET_ERROR; - } - mir_free(httpRequest->sz); - memset(httpRequest, 0, sizeof(*httpRequest)); - - return bytesSent; -} - -INT_PTR NetlibHttpSendRequest(WPARAM wParam, LPARAM lParam) -{ - NetlibConnection *nlc = (struct NetlibConnection*)wParam; - NETLIBHTTPREQUEST *nlhr = (NETLIBHTTPREQUEST*)lParam; - NETLIBHTTPREQUEST *nlhrReply = NULL; - HttpSecurityContext httpSecurity; - - struct ResizableCharBuffer httpRequest = {0}; - char *szHost = NULL, *szNewUrl = NULL; - char *pszProxyAuthHdr = NULL, *pszAuthHdr = NULL; - int i, doneHostHeader, doneContentLengthHeader, doneProxyAuthHeader, doneAuthHeader; - int bytesSent; - bool lastFirstLineFail = false; - - if (nlhr == NULL || nlhr->cbSize != sizeof(NETLIBHTTPREQUEST) || nlhr->szUrl == NULL || nlhr->szUrl[0] == '\0') { - SetLastError(ERROR_INVALID_PARAMETER); - return SOCKET_ERROR; - } - - int hdrTimeout = (nlhr->timeout) ? nlhr->timeout : HTTPRECVHEADERSTIMEOUT; - - const char *pszRequest; - switch(nlhr->requestType) { - case REQUEST_GET: pszRequest = "GET"; break; - case REQUEST_POST: pszRequest = "POST"; break; - case REQUEST_CONNECT: pszRequest = "CONNECT"; break; - case REQUEST_HEAD: pszRequest = "HEAD"; break; - case REQUEST_PUT: pszRequest = "PUT"; break; - case REQUEST_DELETE: pszRequest = "DELETE"; break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - return SOCKET_ERROR; - } - - if (!nlc->usingHttpGateway) - if (!NetlibEnterNestedCS(nlc, NLNCS_SEND)) - return SOCKET_ERROR; - - const char *pszFullUrl = nlhr->szUrl; - const char *pszUrl = NULL; - - unsigned complete = false; - int count = 11; - while (--count) { - if (!NetlibReconnect(nlc)) { - bytesSent = SOCKET_ERROR; - break; - } - - if (!pszUrl) { - pszUrl = pszFullUrl; - if (nlhr->flags & (NLHRF_SMARTREMOVEHOST | NLHRF_REMOVEHOST | NLHRF_GENERATEHOST)) { - bool usingProxy = nlc->proxyType == PROXYTYPE_HTTP && !(nlhr->flags & NLHRF_SSL); - - mir_free(szHost); - szHost = NULL; - - const char *ppath, *phost; - phost = strstr(pszUrl, "://"); - if (phost == NULL) phost = pszUrl; - else phost += 3; - ppath = strchr(phost, '/'); - if (ppath == phost) phost = NULL; - - if (nlhr->flags & NLHRF_GENERATEHOST) { - szHost = mir_strdup(phost); - if (ppath && phost) szHost[ppath - phost] = 0; - } - - if (nlhr->flags & NLHRF_REMOVEHOST || (nlhr->flags & NLHRF_SMARTREMOVEHOST && !usingProxy)) - pszUrl = ppath ? ppath : "/"; - - if (usingProxy && phost && !nlc->dnsThroughProxy) { - char* tszHost = mir_strdup(phost); - if (ppath && phost) tszHost[ppath - phost] = 0; - char* cln = strchr(tszHost, ':'); if (cln) *cln = 0; - - if (inet_addr(tszHost) == INADDR_NONE) { - DWORD ip = DnsLookup(nlc->nlu, tszHost); - if (ip && szHost) { - mir_free(szHost); - szHost = (char*)mir_alloc(64); - if (cln) *cln = ':'; - mir_snprintf(szHost, 64, "%s%s", inet_ntoa(*(PIN_ADDR)&ip), cln ? cln : ""); - } - } - mir_free(tszHost); - } - } - } - - if (nlc->proxyAuthNeeded && proxyAuthList.getCount()) { - if (httpSecurity.m_szProvider == NULL && nlc->szProxyServer) { - const char* szAuthMethodNlu = proxyAuthList.find(nlc->szProxyServer); - if (szAuthMethodNlu) { - mir_free(pszProxyAuthHdr); - pszProxyAuthHdr = httpSecurity.Execute(nlc, nlc->szProxyServer, szAuthMethodNlu, "", complete); - } - } - } - nlc->proxyAuthNeeded = false; - - AppendToCharBuffer(&httpRequest, "%s %s HTTP/1.%d\r\n", pszRequest, pszUrl, (nlhr->flags & NLHRF_HTTP11) != 0); - - //HTTP headers - doneHostHeader = doneContentLengthHeader = doneProxyAuthHeader = doneAuthHeader = 0; - for (i=0; i < nlhr->headersCount; i++) { - NETLIBHTTPHEADER &p = nlhr->headers[i]; - if (!mir_strcmpi(p.szName, "Host")) doneHostHeader = 1; - else if (!mir_strcmpi(p.szName, "Content-Length")) doneContentLengthHeader = 1; - else if (!mir_strcmpi(p.szName, "Proxy-Authorization")) doneProxyAuthHeader = 1; - else if (!mir_strcmpi(p.szName, "Authorization")) doneAuthHeader = 1; - else if (!mir_strcmpi(p.szName, "Connection")) continue; - if (p.szValue == NULL) continue; - AppendToCharBuffer(&httpRequest, "%s: %s\r\n", p.szName, p.szValue); - } - if (szHost && !doneHostHeader) - AppendToCharBuffer(&httpRequest, "%s: %s\r\n", "Host", szHost); - if (pszProxyAuthHdr && !doneProxyAuthHeader) - AppendToCharBuffer(&httpRequest, "%s: %s\r\n", "Proxy-Authorization", pszProxyAuthHdr); - if (pszAuthHdr && !doneAuthHeader) - AppendToCharBuffer(&httpRequest, "%s: %s\r\n", "Authorization", pszAuthHdr); - AppendToCharBuffer(&httpRequest, "%s: %s\r\n", "Connection", "Keep-Alive"); - AppendToCharBuffer(&httpRequest, "%s: %s\r\n", "Proxy-Connection", "Keep-Alive"); - - // Add Sticky Headers - if (nlc->nlu->szStickyHeaders != NULL) - AppendToCharBuffer(&httpRequest, "%s\r\n", nlc->nlu->szStickyHeaders); - - //send it - bytesSent = SendHttpRequestAndData(nlc, &httpRequest, nlhr, !doneContentLengthHeader); - if (bytesSent == SOCKET_ERROR) - break; - - //ntlm reply - if (doneContentLengthHeader && nlhr->requestType != REQUEST_HEAD) - break; - - DWORD fflags = MSG_PEEK | MSG_NODUMP | ((nlhr->flags & NLHRF_NOPROXY) ? MSG_RAW : 0); - DWORD dwTimeOutTime = hdrTimeout < 0 ? -1 : GetTickCount() + hdrTimeout; - if (!HttpPeekFirstResponseLine(nlc, dwTimeOutTime, fflags, &nlhr->resultCode, NULL, NULL)) { - NetlibLogf(nlc->nlu, "%s %d: %s Failed (%u %u)", __FILE__, __LINE__, "HttpPeekFirstResponseLine", GetLastError(), count); - DWORD err = GetLastError(); - if (err == ERROR_TIMEOUT || err == ERROR_BAD_FORMAT || err == ERROR_BUFFER_OVERFLOW || lastFirstLineFail || nlc->termRequested || nlhr->requestType == REQUEST_CONNECT) { - bytesSent = SOCKET_ERROR; - break; - } - - lastFirstLineFail = true; - continue; - } - - int resultCode = nlhr->resultCode; - lastFirstLineFail = false; - - DWORD hflags = (nlhr->flags & (NLHRF_NODUMP|NLHRF_NODUMPHEADERS|NLHRF_NODUMPSEND) ? - MSG_NODUMP : (nlhr->flags & NLHRF_DUMPPROXY ? MSG_DUMPPROXY : 0)) | - (nlhr->flags & NLHRF_NOPROXY ? MSG_RAW : 0); - - DWORD dflags = (nlhr->flags & (NLHRF_NODUMP | NLHRF_NODUMPSEND) ? MSG_NODUMP : MSG_DUMPASTEXT | MSG_DUMPPROXY) | - (nlhr->flags & NLHRF_NOPROXY ? MSG_RAW : 0) | MSG_NODUMP; - - if (resultCode == 100) - nlhrReply = (NETLIBHTTPREQUEST*)NetlibHttpRecvHeaders((WPARAM)nlc, hflags); - - else if (resultCode == 307 || ((resultCode == 301 || resultCode == 302) && (nlhr->flags & NLHRF_REDIRECT))) { // redirect - pszUrl = NULL; - - if (nlhr->requestType == REQUEST_HEAD) - nlhrReply = (NETLIBHTTPREQUEST*)NetlibHttpRecvHeaders((WPARAM)nlc, hflags); - else - nlhrReply = NetlibHttpRecv(nlc, hflags, dflags); - - if (nlhrReply) { - char* tmpUrl = NetlibHttpFindHeader(nlhrReply, "Location"); - if (tmpUrl) { - size_t rlen = 0; - if (tmpUrl[0] == '/') { - const char *ppath, *phost; - phost = strstr(pszFullUrl, "://"); - phost = phost ? phost + 3 : pszFullUrl; - ppath = strchr(phost, '/'); - rlen = ppath ? ppath - pszFullUrl : mir_strlen(pszFullUrl); - } - - nlc->szNewUrl = (char*)mir_realloc(nlc->szNewUrl, rlen + mir_strlen(tmpUrl) * 3 + 1); - - strncpy(nlc->szNewUrl, pszFullUrl, rlen); - mir_strcpy(nlc->szNewUrl + rlen, tmpUrl); - pszFullUrl = nlc->szNewUrl; - pszUrl = NULL; - - if (NetlibHttpProcessUrl(nlhr, nlc->nlu, nlc, pszFullUrl) == NULL) { - bytesSent = SOCKET_ERROR; - break; - } - } - else { - NetlibHttpSetLastErrorUsingHttpResult(resultCode); - bytesSent = SOCKET_ERROR; - break; - } - } - else { - NetlibHttpSetLastErrorUsingHttpResult(resultCode); - bytesSent = SOCKET_ERROR; - break; - } - } - else if (resultCode == 401 && !doneAuthHeader) { //auth required - if (nlhr->requestType == REQUEST_HEAD) - nlhrReply = (NETLIBHTTPREQUEST*)NetlibHttpRecvHeaders((WPARAM)nlc, hflags); - else - nlhrReply = NetlibHttpRecv(nlc, hflags, dflags); - - mir_free(pszAuthHdr); pszAuthHdr = NULL; - if (nlhrReply) { - char *szAuthStr = NULL; - if (!complete) { - szAuthStr = NetlibHttpFindAuthHeader(nlhrReply, "WWW-Authenticate", httpSecurity.m_szProvider); - if (szAuthStr) { - char *szChallenge = strchr(szAuthStr, ' '); - if (!szChallenge || !*lrtrimp(szChallenge)) - complete = true; - } - } - if (complete && httpSecurity.m_hNtlmSecurity) - szAuthStr = httpSecurity.TryBasic() ? NetlibHttpFindAuthHeader(nlhrReply, "WWW-Authenticate", "Basic") : NULL; - - if (szAuthStr) { - char *szChallenge = strchr(szAuthStr, ' '); - if (szChallenge) { *szChallenge = 0; szChallenge = lrtrimp(szChallenge + 1); } - - pszAuthHdr = httpSecurity.Execute(nlc, szHost, szAuthStr, szChallenge, complete); - } - } - if (pszAuthHdr == NULL) { - proxyAuthList.add(szHost, NULL); - NetlibHttpSetLastErrorUsingHttpResult(resultCode); - bytesSent = SOCKET_ERROR; - break; - } - } - else if (resultCode == 407 && !doneProxyAuthHeader) { //proxy auth required - if (nlhr->requestType == REQUEST_HEAD) - nlhrReply = (NETLIBHTTPREQUEST*)NetlibHttpRecvHeaders((WPARAM)nlc, hflags); - else - nlhrReply = NetlibHttpRecv(nlc, hflags, dflags); - - mir_free(pszProxyAuthHdr); pszProxyAuthHdr = NULL; - if (nlhrReply) { - char *szAuthStr = NULL; - if (!complete) { - szAuthStr = NetlibHttpFindAuthHeader(nlhrReply, "Proxy-Authenticate", httpSecurity.m_szProvider); - if (szAuthStr) { - char *szChallenge = strchr(szAuthStr, ' '); - if (!szChallenge || !*lrtrimp(szChallenge + 1)) - complete = true; - } - } - if (complete && httpSecurity.m_hNtlmSecurity) - szAuthStr = httpSecurity.TryBasic() ? NetlibHttpFindAuthHeader(nlhrReply, "Proxy-Authenticate", "Basic") : NULL; - - if (szAuthStr) { - char *szChallenge = strchr(szAuthStr, ' '); - if (szChallenge) { *szChallenge = 0; szChallenge = lrtrimp(szChallenge + 1); } - - pszProxyAuthHdr = httpSecurity.Execute(nlc, nlc->szProxyServer, szAuthStr, szChallenge, complete); - } - } - if (pszProxyAuthHdr == NULL) { - proxyAuthList.add(nlc->szProxyServer, NULL); - NetlibHttpSetLastErrorUsingHttpResult(resultCode); - bytesSent = SOCKET_ERROR; - break; - } - } - else break; - - if (pszProxyAuthHdr && resultCode != 407 && !doneProxyAuthHeader) - replaceStr(pszProxyAuthHdr, NULL); - - if (pszAuthHdr && resultCode != 401 && !doneAuthHeader) - replaceStr(pszAuthHdr, NULL); - - if (nlhrReply) { - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - nlhrReply = NULL; - } - } - - if (count == 0) bytesSent = SOCKET_ERROR; - if (nlhrReply) NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - - //clean up - mir_free(pszProxyAuthHdr); - mir_free(pszAuthHdr); - mir_free(szHost); - mir_free(szNewUrl); - - if (!nlc->usingHttpGateway) - NetlibLeaveNestedCS(&nlc->ncsSend); - - return bytesSent; -} - -INT_PTR NetlibHttpFreeRequestStruct(WPARAM, LPARAM lParam) -{ - NETLIBHTTPREQUEST *nlhr = (NETLIBHTTPREQUEST*)lParam; - - if (nlhr == NULL || nlhr->cbSize != sizeof(NETLIBHTTPREQUEST) || nlhr->requestType != REQUEST_RESPONSE) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - if (nlhr->headers) { - for (int i=0; i < nlhr->headersCount; i++) { - NETLIBHTTPHEADER &p = nlhr->headers[i]; - mir_free(p.szName); - mir_free(p.szValue); - } - mir_free(nlhr->headers); - } - mir_free(nlhr->pData); - mir_free(nlhr->szResultDescr); - mir_free(nlhr->szUrl); - mir_free(nlhr); - return 1; -} - -INT_PTR NetlibHttpRecvHeaders(WPARAM wParam, LPARAM lParam) -{ - NetlibConnection *nlc = (struct NetlibConnection*)wParam; - if (!NetlibEnterNestedCS(nlc, NLNCS_RECV)) - return 0; - - char *peol, *pbuffer; - int headersCount = 0, bufferSize = 8192; - - DWORD dwRequestTimeoutTime = GetTickCount() + HTTPRECVDATATIMEOUT; - NETLIBHTTPREQUEST *nlhr = (NETLIBHTTPREQUEST*)mir_calloc(sizeof(NETLIBHTTPREQUEST)); - nlhr->cbSize = sizeof(NETLIBHTTPREQUEST); - nlhr->nlc = nlc; // Needed to id connection in the protocol HTTP gateway wrapper functions - nlhr->requestType = REQUEST_RESPONSE; - - int firstLineLength = 0; - if (!HttpPeekFirstResponseLine(nlc, dwRequestTimeoutTime, lParam | MSG_PEEK, &nlhr->resultCode, &nlhr->szResultDescr, &firstLineLength)) { - NetlibLeaveNestedCS(&nlc->ncsRecv); - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhr); - return 0; - } - - char *buffer = (char*)mir_alloc(bufferSize + 1); - int bytesPeeked = NLRecv(nlc, buffer, min(firstLineLength, bufferSize), lParam | MSG_DUMPASTEXT); - if (bytesPeeked != firstLineLength) { - NetlibLeaveNestedCS(&nlc->ncsRecv); - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhr); - if (bytesPeeked != SOCKET_ERROR) SetLastError(ERROR_HANDLE_EOF); - mir_free(buffer); - return 0; - } - - // Make sure all headers arrived - bytesPeeked = 0; - for (bool headersCompleted = false; !headersCompleted; ) { - if (bytesPeeked >= bufferSize) { - bufferSize += 8192; - mir_free(buffer); - if (bufferSize > 32 * 1024) { - bytesPeeked = 0; - break; - } - buffer = (char*)mir_alloc(bufferSize + 1); - } - - bytesPeeked = RecvWithTimeoutTime(nlc, dwRequestTimeoutTime, buffer, bufferSize, MSG_PEEK | MSG_NODUMP | lParam); - if (bytesPeeked == 0) - break; - - if (bytesPeeked == SOCKET_ERROR) { - bytesPeeked = 0; - break; - } - buffer[bytesPeeked] = 0; - - for (pbuffer = buffer, headersCount = 0;; pbuffer = peol + 1, ++headersCount) { - peol = strchr(pbuffer, '\n'); - if (peol == NULL) break; - if (peol == pbuffer || (peol == (pbuffer + 1) && *pbuffer == '\r')) { - bytesPeeked = peol - buffer + 1; - headersCompleted = true; - break; - } - } - } - - // Receive headers - if (bytesPeeked > 0) - bytesPeeked = NLRecv(nlc, buffer, bytesPeeked, lParam | MSG_DUMPASTEXT); - if (bytesPeeked <= 0) { - NetlibLeaveNestedCS(&nlc->ncsRecv); - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhr); - mir_free(buffer); - return 0; - } - buffer[bytesPeeked] = 0; - - nlhr->headersCount = headersCount; - nlhr->headers = (NETLIBHTTPHEADER*)mir_calloc(sizeof(NETLIBHTTPHEADER) * headersCount); - - for (pbuffer = buffer, headersCount = 0;; pbuffer = peol + 1, ++headersCount) { - peol = strchr(pbuffer, '\n'); - if (peol == NULL || peol == pbuffer || (peol == (pbuffer + 1) && *pbuffer == '\r')) break; - *peol = 0; - - char *pColon = strchr(pbuffer, ':'); - if (pColon == NULL) { - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhr); nlhr = NULL; - SetLastError(ERROR_INVALID_DATA); - break; - } - - *(pColon++) = 0; - nlhr->headers[headersCount].szName = mir_strdup(rtrim(pbuffer)); - nlhr->headers[headersCount].szValue = mir_strdup(lrtrimp(pColon)); - } - - NetlibLeaveNestedCS(&nlc->ncsRecv); - mir_free(buffer); - return (INT_PTR)nlhr; -} - -INT_PTR NetlibHttpTransaction(WPARAM wParam, LPARAM lParam) -{ - NetlibUser *nlu = (NetlibUser*)wParam; - NETLIBHTTPREQUEST *nlhr = (NETLIBHTTPREQUEST*)lParam, *nlhrReply; - - if (GetNetlibHandleType(nlu) != NLH_USER || !(nlu->user.flags & NUF_OUTGOING) || - nlhr == NULL || nlhr->cbSize != sizeof(NETLIBHTTPREQUEST) || - nlhr->szUrl == NULL || nlhr->szUrl[0] == 0) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - if (nlhr->nlc != NULL && GetNetlibHandleType(nlhr->nlc) != NLH_CONNECTION) - nlhr->nlc = NULL; - - NetlibConnection* nlc = NetlibHttpProcessUrl(nlhr, nlu, (NetlibConnection*)nlhr->nlc); - if (nlc == NULL) - return 0; - - NETLIBHTTPREQUEST nlhrSend; - char szUserAgent[64]; - - nlhrSend = *nlhr; - nlhrSend.flags &= ~NLHRF_REMOVEHOST; - nlhrSend.flags |= NLHRF_GENERATEHOST | NLHRF_SMARTREMOVEHOST | NLHRF_SMARTAUTHHEADER; - - bool doneUserAgentHeader = NetlibHttpFindHeader(nlhr, "User-Agent") != NULL; - bool doneAcceptEncoding = NetlibHttpFindHeader(nlhr, "Accept-Encoding") != NULL; - - if (!doneUserAgentHeader || !doneAcceptEncoding) { - nlhrSend.headers = (NETLIBHTTPHEADER*)mir_alloc(sizeof(NETLIBHTTPHEADER) * (nlhrSend.headersCount + 2)); - memcpy(nlhrSend.headers, nlhr->headers, sizeof(NETLIBHTTPHEADER) * nlhr->headersCount); - } - - if (!doneUserAgentHeader) { - nlhrSend.headers[nlhrSend.headersCount].szName = "User-Agent"; - nlhrSend.headers[nlhrSend.headersCount].szValue = szUserAgent; - ++nlhrSend.headersCount; - - char szMirandaVer[64]; - CallService(MS_SYSTEM_GETVERSIONTEXT, SIZEOF(szMirandaVer), (LPARAM)szMirandaVer); - char *pspace = strchr(szMirandaVer, ' '); - if (pspace) { - *pspace++='\0'; - mir_snprintf(szUserAgent, SIZEOF(szUserAgent), "Miranda/%s (%s)", szMirandaVer, pspace); - } - else mir_snprintf(szUserAgent, SIZEOF(szUserAgent), "Miranda/%s", szMirandaVer); - } - if (!doneAcceptEncoding) { - nlhrSend.headers[nlhrSend.headersCount].szName = "Accept-Encoding"; - nlhrSend.headers[nlhrSend.headersCount].szValue = "deflate, gzip"; - ++nlhrSend.headersCount; - } - if (NetlibHttpSendRequest((WPARAM)nlc, (LPARAM)&nlhrSend) == SOCKET_ERROR) { - if (!doneUserAgentHeader || !doneAcceptEncoding) mir_free(nlhrSend.headers); - nlhr->resultCode = nlhrSend.resultCode; - NetlibCloseHandle((WPARAM)nlc, 0); - return 0; - } - if (!doneUserAgentHeader || !doneAcceptEncoding) - mir_free(nlhrSend.headers); - - DWORD dflags = (nlhr->flags & NLHRF_DUMPASTEXT ? MSG_DUMPASTEXT : 0) | - (nlhr->flags & NLHRF_NODUMP ? MSG_NODUMP : (nlhr->flags & NLHRF_DUMPPROXY ? MSG_DUMPPROXY : 0)) | - (nlhr->flags & NLHRF_NOPROXY ? MSG_RAW : 0); - - DWORD hflags = - (nlhr->flags & NLHRF_NODUMP ? MSG_NODUMP : (nlhr->flags & NLHRF_DUMPPROXY ? MSG_DUMPPROXY : 0)) | - (nlhr->flags & NLHRF_NOPROXY ? MSG_RAW : 0); - - if (nlhr->requestType == REQUEST_HEAD) - nlhrReply = (NETLIBHTTPREQUEST*)NetlibHttpRecvHeaders((WPARAM)nlc, 0); - else - nlhrReply = NetlibHttpRecv(nlc, hflags, dflags); - - if (nlhrReply) { - nlhrReply->szUrl = nlc->szNewUrl; - nlc->szNewUrl = NULL; - } - - if ((nlhr->flags & NLHRF_PERSISTENT) == 0 || nlhrReply == NULL) { - NetlibCloseHandle((WPARAM)nlc, 0); - if (nlhrReply) - nlhrReply->nlc = NULL; - } - else nlhrReply->nlc = nlc; - - return (INT_PTR)nlhrReply; -} - -void NetlibHttpSetLastErrorUsingHttpResult(int result) -{ - if (result >= 200 && result < 300) { - SetLastError(ERROR_SUCCESS); - return; - } - switch(result) { - case 400: SetLastError(ERROR_BAD_FORMAT); break; - case 401: - case 402: - case 403: - case 407: SetLastError(ERROR_ACCESS_DENIED); break; - case 404: SetLastError(ERROR_FILE_NOT_FOUND); break; - case 405: - case 406: SetLastError(ERROR_INVALID_FUNCTION); break; - case 408: SetLastError(ERROR_TIMEOUT); break; - default: SetLastError(ERROR_GEN_FAILURE); break; - } -} - -char* gzip_decode(char *gzip_data, int *len_ptr, int window) -{ - if (*len_ptr == 0) return NULL; - - int gzip_len = *len_ptr * 5; - char* output_data = NULL; - - int gzip_err; - z_stream zstr; - - do { - output_data = (char*)mir_realloc(output_data, gzip_len+1); - - zstr.next_in = (Bytef*)gzip_data; - zstr.avail_in = *len_ptr; - zstr.zalloc = Z_NULL; - zstr.zfree = Z_NULL; - zstr.opaque = Z_NULL; - inflateInit2_(&zstr, window, ZLIB_VERSION, sizeof(z_stream)); - - zstr.next_out = (Bytef*)output_data; - zstr.avail_out = gzip_len; - - gzip_err = inflate(&zstr, Z_FINISH); - - inflateEnd(&zstr); - gzip_len *= 2; - } - while (gzip_err == Z_BUF_ERROR); - - gzip_len = gzip_err == Z_STREAM_END ? zstr.total_out : -1; - - if (gzip_len <= 0) { - mir_free(output_data); - output_data = NULL; - } - else output_data[gzip_len] = 0; - - *len_ptr = gzip_len; - return output_data; -} - -static int NetlibHttpRecvChunkHeader(NetlibConnection* nlc, bool first, DWORD flags) -{ - char data[64], *peol1; - - while(true) { - int recvResult = NLRecv(nlc, data, 31, MSG_RAW | MSG_PEEK); - if (recvResult <= 0) - return SOCKET_ERROR; - - data[recvResult] = 0; - - peol1 = strchr(data, '\n'); - if (peol1 != NULL) { - char *peol2 = first ? peol1 : strchr(peol1 + 1, '\n'); - if (peol2 != NULL) { - int sz = peol2 - data + 1; - int r = strtol(first ? data : peol1 + 1, NULL, 16); - if (r == 0) { - char *peol3 = strchr(peol2 + 1, '\n'); - if (peol3 == NULL) continue; - sz = peol3 - data + 1; - } - NLRecv(nlc, data, sz, MSG_RAW | flags); - return r; - } - else if (recvResult >= 31) - return SOCKET_ERROR; - } - } -} - -NETLIBHTTPREQUEST* NetlibHttpRecv(NetlibConnection* nlc, DWORD hflags, DWORD dflags, bool isConnect) -{ - int dataLen = -1, i, chunkhdr = 0; - bool chunked = false; - int cenc = 0, cenctype = 0, close = 0; - -next: - NETLIBHTTPREQUEST *nlhrReply = (NETLIBHTTPREQUEST*)NetlibHttpRecvHeaders((WPARAM)nlc, hflags); - if (nlhrReply == NULL) - return NULL; - - if (nlhrReply->resultCode == 100) { - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - goto next; - } - - for (i=0; iheadersCount; i++) { - NETLIBHTTPHEADER &p = nlhrReply->headers[i]; - if (!mir_strcmpi(p.szName, "Content-Length")) - dataLen = atoi(p.szValue); - - if (!mir_strcmpi(p.szName, "Content-Encoding")) { - cenc = i; - if (strstr(p.szValue, "gzip")) - cenctype = 1; - else if (strstr(p.szValue, "deflate")) - cenctype = 2; - } - - if (!mir_strcmpi(p.szName, "Connection")) - close = !mir_strcmpi(p.szValue, "close"); - - if (!mir_strcmpi(p.szName, "Transfer-Encoding") && - !mir_strcmpi(p.szValue, "chunked")) - { - chunked = true; - chunkhdr = i; - dataLen = -1; - } - } - - if (nlhrReply->resultCode >= 200 && (dataLen > 0 || (!isConnect && dataLen < 0))) { - int recvResult, chunksz = -1; - int dataBufferAlloced; - - if (chunked) { - chunksz = NetlibHttpRecvChunkHeader(nlc, true, dflags); - if (chunksz == SOCKET_ERROR) { - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - return NULL; - } - dataLen = chunksz; - } - dataBufferAlloced = dataLen < 0 ? 2048 : dataLen + 1; - nlhrReply->pData = (char*)mir_realloc(nlhrReply->pData, dataBufferAlloced); - - while (chunksz != 0) { - while(true) { - recvResult = RecvWithTimeoutTime(nlc, GetTickCount() + HTTPRECVDATATIMEOUT, - nlhrReply->pData + nlhrReply->dataLength, - dataBufferAlloced - nlhrReply->dataLength - 1, - dflags | (cenctype ? MSG_NODUMP : 0)); - - if (recvResult == 0) break; - if (recvResult == SOCKET_ERROR) { - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - return NULL; - } - nlhrReply->dataLength += recvResult; - - if (dataLen >= 0) - { - if (nlhrReply->dataLength >= dataLen) - break; - } - else if ((dataBufferAlloced - nlhrReply->dataLength) < 256) { - dataBufferAlloced += 2048; - nlhrReply->pData = (char*)mir_realloc(nlhrReply->pData, dataBufferAlloced); - if (nlhrReply->pData == NULL) { - SetLastError(ERROR_OUTOFMEMORY); - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - return NULL; - } - } - Sleep(10); - } - - if (!chunked) - break; - - chunksz = NetlibHttpRecvChunkHeader(nlc, false, dflags); - if (chunksz == SOCKET_ERROR) { - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - return NULL; - } - dataLen += chunksz; - dataBufferAlloced += chunksz; - - nlhrReply->pData = (char*)mir_realloc(nlhrReply->pData, dataBufferAlloced); - } - - nlhrReply->pData[nlhrReply->dataLength] = '\0'; - } - - if (chunked) { - nlhrReply->headers[chunkhdr].szName = (char*)mir_realloc(nlhrReply->headers[chunkhdr].szName, 16); - mir_strcpy(nlhrReply->headers[chunkhdr].szName, "Content-Length"); - - nlhrReply->headers[chunkhdr].szValue = (char*)mir_realloc(nlhrReply->headers[chunkhdr].szValue, 16); - mir_snprintf(nlhrReply->headers[chunkhdr].szValue, 16, "%u", nlhrReply->dataLength); - } - - if (cenctype) { - int bufsz = nlhrReply->dataLength; - char* szData = NULL; - - switch (cenctype) { - case 1: - szData = gzip_decode(nlhrReply->pData, &bufsz, 0x10 | MAX_WBITS); - break; - - case 2: - szData = gzip_decode(nlhrReply->pData, &bufsz, -MAX_WBITS); - if (bufsz < 0) - { - bufsz = nlhrReply->dataLength; - szData = gzip_decode(nlhrReply->pData, &bufsz, MAX_WBITS); - } - break; - } - - if (bufsz > 0) { - NetlibDumpData(nlc, (PBYTE)szData, bufsz, 0, dflags); - mir_free(nlhrReply->pData); - nlhrReply->pData = szData; - nlhrReply->dataLength = bufsz; - - mir_free(nlhrReply->headers[cenc].szName); - mir_free(nlhrReply->headers[cenc].szValue); - memmove(&nlhrReply->headers[cenc], &nlhrReply->headers[cenc+1], (--nlhrReply->headersCount-cenc)*sizeof(nlhrReply->headers[0])); - } - else if (bufsz == 0) { - mir_free(nlhrReply->pData); - nlhrReply->pData = NULL; - nlhrReply->dataLength = 0; - } - } - - if (close && - (nlc->proxyType != PROXYTYPE_HTTP || nlc->nloc.flags & NLOCF_SSL) && - (!isConnect || nlhrReply->resultCode != 200)) - NetlibDoClose(nlc); - - return nlhrReply; -} diff --git a/src/modules/netlib/netlibhttpproxy.cpp b/src/modules/netlib/netlibhttpproxy.cpp deleted file mode 100644 index 892554542d..0000000000 --- a/src/modules/netlib/netlibhttpproxy.cpp +++ /dev/null @@ -1,459 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "..\..\core\commonheaders.h" -#include "netlib.h" - -typedef enum -{ - reqHelloGet, - reqOldGet, - reqOldPost, - reqNewPost, -} -RequestType; - -static int HttpGatewayReadSetResult(NetlibConnection *nlc, char *buf, int num, int peek) -{ - if (nlc->dataBufferLen == 0) return 0; - - int bytes = min(num, nlc->dataBufferLen); - int rbytes = nlc->dataBufferLen - bytes; - - memcpy(buf, nlc->dataBuffer, bytes); - if (!peek) { - memmove(nlc->dataBuffer, nlc->dataBuffer + bytes, rbytes); - nlc->dataBufferLen = rbytes; - } - - return bytes; -} - -void HttpGatewayRemovePacket(NetlibConnection *nlc, int pck) -{ - mir_cslock lck(nlc->csHttpSequenceNums); - while (pck-- && nlc->pHttpProxyPacketQueue != NULL) { - NetlibHTTPProxyPacketQueue *p = nlc->pHttpProxyPacketQueue; - nlc->pHttpProxyPacketQueue = nlc->pHttpProxyPacketQueue->next; - - mir_free(p->dataBuffer); - mir_free(p); - } -} - -static bool NetlibHttpGatewaySend(NetlibConnection *nlc, RequestType reqType, const char *buf, int len) -{ - NETLIBHTTPREQUEST nlhrSend = { 0 }; - char szUrl[512]; - - nlhrSend.cbSize = sizeof(nlhrSend); - nlhrSend.nlc = nlc; - - nlhrSend.pData = (char*)buf; - nlhrSend.dataLength = len; - - nlhrSend.flags = NLHRF_GENERATEHOST | NLHRF_DUMPPROXY | NLHRF_SMARTAUTHHEADER | NLHRF_NOPROXY | NLHRF_REDIRECT; - if (nlc->nlhpi.flags & NLHPIF_HTTP11) - nlhrSend.flags |= NLHRF_HTTP11; - - switch (reqType) { - case reqHelloGet: - nlhrSend.requestType = REQUEST_GET; - nlhrSend.szUrl = nlc->nlu->user.szHttpGatewayHello; - break; - - case reqOldGet: - nlhrSend.requestType = REQUEST_GET; - nlhrSend.timeout = -1; - if ((nlc->nlhpi.flags & NLHPIF_USEGETSEQUENCE) && (nlc->nlhpi.szHttpGetUrl != NULL)) { - mir_cslock lck(nlc->csHttpSequenceNums); - mir_snprintf(szUrl, "%s%u", nlc->nlhpi.szHttpGetUrl, nlc->nlhpi.firstGetSequence++); - if (nlc->nlhpi.flags & NLHPIF_GETPOSTSAMESEQUENCE) - nlc->nlhpi.firstPostSequence++; - nlhrSend.szUrl = szUrl; - } - else nlhrSend.szUrl = nlc->nlhpi.szHttpGetUrl; - break; - - case reqOldPost: - nlhrSend.requestType = REQUEST_POST; - if ((nlc->nlhpi.flags & NLHPIF_USEPOSTSEQUENCE) && (nlc->nlhpi.szHttpPostUrl != NULL)) { - mir_snprintf(szUrl, "%s%u", nlc->nlhpi.szHttpPostUrl, nlc->nlhpi.firstPostSequence); - nlhrSend.szUrl = szUrl; - } - else nlhrSend.szUrl = nlc->nlhpi.szHttpPostUrl; - break; - - case reqNewPost: - nlhrSend.requestType = REQUEST_POST; - nlhrSend.szUrl = nlc->nlhpi.szHttpPostUrl; - break; - } - - if (nlc->usingDirectHttpGateway) { - NETLIBOPENCONNECTION nloc; - NetlibConnFromUrl(nlhrSend.szUrl, false, nloc); - - bool sameHost = mir_strcmp(nlc->nloc.szHost, nloc.szHost) == 0 && nlc->nloc.wPort == nloc.wPort; - if (!sameHost) { - NetlibDoClose(nlc); - - mir_free((char*)nlc->nloc.szHost); - nlc->nloc = nloc; - if (!NetlibDoConnect(nlc)) - return false; - } - else mir_free((char*)nloc.szHost); - } - - nlhrSend.headersCount = 3; - nlhrSend.headers = (NETLIBHTTPHEADER*)alloca(sizeof(NETLIBHTTPHEADER) * nlhrSend.headersCount); - nlhrSend.headers[0].szName = "User-Agent"; - nlhrSend.headers[0].szValue = nlc->nlu->user.szHttpGatewayUserAgent; - nlhrSend.headers[1].szName = "Cache-Control"; - nlhrSend.headers[1].szValue = "no-cache, no-store "; - nlhrSend.headers[2].szName = "Pragma"; - nlhrSend.headers[2].szValue = "no-cache"; - return NetlibHttpSendRequest((WPARAM)nlc, (LPARAM)&nlhrSend) != SOCKET_ERROR; -} - -static bool NetlibHttpGatewayStdPost(NetlibConnection *nlc, int &numPackets) -{ - int np = 0, len = 0; - char *buf; - NetlibHTTPProxyPacketQueue *p; - { - mir_cslock lck(nlc->csHttpSequenceNums); - - for (p = nlc->pHttpProxyPacketQueue; p != NULL && np < nlc->nlhpi.combinePackets; p = p->next) { - np++; - len += p->dataBufferLen; - } - - int dlen = 0; - buf = (char*)alloca(len); - numPackets = np; - - for (p = nlc->pHttpProxyPacketQueue; np--; p = p->next) { - memcpy(buf + dlen, p->dataBuffer, p->dataBufferLen); - dlen += p->dataBufferLen; - } - } - - return NetlibHttpGatewaySend(nlc, reqNewPost, buf, len); -} - -static bool NetlibHttpGatewayOscarPost(NetlibConnection *nlc, const char *buf, int len, int flags) -{ - NetlibConnection nlcSend = { 0 }; - nlcSend.handleType = NLH_CONNECTION; - nlcSend.nlu = nlc->nlu; - nlcSend.nlhpi = nlc->nlhpi; - nlcSend.s = nlc->s2; - nlcSend.usingHttpGateway = nlc->usingHttpGateway; - nlcSend.szProxyServer = nlc->szProxyServer; - nlcSend.wProxyPort = nlc->wProxyPort; - nlcSend.proxyType = nlc->proxyType; - - if (!NetlibReconnect(&nlcSend)) return false; - nlc->s2 = nlcSend.s; - - nlcSend.hOkToCloseEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - NetlibInitializeNestedCS(&nlcSend.ncsRecv); - NetlibInitializeNestedCS(&nlcSend.ncsSend); - - bool res = NetlibHttpGatewaySend(&nlcSend, reqOldPost, buf, len); - if (res) { - NETLIBHTTPREQUEST *nlhrReply = NetlibHttpRecv(&nlcSend, flags | MSG_RAW | MSG_DUMPPROXY, MSG_RAW | MSG_DUMPPROXY); - if (nlhrReply != NULL) { - if (nlhrReply->resultCode != 200) { - NetlibHttpSetLastErrorUsingHttpResult(nlhrReply->resultCode); - res = false; - } - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - } - else res = false; - } - - NetlibDeleteNestedCS(&nlcSend.ncsSend); - NetlibDeleteNestedCS(&nlcSend.ncsRecv); - CloseHandle(nlcSend.hOkToCloseEvent); - - nlc->s2 = nlcSend.s; - mir_free((char*)nlcSend.nloc.szHost); - - mir_cslock lck(nlc->csHttpSequenceNums); - nlc->nlhpi.firstPostSequence++; - if (nlc->nlhpi.flags & NLHPIF_GETPOSTSAMESEQUENCE) - nlc->nlhpi.firstGetSequence++; - - return res; -} - -int NetlibHttpGatewayPost(NetlibConnection *nlc, const char *buf, int len, int flags) -{ - if (nlc->nlhpi.szHttpGetUrl != NULL) - return NetlibHttpGatewayOscarPost(nlc, buf, len, flags) ? len : SOCKET_ERROR; - - /* - * Gena01 - many changes here, do compare against the other version. - * - * Change #1: simplify to use similar code to GET - * Change #2: we need to allow to parse POST reply if szHttpGetUrl is NULL - * Change #3: Keep connection open if we need to. - * - * Impact: NONE! Since currently miranda doesn't allow szHttpGetUrl to be NULL, it will not connect - * with the new plugins that use this code. - */ - - NetlibHTTPProxyPacketQueue *p = (NetlibHTTPProxyPacketQueue*)mir_alloc(sizeof(struct NetlibHTTPProxyPacketQueue)); - p->dataBuffer = (PBYTE)mir_alloc(len); - memcpy(p->dataBuffer, buf, len); - p->dataBufferLen = len; - p->next = NULL; - - /* - * Now check to see where to insert this in our queue - */ - - mir_cslock lck(nlc->csHttpSequenceNums); - if (nlc->pHttpProxyPacketQueue == NULL) - nlc->pHttpProxyPacketQueue = p; - else { - NetlibHTTPProxyPacketQueue *t = nlc->pHttpProxyPacketQueue; - while (t->next != NULL) - t = t->next; - t->next = p; - } - - /* - * Gena01 - fake a Send!! tell 'em all is ok. We catch errors in Recv. - */ - return len; -} - -#define NETLIBHTTP_RETRYCOUNT 3 -#define NETLIBHTTP_RETRYTIMEOUT 2000 - -int NetlibHttpGatewayRecv(NetlibConnection *nlc, char *buf, int len, int flags) -{ - bool peek = (flags & MSG_PEEK) != 0; - - if (nlc->dataBufferLen != 0 && (!peek || nlc->dataBufferLen >= len)) { - return HttpGatewayReadSetResult(nlc, buf, len, peek); - } - - for (int retryCount = 0; retryCount < NETLIBHTTP_RETRYCOUNT;) { - if (nlc->nlhpi.szHttpGetUrl == NULL && retryCount == 0) { - if (nlc->pollingTimeout == 0) nlc->pollingTimeout = 30; - - /* We Need to sleep/wait for the data to send before we do receive */ - for (int pollCount = nlc->pollingTimeout; pollCount--;) { - if (nlc->pHttpProxyPacketQueue != NULL && GetTickCount() - nlc->lastPost > 1000) - break; - - if (nlc->termRequested || (SleepEx(1000, TRUE) && Miranda_Terminated())) - return SOCKET_ERROR; - } - - nlc->lastPost = GetTickCount(); - if (nlc->pHttpProxyPacketQueue == NULL && nlc->nlu->user.pfnHttpGatewayWrapSend != NULL) { - if (nlc->nlu->user.pfnHttpGatewayWrapSend(nlc, (PBYTE)"", 0, MSG_NOHTTPGATEWAYWRAP, NetlibSend) == SOCKET_ERROR) - return SOCKET_ERROR; - } - } - - int numPackets = 0; - if (nlc->nlhpi.szHttpGetUrl) { - if (!NetlibHttpGatewaySend(nlc, reqOldGet, NULL, 0)) { - if (GetLastError() == ERROR_ACCESS_DENIED || nlc->termRequested) - break; - - ++retryCount; - continue; - } - } - else { - if (!NetlibHttpGatewayStdPost(nlc, numPackets)) { - if (GetLastError() == ERROR_ACCESS_DENIED || nlc->termRequested) - break; - - ++retryCount; - continue; - } - } - NETLIBHTTPREQUEST *nlhrReply = NetlibHttpRecv(nlc, flags | MSG_RAW | MSG_DUMPPROXY, MSG_RAW | MSG_DUMPPROXY); - if (nlhrReply == NULL) return SOCKET_ERROR; - - if (nlc->nlu->user.pfnHttpGatewayUnwrapRecv && !(flags & MSG_NOHTTPGATEWAYWRAP)) { - nlhrReply->pData = (char*)nlc->nlu->user.pfnHttpGatewayUnwrapRecv(nlhrReply, - (PBYTE)nlhrReply->pData, nlhrReply->dataLength, &nlhrReply->dataLength, mir_realloc); - } - - if (nlhrReply->resultCode >= 300) { - int resultCode = nlhrReply->resultCode; - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - - if (nlc->nlhpi.szHttpGetUrl && resultCode != 404) { - NetlibLogf(nlc->nlu, "Error received from proxy, retrying"); - continue; - } - else { - NetlibLogf(nlc->nlu, "Error received from proxy, retry attempts exceeded (%u)", retryCount); - SetLastError(ERROR_GEN_FAILURE); - return SOCKET_ERROR; - } - } - else { - retryCount = 0; - HttpGatewayRemovePacket(nlc, numPackets); - } - - if (nlhrReply->dataLength) { - if (peek) { - int rbytes = nlc->dataBufferLen + nlhrReply->dataLength; - - nlc->dataBuffer = (PBYTE)mir_realloc(nlc->dataBuffer, rbytes); - memcpy(nlc->dataBuffer + nlc->dataBufferLen, nlhrReply->pData, nlhrReply->dataLength); - nlc->dataBufferLen = rbytes; - - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - - return HttpGatewayReadSetResult(nlc, buf, len, peek); - } - else { - int bytes = min(len, nlhrReply->dataLength); - int rbytes = nlhrReply->dataLength - bytes; - - memcpy(buf, nlhrReply->pData, bytes); - - nlc->dataBuffer = (PBYTE)mir_realloc(nlc->dataBuffer, rbytes); - if (rbytes) memcpy(nlc->dataBuffer, nlhrReply->pData + bytes, rbytes); - nlc->dataBufferLen = rbytes; - - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - return bytes; - } - } - else { - if ((peek && nlc->dataBufferLen != 0) || nlhrReply->pData) { - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - return HttpGatewayReadSetResult(nlc, buf, len, peek); - } - } - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - } - - SetLastError(ERROR_GEN_FAILURE); - return SOCKET_ERROR; -} - -int NetlibInitHttpConnection(NetlibConnection *nlc, NetlibUser *nlu, NETLIBOPENCONNECTION *nloc) -{ - NETLIBHTTPREQUEST *nlhrReply = NULL; - { - mir_cslock lck(nlc->csHttpSequenceNums); - nlc->nlhpi.firstGetSequence = 1; - nlc->nlhpi.firstPostSequence = 1; - } - - if (nlu->user.szHttpGatewayHello != NULL) { - nlc->usingHttpGateway = true; - if (NetlibHttpGatewaySend(nlc, reqHelloGet, NULL, 0)) - nlhrReply = NetlibHttpRecv(nlc, MSG_DUMPPROXY | MSG_RAW, MSG_DUMPPROXY | MSG_RAW); - nlc->usingHttpGateway = false; - if (nlhrReply == NULL) return 0; - - if (nlhrReply->resultCode != 200) { - NetlibHttpSetLastErrorUsingHttpResult(nlhrReply->resultCode); - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - return 0; - } - } - if (!nlu->user.pfnHttpGatewayInit(nlc, nloc, nlhrReply)) { - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - return 0; - } - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - - /* - * Gena01 - Ok, we should be able to use just POST. Needed for Yahoo, NO GET requests - */ - if (nlc->nlhpi.szHttpPostUrl == NULL) { - SetLastError(ERROR_BAD_FORMAT); - return 0; - } - - nlc->usingHttpGateway = true; - - //now properly connected - if (nlu->user.pfnHttpGatewayBegin && !nlu->user.pfnHttpGatewayBegin(nlc, nloc)) - return 0; - - return 1; -} - -INT_PTR NetlibHttpGatewaySetInfo(WPARAM wParam, LPARAM lParam) -{ - NETLIBHTTPPROXYINFO *nlhpi = (NETLIBHTTPPROXYINFO*)lParam; - NetlibConnection *nlc = (struct NetlibConnection*)wParam; - - if (GetNetlibHandleType(nlc) != NLH_CONNECTION || nlhpi == NULL || - nlhpi->cbSize < (sizeof(NETLIBHTTPPROXYINFO) - sizeof(int)) || - nlhpi->szHttpPostUrl == NULL) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - mir_free(nlc->nlhpi.szHttpGetUrl); - mir_free(nlc->nlhpi.szHttpPostUrl); - - nlc->nlhpi.combinePackets = 1; - memcpy(&nlc->nlhpi, nlhpi, min(nlhpi->cbSize, sizeof(*nlhpi))); - if (nlc->nlhpi.combinePackets == 0) nlc->nlhpi.combinePackets = 1; - - nlc->nlhpi.szHttpGetUrl = mir_strdup(nlc->nlhpi.szHttpGetUrl); - nlc->nlhpi.szHttpPostUrl = mir_strdup(nlc->nlhpi.szHttpPostUrl); - - return 1; -} - -INT_PTR NetlibHttpSetSticky(WPARAM wParam, LPARAM lParam) -{ - NetlibUser * nu = (NetlibUser*)wParam; - if (GetNetlibHandleType(nu) != NLH_USER) return ERROR_INVALID_PARAMETER; - mir_free(nu->szStickyHeaders); - nu->szStickyHeaders = mir_strdup((char*)lParam); // pointer is ours - return 0; -} - -INT_PTR NetlibHttpSetPollingTimeout(WPARAM wParam, LPARAM lParam) -{ - int oldTimeout; - NetlibConnection *nlc = (struct NetlibConnection*)wParam; - if (GetNetlibHandleType(nlc) != NLH_CONNECTION) return -1; - oldTimeout = nlc->pollingTimeout; - nlc->pollingTimeout = lParam; - return oldTimeout; -} diff --git a/src/modules/netlib/netliblog.cpp b/src/modules/netlib/netliblog.cpp deleted file mode 100644 index 2d3db45941..0000000000 --- a/src/modules/netlib/netliblog.cpp +++ /dev/null @@ -1,532 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "..\..\core\commonheaders.h" -#include "netlib.h" - -#define MS_NETLIB_LOGWIN "Netlib/Log/Win" - -extern HANDLE hConnectionHeaderMutex; - -#define TIMEFORMAT_NONE 0 -#define TIMEFORMAT_HHMMSS 1 -#define TIMEFORMAT_MILLISECONDS 2 -#define TIMEFORMAT_MICROSECONDS 3 -struct { - HWND hwndOpts; - int toOutputDebugString; - int toFile; - int toLog; - int timeFormat; - int showUser; - int dumpSent, dumpRecv, dumpProxy, dumpSsl; - int textDumps, autoDetectText; - CMString tszFile, tszUserFile; -} -static logOptions = { 0 }; - -struct LOGMSG -{ - const char* pszHead; - const char* pszMsg; -}; - -static __int64 mirandaStartTime, perfCounterFreq; -static int bIsActive = TRUE; -static HANDLE hLogEvent = NULL; -static HANDLE hLogger = NULL; - -static void InitLog() -{ - if (hLogger) { - mir_closeLog(hLogger); - hLogger = NULL; - } - - ptrT szBuf(db_get_tsa(NULL, "Netlib", "File")); - if (mir_tstrlen(szBuf)) { - logOptions.tszUserFile = szBuf; - - TCHAR path[MAX_PATH]; - PathToAbsoluteT(VARST(szBuf), path); - logOptions.tszFile = path; - } - else { - db_set_ts(NULL, "Netlib", "File", logOptions.tszUserFile = _T("%miranda_logpath%\\netlog.txt")); - logOptions.tszFile = Utils_ReplaceVarsT(logOptions.tszUserFile); - } - - if (logOptions.toFile) - hLogger = mir_createLog("Netlib", LPGENT("Standard netlib log"), logOptions.tszFile, 0); -} - -static const TCHAR* szTimeFormats[] = -{ - LPGENT("No times"), - LPGENT("Standard hh:mm:ss times"), - LPGENT("Times in milliseconds"), - LPGENT("Times in microseconds") -}; - -static INT_PTR CALLBACK LogOptionsDlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - TCHAR str[MAX_PATH]; - - switch (message) { - case WM_INITDIALOG: - logOptions.hwndOpts = hwndDlg; - TranslateDialogDefault(hwndDlg); - CheckDlgButton(hwndDlg, IDC_DUMPRECV, logOptions.dumpRecv ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_DUMPSENT, logOptions.dumpSent ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_DUMPPROXY, logOptions.dumpProxy ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_DUMPSSL, logOptions.dumpSsl ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_TEXTDUMPS, logOptions.textDumps ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_AUTODETECTTEXT, logOptions.autoDetectText ? BST_CHECKED : BST_UNCHECKED); - { - for (int i=0; i < SIZEOF(szTimeFormats); i++) - SendDlgItemMessage(hwndDlg, IDC_TIMEFORMAT, CB_ADDSTRING, 0, (LPARAM)TranslateTS(szTimeFormats[i])); - } - SendDlgItemMessage(hwndDlg, IDC_TIMEFORMAT, CB_SETCURSEL, logOptions.timeFormat, 0); - CheckDlgButton(hwndDlg, IDC_SHOWNAMES, logOptions.showUser ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_TOOUTPUTDEBUGSTRING, logOptions.toOutputDebugString ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_TOFILE, logOptions.toFile ? BST_CHECKED : BST_UNCHECKED); - SetDlgItemText(hwndDlg, IDC_FILENAME, logOptions.tszUserFile); - SetDlgItemText(hwndDlg, IDC_PATH, logOptions.tszFile); - CheckDlgButton(hwndDlg, IDC_SHOWTHISDLGATSTART, db_get_b(NULL, "Netlib", "ShowLogOptsAtStart", 0) ? BST_CHECKED : BST_UNCHECKED); - { - ptrA szRun(db_get_sa(NULL, "Netlib", "RunAtStart")); - if (szRun) - SetDlgItemTextA(hwndDlg, IDC_RUNATSTART, szRun); - - HWND hwndFilter = GetDlgItem(hwndDlg, IDC_FILTER); - SetWindowLongPtr(hwndFilter, GWL_STYLE, GetWindowLongPtr(hwndFilter, GWL_STYLE) | (TVS_NOHSCROLL | TVS_CHECKBOXES)); - - TVINSERTSTRUCT tvis = { 0 }; - tvis.hInsertAfter = TVI_SORT; - tvis.item.mask = TVIF_PARAM | TVIF_TEXT | TVIF_STATE; - tvis.item.stateMask = TVIS_STATEIMAGEMASK; - - for (int i = 0; i < netlibUser.getCount(); i++) { - tvis.item.pszText = netlibUser[i]->user.ptszDescriptiveName; - tvis.item.lParam = i; - tvis.item.state = INDEXTOSTATEIMAGEMASK((netlibUser[i]->toLog) ? 2 : 1); - TreeView_InsertItem(hwndFilter, &tvis); - } - tvis.item.lParam = -1; - tvis.item.pszText = TranslateT("(Miranda core logging)"); - tvis.item.state = INDEXTOSTATEIMAGEMASK((logOptions.toLog) ? 2 : 1); - TreeView_InsertItem(hwndFilter, &tvis); - } - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_FILENAME: - if (HIWORD(wParam) == EN_CHANGE) { - if ((HWND)lParam == GetFocus()) - CheckDlgButton(hwndDlg, IDC_TOFILE, BST_CHECKED); - - TCHAR path[MAX_PATH]; - GetWindowText((HWND)lParam, path, SIZEOF(path)); - - PathToAbsoluteT(VARST(path), path); - SetDlgItemText(hwndDlg, IDC_PATH, path); - } - break; - - case IDC_FILENAMEBROWSE: - case IDC_RUNATSTARTBROWSE: - GetWindowText(GetWindow((HWND)lParam, GW_HWNDPREV), str, SIZEOF(str)); - { - TCHAR filter[200]; - mir_sntprintf(filter, SIZEOF(filter), _T("%s (*)%c*%c"), TranslateT("All files"), 0, 0); - - OPENFILENAME ofn = { 0 }; - ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - ofn.hwndOwner = hwndDlg; - ofn.Flags = OFN_HIDEREADONLY | OFN_DONTADDTORECENT; - if (LOWORD(wParam) == IDC_FILENAMEBROWSE) - ofn.lpstrTitle = TranslateT("Select where log file will be created"); - else { - ofn.Flags |= OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - ofn.lpstrTitle = TranslateT("Select program to be run"); - } - ofn.lpstrFilter = filter; - ofn.lpstrFile = str; - ofn.nMaxFile = SIZEOF(str) - 2; - ofn.nMaxFileTitle = MAX_PATH; - if (LOWORD(wParam) == IDC_FILENAMEBROWSE) { - if (!GetSaveFileName(&ofn)) return 1; - } - else if (!GetOpenFileName(&ofn)) - return 1; - - if (LOWORD(wParam) == IDC_RUNATSTARTBROWSE && _tcschr(str, ' ') != NULL) { - memmove(str + 1, str, ((SIZEOF(str) - 2) * sizeof(TCHAR))); - str[0] = '"'; - mir_tstrcat(str, _T("\"")); - } - SetWindowText(GetWindow((HWND)lParam, GW_HWNDPREV), str); - } - break; - - case IDC_RUNNOW: - GetDlgItemText(hwndDlg, IDC_RUNATSTART, str, SIZEOF(str)); - if (str[0]) { - STARTUPINFO si = { sizeof(si) }; - PROCESS_INFORMATION pi; - CreateProcess(NULL, str, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); - } - break; - - case IDOK: - GetDlgItemText(hwndDlg, IDC_RUNATSTART, str, SIZEOF(str)); - db_set_ts(NULL, "Netlib", "RunAtStart", str); - db_set_b(NULL, "Netlib", "ShowLogOptsAtStart", (BYTE)IsDlgButtonChecked(hwndDlg, IDC_SHOWTHISDLGATSTART)); - - GetDlgItemText(hwndDlg, IDC_FILENAME, str, SIZEOF(str)); - logOptions.tszUserFile = rtrimt(str); - db_set_ts(NULL, "Netlib", "File", str); - - GetDlgItemText(hwndDlg, IDC_PATH, str, SIZEOF(str)); - logOptions.tszFile = rtrimt(str); - - db_set_b(NULL, "Netlib", "DumpRecv", logOptions.dumpRecv = IsDlgButtonChecked(hwndDlg, IDC_DUMPRECV)); - db_set_b(NULL, "Netlib", "DumpSent", logOptions.dumpSent = IsDlgButtonChecked(hwndDlg, IDC_DUMPSENT)); - db_set_b(NULL, "Netlib", "DumpProxy", logOptions.dumpProxy = IsDlgButtonChecked(hwndDlg, IDC_DUMPPROXY)); - db_set_b(NULL, "Netlib", "DumpSsl", logOptions.dumpSsl = IsDlgButtonChecked(hwndDlg, IDC_DUMPSSL)); - db_set_b(NULL, "Netlib", "TextDumps", logOptions.textDumps = IsDlgButtonChecked(hwndDlg, IDC_TEXTDUMPS)); - db_set_b(NULL, "Netlib", "AutoDetectText", logOptions.autoDetectText = IsDlgButtonChecked(hwndDlg, IDC_AUTODETECTTEXT)); - db_set_b(NULL, "Netlib", "TimeFormat", logOptions.timeFormat = SendDlgItemMessage(hwndDlg, IDC_TIMEFORMAT, CB_GETCURSEL, 0, 0)); - db_set_b(NULL, "Netlib", "ShowUser", logOptions.showUser = IsDlgButtonChecked(hwndDlg, IDC_SHOWNAMES)); - db_set_b(NULL, "Netlib", "ToOutputDebugString", logOptions.toOutputDebugString = IsDlgButtonChecked(hwndDlg, IDC_TOOUTPUTDEBUGSTRING)); - db_set_b(NULL, "Netlib", "ToFile", logOptions.toFile = IsDlgButtonChecked(hwndDlg, IDC_TOFILE)); - { - HWND hwndFilter = GetDlgItem(logOptions.hwndOpts, IDC_FILTER); - TVITEM tvi = { 0 }; - BOOL checked; - - tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE | TVIF_TEXT; - tvi.hItem = TreeView_GetRoot(hwndFilter); - - while (tvi.hItem) { - TreeView_GetItem(hwndFilter, &tvi); - checked = ((tvi.state & TVIS_STATEIMAGEMASK) >> 12 == 2); - - if (tvi.lParam == -1) { - logOptions.toLog = checked; - db_set_dw(NULL, "Netlib", "NLlog", checked); - } - else if (tvi.lParam < netlibUser.getCount()) { - netlibUser[tvi.lParam]->toLog = checked; - db_set_dw(NULL, netlibUser[tvi.lParam]->user.szSettingsModule, "NLlog", checked); - } - - tvi.hItem = TreeView_GetNextSibling(hwndFilter, tvi.hItem); - } - } - InitLog(); - // fall through - case IDCANCEL: - DestroyWindow(hwndDlg); - } - break; - - case WM_CLOSE: - DestroyWindow(hwndDlg); - break; - - case WM_DESTROY: - ImageList_Destroy(TreeView_GetImageList(GetDlgItem(hwndDlg, IDC_FILTER), TVSIL_STATE)); - logOptions.hwndOpts = NULL; - break; - } - return FALSE; -} - -void NetlibLogShowOptions(void) -{ - if (logOptions.hwndOpts == NULL) - logOptions.hwndOpts = CreateDialog(hInst, MAKEINTRESOURCE(IDD_NETLIBLOGOPTS), NULL, LogOptionsDlgProc); - SetForegroundWindow(logOptions.hwndOpts); -} - -static INT_PTR ShowOptions(WPARAM, LPARAM) -{ - NetlibLogShowOptions(); - return 0; -} - -static INT_PTR NetlibLog(WPARAM wParam, LPARAM lParam) -{ - if (!bIsActive) - return 0; - - DWORD dwOriginalLastError = GetLastError(); - - NetlibUser *nlu = (NetlibUser*)wParam; - const char *pszMsg = (const char*)lParam; - if ((nlu != NULL && GetNetlibHandleType(nlu) != NLH_USER) || pszMsg == NULL) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - /* if the Netlib user handle is NULL, just pretend its not */ - if (!(nlu != NULL ? nlu->toLog : logOptions.toLog)) - return 1; - - LARGE_INTEGER liTimeNow; - char szTime[32], szHead[128]; - switch (logOptions.timeFormat) { - case TIMEFORMAT_HHMMSS: - GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, NULL, NULL, szTime, SIZEOF(szTime)); - mir_strcat(szTime, " "); - break; - - case TIMEFORMAT_MILLISECONDS: - QueryPerformanceCounter(&liTimeNow); - liTimeNow.QuadPart -= mirandaStartTime; - mir_snprintf(szTime, SIZEOF(szTime), "%I64u.%03I64u ", liTimeNow.QuadPart / perfCounterFreq, - 1000 * (liTimeNow.QuadPart % perfCounterFreq) / perfCounterFreq); - break; - - case TIMEFORMAT_MICROSECONDS: - QueryPerformanceCounter(&liTimeNow); - liTimeNow.QuadPart -= mirandaStartTime; - mir_snprintf(szTime, SIZEOF(szTime), "%I64u.%06I64u ", liTimeNow.QuadPart / perfCounterFreq, - 1000000 * (liTimeNow.QuadPart % perfCounterFreq) / perfCounterFreq); - break; - - default: - szTime[0] = '\0'; - break; - } - - char *szUser = (logOptions.showUser) ? (nlu == NULL ? NULL : nlu->user.szSettingsModule) : NULL; - if (szUser) - mir_snprintf(szHead, SIZEOF(szHead), "[%s%04X] [%s] ", szTime, GetCurrentThreadId(), szUser); - else - mir_snprintf(szHead, SIZEOF(szHead), "[%s%04X] ", szTime, GetCurrentThreadId()); - - if (logOptions.toOutputDebugString) { - if (szHead[0]) - OutputDebugStringA(szHead); - OutputDebugStringA(pszMsg); - OutputDebugStringA("\n"); - } - - if (logOptions.toFile && !logOptions.tszFile.IsEmpty()) { - size_t len = mir_strlen(pszMsg); - mir_writeLogA(hLogger, "%s%s%s", szHead, pszMsg, pszMsg[len-1] == '\n' ? "" : "\r\n"); - } - - LOGMSG logMsg = { szHead, pszMsg }; - NotifyFastHook(hLogEvent, (WPARAM)nlu, (LPARAM)&logMsg); - - SetLastError(dwOriginalLastError); - return 1; -} - -static INT_PTR NetlibLogW(WPARAM wParam, LPARAM lParam) -{ - const wchar_t *pszMsg = (const wchar_t*)lParam; - char* szMsg = Utf8EncodeW(pszMsg); - INT_PTR res = NetlibLog(wParam, (LPARAM)szMsg); - mir_free(szMsg); - return res; -} - -void NetlibLogf(NetlibUser* nlu, const char *fmt, ...) -{ - if (nlu == NULL) { - if (!logOptions.toLog) - return; - } - else if (!nlu->toLog) - return; - - va_list va; - char szText[1024]; - - va_start(va, fmt); - mir_vsnprintf(szText, sizeof(szText), fmt, va); - va_end(va); - - NetlibLog((WPARAM)nlu, (LPARAM)szText); -} - -void NetlibDumpData(NetlibConnection *nlc, PBYTE buf, int len, int sent, int flags) -{ - char szTitleLine[128]; - char *szBuf; - bool useStack = false; - - // This section checks a number of conditions and aborts - // the dump if the data should not be written to the log - - // Check packet flags - if (flags & (MSG_PEEK | MSG_NODUMP)) - return; - - // Check user's log settings - if (!(logOptions.toOutputDebugString || GetSubscribersCount(hLogEvent) != 0 || (logOptions.toFile && !logOptions.tszFile.IsEmpty()))) - return; - if ((sent && !logOptions.dumpSent) || (!sent && !logOptions.dumpRecv)) - return; - if ((flags & MSG_DUMPPROXY) && !logOptions.dumpProxy) - return; - if ((flags & MSG_DUMPSSL) && !logOptions.dumpSsl) - return; - - WaitForSingleObject(hConnectionHeaderMutex, INFINITE); - NetlibUser *nlu = nlc ? nlc->nlu : NULL; - int titleLineLen = mir_snprintf(szTitleLine, SIZEOF(szTitleLine), "(%p:%u) Data %s%s\r\n", - nlc, nlc ? nlc->s : 0, sent ? "sent" : "received", flags & MSG_DUMPPROXY ? " (proxy)" : ""); - ReleaseMutex(hConnectionHeaderMutex); - - // check filter settings - if (nlu == NULL) { - if (!logOptions.toLog) - return; - } - else if (!nlu->toLog) - return; - - bool isText = true; - if (!logOptions.textDumps) - isText = false; - else if (!(flags & MSG_DUMPASTEXT)) { - if (logOptions.autoDetectText) { - for (int i = 0; i < len; i++) { - if ((buf[i] < ' ' && buf[i] != '\t' && buf[i] != '\r' && buf[i] != '\n') || buf[i] >= 0x80) { - isText = false; - break; - } - } - } - else isText = false; - } - - // Text data - if (isText) { - int sz = titleLineLen + len + 1; - useStack = sz <= 8192; - szBuf = (char*)(useStack ? alloca(sz) : mir_alloc(sz)); - memcpy(szBuf, szTitleLine, titleLineLen); - memcpy(szBuf + titleLineLen, (const char*)buf, len); - szBuf[titleLineLen + len] = '\0'; - } - // Binary data - else { - int line, col, colsInLine; - int sz = titleLineLen + ((len + 16) >> 4) * 78 + 1; - useStack = sz <= 8192; - - szBuf = (char*)(useStack ? alloca(sz) : mir_alloc(sz)); - memcpy(szBuf, szTitleLine, titleLineLen); - char *pszBuf = szBuf + titleLineLen; - for (line = 0;; line += 16) { - colsInLine = min(16, len - line); - - if (colsInLine == 16) { - PBYTE p = buf + line; - pszBuf += wsprintfA( - pszBuf, "%08X: %02X %02X %02X %02X-%02X %02X %02X %02X-%02X %02X %02X %02X-%02X %02X %02X %02X ", - line, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); //!!!!!!!!!! - } - else { - pszBuf += wsprintfA(pszBuf, "%08X: ", line); //!!!!!!!!!! - // Dump data as hex - for (col = 0; col < colsInLine; col++) - pszBuf += wsprintfA(pszBuf, "%02X%c", buf[line + col], ((col & 3) == 3 && col != 15) ? '-' : ' '); //!!!!!!!!!! - // Fill out last line with blanks - for (; col < 16; col++) { - mir_strcpy(pszBuf, " "); - pszBuf += 3; - } - *pszBuf++ = ' '; - } - - for (col = 0; col < colsInLine; col++) - *pszBuf++ = (buf[line + col] < ' ') ? '.' : (char)buf[line + col]; - - if (len - line <= 16) - break; - - *pszBuf++ = '\r'; // End each line with a break - *pszBuf++ = '\n'; // End each line with a break - } - *pszBuf = '\0'; - } - - NetlibLog((WPARAM)nlu, (LPARAM)szBuf); - if (!useStack) - mir_free(szBuf); -} - -void NetlibLogInit(void) -{ - LARGE_INTEGER li; - QueryPerformanceFrequency(&li); - perfCounterFreq = li.QuadPart; - QueryPerformanceCounter(&li); - mirandaStartTime = li.QuadPart; - - CreateServiceFunction(MS_NETLIB_LOGWIN, ShowOptions); - CreateServiceFunction(MS_NETLIB_LOG, NetlibLog); - CreateServiceFunction(MS_NETLIB_LOGW, NetlibLogW); - hLogEvent = CreateHookableEvent(ME_NETLIB_FASTDUMP); - - logOptions.dumpRecv = db_get_b(NULL, "Netlib", "DumpRecv", 1); - logOptions.dumpSent = db_get_b(NULL, "Netlib", "DumpSent", 1); - logOptions.dumpProxy = db_get_b(NULL, "Netlib", "DumpProxy", 1); - logOptions.dumpSsl = db_get_b(NULL, "Netlib", "DumpSsl", 0); - logOptions.textDumps = db_get_b(NULL, "Netlib", "TextDumps", 1); - logOptions.autoDetectText = db_get_b(NULL, "Netlib", "AutoDetectText", 1); - logOptions.timeFormat = db_get_b(NULL, "Netlib", "TimeFormat", TIMEFORMAT_HHMMSS); - logOptions.showUser = db_get_b(NULL, "Netlib", "ShowUser", 1); - logOptions.toOutputDebugString = db_get_b(NULL, "Netlib", "ToOutputDebugString", 0); - logOptions.toFile = db_get_b(NULL, "Netlib", "ToFile", 0); - logOptions.toLog = db_get_dw(NULL, "Netlib", "NLlog", 1); - - InitLog(); - - if (db_get_b(NULL, "Netlib", "ShowLogOptsAtStart", 0)) - NetlibLogShowOptions(); - - ptrT szBuf(db_get_tsa(NULL, "Netlib", "RunAtStart")); - if (szBuf) { - STARTUPINFO si = { sizeof(si) }; - PROCESS_INFORMATION pi; - CreateProcess(NULL, szBuf, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); - } -} - -void NetlibLogShutdown(void) -{ - bIsActive = FALSE; - DestroyHookableEvent(hLogEvent); hLogEvent = NULL; - if (IsWindow(logOptions.hwndOpts)) - DestroyWindow(logOptions.hwndOpts); -} diff --git a/src/modules/netlib/netlibopenconn.cpp b/src/modules/netlib/netlibopenconn.cpp deleted file mode 100644 index 1eb1ba633c..0000000000 --- a/src/modules/netlib/netlibopenconn.cpp +++ /dev/null @@ -1,890 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "..\..\core\commonheaders.h" -#include "netlib.h" - -extern mir_cs csNetlibUser; -extern HANDLE hConnectionOpenMutex; -extern DWORD g_LastConnectionTick; -extern int connectionTimeout; -static int iUPnPCleanup = 0; - -#define RECV_DEFAULT_TIMEOUT 60000 - -//returns in network byte order -DWORD DnsLookup(NetlibUser *nlu, const char *szHost) -{ - HOSTENT* host; - DWORD ip = inet_addr(szHost); - if (ip != INADDR_NONE) - return ip; - - __try - { - host = gethostbyname(szHost); - if (host) - return *(u_long*)host->h_addr_list[0]; - - NetlibLogf(nlu, "%s %d: %s() for host %s failed (%u)", __FILE__, __LINE__, "gethostbyname", szHost, WSAGetLastError()); - } - __except(EXCEPTION_EXECUTE_HANDLER) {} - - return 0; -} - -int WaitUntilReadable(SOCKET s, DWORD dwTimeout, bool check) -{ - fd_set readfd; - TIMEVAL tv; - - if (s == INVALID_SOCKET) return SOCKET_ERROR; - - tv.tv_sec = dwTimeout / 1000; - tv.tv_usec = (dwTimeout % 1000) * 1000; - - FD_ZERO(&readfd); - FD_SET(s, &readfd); - - int result = select(0, &readfd, 0, 0, &tv); - if (result == 0 && !check) SetLastError(ERROR_TIMEOUT); - return result; -} - -int WaitUntilWritable(SOCKET s, DWORD dwTimeout) -{ - fd_set writefd; - TIMEVAL tv; - - tv.tv_sec = dwTimeout / 1000; - tv.tv_usec = (dwTimeout % 1000) * 1000; - - FD_ZERO(&writefd); - FD_SET(s, &writefd); - - switch(select(0, 0, &writefd, 0, &tv)) { - case 0: - SetLastError(ERROR_TIMEOUT); - case SOCKET_ERROR: - return 0; - } - return 1; -} - -bool RecvUntilTimeout(NetlibConnection *nlc, char *buf, int len, int flags, DWORD dwTimeout) -{ - int nReceived = 0; - DWORD dwTimeNow, dwCompleteTime = GetTickCount() + dwTimeout; - - while ((dwTimeNow = GetTickCount()) < dwCompleteTime) { - if (WaitUntilReadable(nlc->s, dwCompleteTime - dwTimeNow) <= 0) return false; - nReceived = NLRecv(nlc, buf, len, flags); - if (nReceived <= 0) return false; - - buf += nReceived; - len -= nReceived; - if (len <= 0) return true; - } - SetLastError(ERROR_TIMEOUT); - return false; -} - -static int NetlibInitSocks4Connection(NetlibConnection *nlc, NetlibUser *nlu, NETLIBOPENCONNECTION *nloc) -{ - // http://www.socks.nec.com/protocol/socks4.protocol and http://www.socks.nec.com/protocol/socks4a.protocol - if (!nloc || !nloc->szHost || !nloc->szHost[0]) return 0; - - size_t nHostLen = mir_strlen(nloc->szHost) + 1; - size_t nUserLen = nlu->settings.szProxyAuthUser ? mir_strlen(nlu->settings.szProxyAuthUser) + 1 : 1; - size_t len = 8 + nUserLen; - - char* pInit = (char*)alloca(len + nHostLen); - pInit[0] = 4; // SOCKS4 - pInit[1] = 1; //connect - *(PWORD)&pInit[2] = htons(nloc->wPort); - - if (nUserLen <= 1) pInit[8] = 0; - else memcpy(&pInit[8], nlu->settings.szProxyAuthUser, nUserLen); - - //if cannot resolve host, try resolving through proxy (requires SOCKS4a) - DWORD ip = DnsLookup(nlu, nloc->szHost); - *(PDWORD)&pInit[4] = ip ? ip : 0x01000000; - if (!ip) { - memcpy(&pInit[len], nloc->szHost, nHostLen); - len += nHostLen; - } - - if (NLSend(nlc, pInit, (int)len, MSG_DUMPPROXY) == SOCKET_ERROR) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "NLSend", GetLastError()); - return 0; - } - - char reply[8]; - if (!RecvUntilTimeout(nlc, reply, sizeof(reply), MSG_DUMPPROXY, RECV_DEFAULT_TIMEOUT)) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "RecvUntilTimeout", GetLastError()); - return 0; - } - - switch ((BYTE)reply[1]) { - case 90: return 1; - case 91: SetLastError(ERROR_ACCESS_DENIED); break; - case 92: SetLastError(ERROR_CONNECTION_UNAVAIL); break; - case 93: SetLastError(ERROR_INVALID_ACCESS); break; - default: SetLastError(ERROR_INVALID_DATA); break; - } - NetlibLogf(nlu, "%s %d: Proxy connection failed (%x %u)", __FILE__, __LINE__, (BYTE)reply[1], GetLastError()); - return 0; -} - -static int NetlibInitSocks5Connection(NetlibConnection *nlc, NetlibUser *nlu, NETLIBOPENCONNECTION *nloc) -{ - //rfc1928 - BYTE buf[258]; - - buf[0] = 5; //yep, socks5 - buf[1] = 1; //one auth method - buf[2] = nlu->settings.useProxyAuth?2:0; - if (NLSend(nlc, (char*)buf, 3, MSG_DUMPPROXY) == SOCKET_ERROR) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "NLSend", GetLastError()); - return 0; - } - - //confirmation of auth method - if (!RecvUntilTimeout(nlc, (char*)buf, 2, MSG_DUMPPROXY, RECV_DEFAULT_TIMEOUT)) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "RecvUntilTimeout", GetLastError()); - return 0; - } - if ((buf[1] != 0 && buf[1] != 2)) { - SetLastError(ERROR_INVALID_ID_AUTHORITY); - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "NLRecv", GetLastError()); - return 0; - } - - if (buf[1] == 2) { //rfc1929 - size_t nUserLen = mir_strlen(nlu->settings.szProxyAuthUser); - size_t nPassLen = mir_strlen(nlu->settings.szProxyAuthPassword); - PBYTE pAuthBuf = (PBYTE)mir_alloc(3 + nUserLen + nPassLen); - pAuthBuf[0] = 1; //auth version - pAuthBuf[1] = (BYTE)nUserLen; - memcpy(pAuthBuf + 2, nlu->settings.szProxyAuthUser, nUserLen); - pAuthBuf[2 + nUserLen] = (BYTE)nPassLen; - memcpy(pAuthBuf + 3 + nUserLen, nlu->settings.szProxyAuthPassword, nPassLen); - if (NLSend(nlc, (char*)pAuthBuf, int(3 + nUserLen + nPassLen), MSG_DUMPPROXY) == SOCKET_ERROR) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "NLSend", GetLastError()); - mir_free(pAuthBuf); - return 0; - } - mir_free(pAuthBuf); - - if (!RecvUntilTimeout(nlc, (char*)buf, 2, MSG_DUMPPROXY, RECV_DEFAULT_TIMEOUT)) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "RecvUntilTimeout", GetLastError()); - return 0; - } - if (buf[1]) { - SetLastError(ERROR_ACCESS_DENIED); - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "RecvUntilTimeout", GetLastError()); - return 0; - } - } - - size_t nHostLen; - DWORD hostIP; - - if (nlc->dnsThroughProxy) { - hostIP = inet_addr(nloc->szHost); - nHostLen = (hostIP == INADDR_NONE) ? mir_strlen(nloc->szHost) + 1 : 4; - } - else { - hostIP = DnsLookup(nlu, nloc->szHost); - if (hostIP == 0) - return 0; - nHostLen = 4; - } - PBYTE pInit = (PBYTE)mir_alloc(6 + nHostLen); - pInit[0] = 5; //SOCKS5 - pInit[1] = nloc->flags & NLOCF_UDP ? 3 : 1; //connect or UDP - pInit[2] = 0; //reserved - if (hostIP == INADDR_NONE) { //DNS lookup through proxy - pInit[3] = 3; - pInit[4] = BYTE(nHostLen - 1); - memcpy(pInit + 5, nloc->szHost, nHostLen - 1); - } - else { - pInit[3] = 1; - *(PDWORD)(pInit + 4) = hostIP; - } - *(PWORD)(pInit + 4 + nHostLen) = htons(nloc->wPort); - if (NLSend(nlc, (char*)pInit, int(6 + nHostLen), MSG_DUMPPROXY) == SOCKET_ERROR) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "NLSend", GetLastError()); - mir_free(pInit); - return 0; - } - mir_free(pInit); - - if (!RecvUntilTimeout(nlc, (char*)buf, 5, MSG_DUMPPROXY, RECV_DEFAULT_TIMEOUT)) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "RecvUntilTimeout", GetLastError()); - return 0; - } - - if (buf[0] != 5 || buf[1]) { - const char* err = "Unknown response"; - if (buf[0] != 5) - SetLastError(ERROR_BAD_FORMAT); - else { - switch (buf[1]) { - case 1: SetLastError(ERROR_GEN_FAILURE); err = "General failure"; break; - case 2: SetLastError(ERROR_ACCESS_DENIED); err = "Connection not allowed by ruleset"; break; - case 3: SetLastError(WSAENETUNREACH); err = "Network unreachable"; break; - case 4: SetLastError(WSAEHOSTUNREACH); err = "Host unreachable"; break; - case 5: SetLastError(WSAECONNREFUSED); err = "Connection refused by destination host"; break; - case 6: SetLastError(WSAETIMEDOUT); err = "TTL expired"; break; - case 7: SetLastError(ERROR_CALL_NOT_IMPLEMENTED); err = "Command not supported / protocol error"; break; - case 8: SetLastError(ERROR_INVALID_ADDRESS); err = "Address type not supported"; break; - default: SetLastError(ERROR_INVALID_DATA); break; - } - } - NetlibLogf(nlu, "%s %d: Proxy conection failed. %s.", __FILE__, __LINE__, err); - return 0; - } - - int nRecvSize = 0; - switch (buf[3]) { - case 1:// ipv4 addr - nRecvSize = 5; - break; - case 3:// dns name addr - nRecvSize = buf[4] + 2; - break; - case 4:// ipv6 addr - nRecvSize = 17; - break; - default: - NetlibLogf(nlu, "%s %d: %s() unknown address type (%u)", __FILE__, __LINE__, "NetlibInitSocks5Connection", (int)buf[3]); - return 0; - } - if (!RecvUntilTimeout(nlc, (char*)buf, nRecvSize, MSG_DUMPPROXY, RECV_DEFAULT_TIMEOUT)) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "RecvUntilTimeout", GetLastError()); - return 0; - } - - //connected - return 1; -} - -static bool NetlibInitHttpsConnection(NetlibConnection *nlc, NetlibUser *nlu, NETLIBOPENCONNECTION *nloc) -{ - //rfc2817 - NETLIBHTTPREQUEST nlhrSend = { 0 }; - char szUrl[512]; - - nlhrSend.cbSize = sizeof(nlhrSend); - nlhrSend.requestType = REQUEST_CONNECT; - nlhrSend.flags = NLHRF_GENERATEHOST | NLHRF_DUMPPROXY | NLHRF_SMARTAUTHHEADER | NLHRF_HTTP11 | NLHRF_NOPROXY | NLHRF_REDIRECT; - if (nlc->dnsThroughProxy) - mir_snprintf(szUrl, "%s:%u", nloc->szHost, nloc->wPort); - else { - DWORD ip = DnsLookup(nlu, nloc->szHost); - if (ip == 0) return false; - mir_snprintf(szUrl, "%s:%u", inet_ntoa(*(PIN_ADDR)&ip), nloc->wPort); - } - nlhrSend.szUrl = szUrl; - - nlc->usingHttpGateway = true; - - if (NetlibHttpSendRequest((WPARAM)nlc, (LPARAM)&nlhrSend) == SOCKET_ERROR) { - nlc->usingHttpGateway = false; - return 0; - } - - NETLIBHTTPREQUEST *nlhrReply = NetlibHttpRecv(nlc, MSG_DUMPPROXY | MSG_RAW, MSG_DUMPPROXY | MSG_RAW, true); - nlc->usingHttpGateway = false; - if (nlhrReply == NULL) - return false; - - if (nlhrReply->resultCode < 200 || nlhrReply->resultCode >= 300) { - if (nlhrReply->resultCode == 403 && nlc->dnsThroughProxy) { - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - nlc->dnsThroughProxy = 0; - return NetlibInitHttpsConnection(nlc, nlu, nloc); - } - - NetlibHttpSetLastErrorUsingHttpResult(nlhrReply->resultCode); - NetlibLogf(nlu, "%s %d: %s request failed (%u %s)", __FILE__, __LINE__, nlu->settings.proxyType == PROXYTYPE_HTTP ? "HTTP" : "HTTPS", nlhrReply->resultCode, nlhrReply->szResultDescr); - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - return 0; - } - NetlibHttpFreeRequestStruct(0, (LPARAM)nlhrReply); - //connected - return true; -} - -static void FreePartiallyInitedConnection(NetlibConnection *nlc) -{ - DWORD dwOriginalLastError = GetLastError(); - - if (nlc->s != INVALID_SOCKET) closesocket(nlc->s); - mir_free(nlc->nlhpi.szHttpPostUrl); - mir_free(nlc->nlhpi.szHttpGetUrl); - mir_free((char*)nlc->nloc.szHost); - mir_free(nlc->szProxyServer); - NetlibDeleteNestedCS(&nlc->ncsSend); - NetlibDeleteNestedCS(&nlc->ncsRecv); - CloseHandle(nlc->hOkToCloseEvent); - DeleteCriticalSection(&nlc->csHttpSequenceNums); - mir_free(nlc); - SetLastError(dwOriginalLastError); -} - -static bool my_connectIPv4(NetlibConnection *nlc, NETLIBOPENCONNECTION *nloc) -{ - int rc = 0, retrycnt = 0; - u_long notblocking = 1; - DWORD lasterr = 0; - static const TIMEVAL tv = { 1, 0 }; - - // if dwTimeout is zero then its an old style connection or new with a 0 timeout, select() will error quicker anyway - unsigned int dwTimeout = (nloc && (nloc->cbSize == sizeof(NETLIBOPENCONNECTION)) && (nloc->flags & NLOCF_V2) && (nloc->timeout>0)) ? nloc->timeout : 30; - - // this is for XP SP2 where there is a default connection attempt limit of 10/second - if (connectionTimeout) { - WaitForSingleObject(hConnectionOpenMutex, 10000); - int waitdiff = GetTickCount() - g_LastConnectionTick; - if (waitdiff < connectionTimeout) SleepEx(connectionTimeout, TRUE); - g_LastConnectionTick = GetTickCount(); - ReleaseMutex(hConnectionOpenMutex); - - // might of died in between the wait - if (Miranda_Terminated()) return false; - } - - PHOSTENT he; - SOCKADDR_IN sin = { 0 }; - sin.sin_family = AF_INET; - - if (nlc->proxyType) { - if (!nlc->szProxyServer) return false; - - if (nloc) - NetlibLogf(nlc->nlu, "(%p) Connecting to proxy %s:%d for %s:%d ....", nlc, nlc->szProxyServer, nlc->wProxyPort, nloc->szHost, nloc->wPort); - else - NetlibLogf(nlc->nlu, "(%p) Connecting to proxy %s:%d ....", nlc, nlc->szProxyServer, nlc->wProxyPort); - - sin.sin_port = htons(nlc->wProxyPort); - he = gethostbyname(nlc->szProxyServer); - } - else { - if (!nloc || !nloc->szHost || nloc->szHost[0] == '[' || strchr(nloc->szHost, ':')) return false; - NetlibLogf(nlc->nlu, "(%p) Connecting to server %s:%d....", nlc, nloc->szHost, nloc->wPort); - - sin.sin_port = htons(nloc->wPort); - he = gethostbyname(nloc->szHost); - } - - for (char** har = he->h_addr_list; *har && !Miranda_Terminated(); ++har) { - sin.sin_addr.s_addr = *(u_long*)*har; - - char* szIp = NetlibAddressToString((SOCKADDR_INET_M*)&sin); - NetlibLogf(nlc->nlu, "(%p) Connecting to ip %s ....", nlc, szIp); - mir_free(szIp); - -retry: - nlc->s = socket(AF_INET, nloc->flags & NLOCF_UDP ? SOCK_DGRAM : SOCK_STREAM, 0); - if (nlc->s == INVALID_SOCKET) - return false; - - // return the socket to non blocking - if (ioctlsocket(nlc->s, FIONBIO, ¬blocking) != 0) - return false; - - if (nlc->nlu->settings.specifyOutgoingPorts && nlc->nlu->settings.szOutgoingPorts && nlc->nlu->settings.szOutgoingPorts[0]) { - if (!BindSocketToPort(nlc->nlu->settings.szOutgoingPorts, nlc->s, INVALID_SOCKET, &nlc->nlu->inportnum)) - NetlibLogf(nlc->nlu, "Netlib connect: Not enough ports for outgoing connections specified"); - } - - // try a connect - if (connect(nlc->s, (LPSOCKADDR)&sin, sizeof(sin)) == 0) { - rc = 0; - break; - } - - // didn't work, was it cos of nonblocking? - if (WSAGetLastError() != WSAEWOULDBLOCK) { - rc = SOCKET_ERROR; - closesocket(nlc->s); - nlc->s = INVALID_SOCKET; - continue; - } - - while (true) { - fd_set r, w, e; - FD_ZERO(&r); FD_ZERO(&w); FD_ZERO(&e); - FD_SET(nlc->s, &r); - FD_SET(nlc->s, &w); - FD_SET(nlc->s, &e); - if ((rc = select(0, &r, &w, &e, &tv)) == SOCKET_ERROR) - break; - - if (rc > 0) { - if (FD_ISSET(nlc->s, &w)) { - // connection was successful - rc = 0; - } - if (FD_ISSET(nlc->s, &r)) { - // connection was closed - rc = SOCKET_ERROR; - lasterr = WSAECONNRESET; - } - if (FD_ISSET(nlc->s, &e)) { - // connection failed. - int len = sizeof(lasterr); - rc = SOCKET_ERROR; - getsockopt(nlc->s, SOL_SOCKET, SO_ERROR, (char*)&lasterr, &len); - if (lasterr == WSAEADDRINUSE && ++retrycnt <= 2) { - closesocket(nlc->s); - goto retry; - } - } - break; - } - else if (Miranda_Terminated()) { - rc = SOCKET_ERROR; - lasterr = ERROR_TIMEOUT; - break; - } - else if (nloc->cbSize == sizeof(NETLIBOPENCONNECTION) && nloc->flags & NLOCF_V2 && nloc->waitcallback != NULL && nloc->waitcallback(&dwTimeout) == 0) { - rc = SOCKET_ERROR; - lasterr = ERROR_TIMEOUT; - break; - } - if (--dwTimeout == 0) { - rc = SOCKET_ERROR; - lasterr = ERROR_TIMEOUT; - break; - } - } - - if (rc == 0) break; - - closesocket(nlc->s); - nlc->s = INVALID_SOCKET; - } - - notblocking = 0; - if (nlc->s != INVALID_SOCKET) ioctlsocket(nlc->s, FIONBIO, ¬blocking); - if (rc && lasterr) SetLastError(lasterr); - return rc == 0; -} - -static bool my_connectIPv6(NetlibConnection *nlc, NETLIBOPENCONNECTION *nloc) -{ - if (!nloc) - return false; - - int rc = SOCKET_ERROR, retrycnt = 0; - u_long notblocking = 1; - DWORD lasterr = 0; - static const TIMEVAL tv = { 1, 0 }; - unsigned int dwTimeout = (nloc->cbSize == sizeof(NETLIBOPENCONNECTION) && nloc->flags & NLOCF_V2) ? nloc->timeout : 0; - // if dwTimeout is zero then its an old style connection or new with a 0 timeout, select() will error quicker anyway - if (dwTimeout == 0) dwTimeout = 30; - - // this is for XP SP2 where there is a default connection attempt limit of 10/second - if (connectionTimeout) { - WaitForSingleObject(hConnectionOpenMutex, 10000); - int waitdiff = GetTickCount() - g_LastConnectionTick; - if (waitdiff < connectionTimeout) SleepEx(connectionTimeout, TRUE); - g_LastConnectionTick = GetTickCount(); - ReleaseMutex(hConnectionOpenMutex); - - // might of died in between the wait - if (Miranda_Terminated()) return false; - } - - char szPort[6]; - addrinfo *air = NULL, *ai, hints = { 0 }; - - hints.ai_family = AF_UNSPEC; - - if (nloc->flags & NLOCF_UDP) { - hints.ai_socktype = SOCK_DGRAM; - hints.ai_protocol = IPPROTO_UDP; - } - else { - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - } - - if (nlc->proxyType) { - if (!nlc->szProxyServer) - return false; - - NetlibLogf(nlc->nlu, "(%p) Connecting to proxy %s:%d for %s:%d ....", nlc, nlc->szProxyServer, nlc->wProxyPort, nloc->szHost, nloc->wPort); - - _itoa(nlc->wProxyPort, szPort, 10); - if (GetAddrInfoA(nlc->szProxyServer, szPort, &hints, &air)) { - NetlibLogf(nlc->nlu, "%s %d: %s() for host %s failed (%u)", __FILE__, __LINE__, "getaddrinfo", nlc->szProxyServer, WSAGetLastError()); - return false; - } - } - else { - if (!nloc->szHost) - return false; - - NetlibLogf(nlc->nlu, "(%p) Connecting to server %s:%d....", nlc, nloc->szHost, nloc->wPort); - - _itoa(nlc->nloc.wPort, szPort, 10); - - if (GetAddrInfoA(nlc->nloc.szHost, szPort, &hints, &air)) { - NetlibLogf(nlc->nlu, "%s %d: %s() for host %s failed (%u)", __FILE__, __LINE__, "getaddrinfo", nlc->nloc.szHost, WSAGetLastError()); - return false; - } - } - - for (ai = air; ai && !Miranda_Terminated(); ai = ai->ai_next) { - NetlibLogf(nlc->nlu, "(%p) Connecting to ip %s ....", nlc, ptrA(NetlibAddressToString((SOCKADDR_INET_M*)ai->ai_addr))); -retry: - nlc->s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (nlc->s == INVALID_SOCKET) { - FreeAddrInfoA(air); - return false; - } - - // return the socket to non blocking - if (ioctlsocket(nlc->s, FIONBIO, ¬blocking) != 0) { - FreeAddrInfoA(air); - return false; - } - - if (nlc->nlu->settings.specifyOutgoingPorts && nlc->nlu->settings.szOutgoingPorts && nlc->nlu->settings.szOutgoingPorts[0]) { - SOCKET s = ai->ai_family == AF_INET ? nlc->s : INVALID_SOCKET; - SOCKET s6 = ai->ai_family == AF_INET6 ? nlc->s : INVALID_SOCKET; - if (!BindSocketToPort(nlc->nlu->settings.szOutgoingPorts, s, s6, &nlc->nlu->inportnum)) - NetlibLogf(nlc->nlu, "Netlib connect: Not enough ports for outgoing connections specified"); - } - - // try a connect - if (connect(nlc->s, ai->ai_addr, (int)ai->ai_addrlen) == 0) { - rc = 0; - break; - } - - // didn't work, was it cos of nonblocking? - if (WSAGetLastError() != WSAEWOULDBLOCK) { - rc = SOCKET_ERROR; - closesocket(nlc->s); - nlc->s = INVALID_SOCKET; - continue; - } - - while (true) { // timeout loop - fd_set r, w, e; - FD_ZERO(&r); FD_ZERO(&w); FD_ZERO(&e); - FD_SET(nlc->s, &r); - FD_SET(nlc->s, &w); - FD_SET(nlc->s, &e); - if ((rc = select(0, &r, &w, &e, &tv)) == SOCKET_ERROR) - break; - - if (rc > 0) { - if (FD_ISSET(nlc->s, &w)) { - // connection was successful - rc = 0; - lasterr = 0; - } - if (FD_ISSET(nlc->s, &r)) { - // connection was closed - rc = SOCKET_ERROR; - lasterr = WSAECONNRESET; - } - if (FD_ISSET(nlc->s, &e)) { - // connection failed. - int len = sizeof(lasterr); - rc = SOCKET_ERROR; - getsockopt(nlc->s, SOL_SOCKET, SO_ERROR, (char*)&lasterr, &len); - if (lasterr == WSAEADDRINUSE && ++retrycnt <= 2) { - closesocket(nlc->s); - nlc->s = INVALID_SOCKET; - goto retry; - } - } - break; - } - else if (Miranda_Terminated()) { - rc = SOCKET_ERROR; - lasterr = ERROR_TIMEOUT; - break; - } - else if (nloc->cbSize == sizeof(NETLIBOPENCONNECTION) && nloc->flags & NLOCF_V2 && nloc->waitcallback != NULL && nloc->waitcallback(&dwTimeout) == 0) { - rc = SOCKET_ERROR; - lasterr = ERROR_TIMEOUT; - break; - } - if (--dwTimeout == 0) { - rc = SOCKET_ERROR; - lasterr = ERROR_TIMEOUT; - break; - } - } - - if (rc == 0) break; - - closesocket(nlc->s); - nlc->s = INVALID_SOCKET; - } - - FreeAddrInfoA(air); - - notblocking = 0; - if (nlc->s != INVALID_SOCKET) ioctlsocket(nlc->s, FIONBIO, ¬blocking); - if (rc && lasterr) SetLastError(lasterr); - return rc == 0; -} - -static bool my_connect(NetlibConnection *nlc, NETLIBOPENCONNECTION *nloc) -{ - return my_connectIPv6(nlc, nloc); -} - -static int NetlibHttpFallbackToDirect(NetlibConnection *nlc, NetlibUser *nlu, NETLIBOPENCONNECTION *nloc) -{ - NetlibDoClose(nlc, true); - - NetlibLogf(nlu, "Fallback to direct connection"); - - nlc->proxyAuthNeeded = false; - nlc->proxyType = 0; - mir_free(nlc->szProxyServer); nlc->szProxyServer = NULL; - if (!my_connect(nlc, nloc)) { - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "connect", WSAGetLastError()); - return false; - } - return true; -} - -bool NetlibDoConnect(NetlibConnection *nlc) -{ - NETLIBOPENCONNECTION *nloc = &nlc->nloc; - NetlibUser *nlu = nlc->nlu; - - mir_free(nlc->szProxyServer); nlc->szProxyServer = NULL; - - bool usingProxy = false, forceHttps = false; - if (nlu->settings.useProxy) { - if (nlu->settings.proxyType == PROXYTYPE_IE) - usingProxy = NetlibGetIeProxyConn(nlc, false); - else { - if (nlu->settings.szProxyServer && nlu->settings.szProxyServer[0]) { - nlc->szProxyServer = mir_strdup(nlu->settings.szProxyServer); - nlc->wProxyPort = nlu->settings.wProxyPort; - nlc->proxyType = nlu->settings.proxyType; - usingProxy = true; - } - } - } - - while (!my_connect(nlc, nloc)) { - // if connection failed, the state of nlc might be unpredictable - if (GetNetlibHandleType(nlc) == NLH_CONNECTION) { - // Fallback to direct only when using HTTP proxy, as this is what used by companies - // If other type of proxy used it's an indication of security nutcase, leave him alone - if (usingProxy && (nlc->proxyType == PROXYTYPE_HTTPS || nlc->proxyType == PROXYTYPE_HTTP)) { - usingProxy = false; - nlc->proxyType = 0; - NetlibLogf(nlu, "Fallback to direct connection"); - continue; - } - if (nlu->settings.useProxy && !usingProxy && nlu->settings.proxyType == PROXYTYPE_IE && !forceHttps) { - forceHttps = true; - usingProxy = NetlibGetIeProxyConn(nlc, true); - if (usingProxy) - continue; - } - } - NetlibLogf(nlu, "%s %d: %s() failed (%u)", __FILE__, __LINE__, "connect", WSAGetLastError()); - return false; - } - - if (usingProxy && !((nloc->flags & (NLOCF_HTTP | NLOCF_SSL)) == NLOCF_HTTP && (nlc->proxyType == PROXYTYPE_HTTP || nlc->proxyType == PROXYTYPE_HTTPS))) { - if (!WaitUntilWritable(nlc->s, 30000)) - return false; - - switch (nlc->proxyType) { - case PROXYTYPE_SOCKS4: - if (!NetlibInitSocks4Connection(nlc, nlu, nloc)) - return false; - break; - - case PROXYTYPE_SOCKS5: - if (!NetlibInitSocks5Connection(nlc, nlu, nloc)) - return false; - break; - - case PROXYTYPE_HTTPS: - nlc->proxyAuthNeeded = true; - if (!NetlibInitHttpsConnection(nlc, nlu, nloc)) { - usingProxy = false; - if (!NetlibHttpFallbackToDirect(nlc, nlu, nloc)) - return false; - } - break; - - case PROXYTYPE_HTTP: - nlc->proxyAuthNeeded = true; - if (!(nlu->user.flags & NUF_HTTPGATEWAY || nloc->flags & NLOCF_HTTPGATEWAY) || nloc->flags & NLOCF_SSL) { - //NLOCF_HTTP not specified and no HTTP gateway available: try HTTPS - if (!NetlibInitHttpsConnection(nlc, nlu, nloc)) { - //can't do HTTPS: try direct - usingProxy = false; - if (!NetlibHttpFallbackToDirect(nlc, nlu, nloc)) - return false; - } - } - else if (!NetlibInitHttpConnection(nlc, nlu, nloc)) - return false; - - break; - - default: - SetLastError(ERROR_INVALID_PARAMETER); - FreePartiallyInitedConnection(nlc); - return false; - } - } - else if (nloc->flags & NLOCF_HTTPGATEWAY) { - if (!NetlibInitHttpConnection(nlc, nlu, nloc)) return false; - nlc->usingDirectHttpGateway = true; - } - - NetlibLogf(nlu, "(%d) Connected to %s:%d", nlc->s, nloc->szHost, nloc->wPort); - - if (NLOCF_SSL & nloc->flags) - return NetlibStartSsl((WPARAM)nlc, 0) != 0; - - return true; -} - -bool NetlibReconnect(NetlibConnection *nlc) -{ - // a connection might be freed already - if (GetNetlibHandleType(nlc) != NLH_CONNECTION) - return false; - - char buf[4]; - bool opened = nlc->s != INVALID_SOCKET; - if (opened) { - switch (WaitUntilReadable(nlc->s, 0, true)) { - case SOCKET_ERROR: - opened = false; - break; - - case 0: - opened = true; - break; - - case 1: - opened = recv(nlc->s, buf, 1, MSG_PEEK) > 0; - break; - } - - if (!opened) - NetlibDoClose(nlc, true); - } - - if (!opened) { - if (Miranda_Terminated()) - return false; - - if (nlc->usingHttpGateway) { - nlc->proxyAuthNeeded = true; - return my_connect(nlc, &nlc->nloc); - } - return NetlibDoConnect(nlc); - } - return true; -} - -INT_PTR NetlibOpenConnection(WPARAM wParam, LPARAM lParam) -{ - NETLIBOPENCONNECTION *nloc = (NETLIBOPENCONNECTION*)lParam; - if (nloc == NULL || nloc->cbSize != sizeof(NETLIBOPENCONNECTION) || nloc->szHost == NULL || nloc->wPort == 0) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } - - NetlibUser *nlu = (NetlibUser*)wParam; - if (GetNetlibHandleType(nlu) != NLH_USER || !(nlu->user.flags & NUF_OUTGOING)) - return 0; - - NetlibLogf(nlu, "Connection request to %s:%d (Flags %x)....", nloc->szHost, nloc->wPort, nloc->flags); - - NetlibConnection *nlc = (NetlibConnection*)mir_calloc(sizeof(struct NetlibConnection)); - nlc->handleType = NLH_CONNECTION; - nlc->nlu = nlu; - nlc->nloc = *nloc; - nlc->nloc.szHost = mir_strdup(nloc->szHost); - nlc->s = INVALID_SOCKET; - nlc->s2 = INVALID_SOCKET; - nlc->dnsThroughProxy = nlu->settings.dnsThroughProxy != 0; - - InitializeCriticalSection(&nlc->csHttpSequenceNums); - nlc->hOkToCloseEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - nlc->dontCloseNow = 0; - NetlibInitializeNestedCS(&nlc->ncsSend); - NetlibInitializeNestedCS(&nlc->ncsRecv); - - if (!NetlibDoConnect(nlc)) { - FreePartiallyInitedConnection(nlc); - return 0; - } - - if (iUPnPCleanup == 0) { - mir_cslock lck(csNetlibUser); - if (iUPnPCleanup == 0) { - iUPnPCleanup = 1; - forkthread(NetlibUPnPCleanup, 0, NULL); - } - } - - return (INT_PTR)nlc; -} - -INT_PTR NetlibStartSsl(WPARAM wParam, LPARAM lParam) -{ - NetlibConnection *nlc = (NetlibConnection*)wParam; - if (nlc == NULL) - return 0; - - NETLIBSSL *sp = (NETLIBSSL*)lParam; - const char *szHost = sp ? sp->host : nlc->nloc.szHost; - - NetlibLogf(nlc->nlu, "(%d %s) Starting SSL negotiation", nlc->s, szHost); - nlc->hSsl = si.connect(nlc->s, szHost, nlc->nlu->settings.validateSSL); - - if (nlc->hSsl == NULL) - NetlibLogf(nlc->nlu, "(%d %s) Failure to negotiate SSL connection", nlc->s, szHost); - else - NetlibLogf(nlc->nlu, "(%d %s) SSL negotiation successful", nlc->s, szHost); - - return nlc->hSsl != NULL; -} diff --git a/src/modules/netlib/netlibopts.cpp b/src/modules/netlib/netlibopts.cpp deleted file mode 100644 index fff81944d3..0000000000 --- a/src/modules/netlib/netlibopts.cpp +++ /dev/null @@ -1,530 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "..\..\core\commonheaders.h" -#include "netlib.h" - -struct NetlibTempSettings -{ - DWORD flags; - char *szSettingsModule; - NETLIBUSERSETTINGS settings; -}; - -static LIST tempSettings(5); - -static const UINT outgoingConnectionsControls[] = -{ - IDC_STATIC12, - IDC_USEPROXY, - IDC_STATIC21, IDC_PROXYTYPE, - IDC_STATIC22, IDC_PROXYHOST, IDC_STATIC23, IDC_PROXYPORT, IDC_STOFTENPORT, - IDC_PROXYAUTH, - IDC_STATIC31, IDC_PROXYUSER, IDC_STATIC32, IDC_PROXYPASS, - IDC_PROXYDNS, - IDC_SPECIFYPORTSO, - IDC_PORTSRANGEO, - IDC_STATIC54, - IDC_VALIDATESSL}; -static const UINT useProxyControls[] = { - IDC_STATIC21, IDC_PROXYTYPE, - IDC_STATIC22, IDC_PROXYHOST, IDC_STATIC23, IDC_PROXYPORT, IDC_STOFTENPORT, - IDC_PROXYAUTH, - IDC_STATIC31, IDC_PROXYUSER, IDC_STATIC32, IDC_PROXYPASS, - IDC_PROXYDNS}; -static const UINT specifyOPortsControls[] = { - IDC_PORTSRANGEO, - IDC_STATIC54 -}; -static const UINT incomingConnectionsControls[] = { - IDC_STATIC43, - IDC_SPECIFYPORTS, - IDC_PORTSRANGE, - IDC_STATIC52, - IDC_ENABLEUPNP}; -static const UINT specifyPortsControls[] = { - IDC_PORTSRANGE, - IDC_STATIC52}; - -static const TCHAR* szProxyTypes[] = {LPGENT(""), _T("SOCKS4"), _T("SOCKS5"), _T("HTTP"), _T("HTTPS"), _T("Internet Explorer")}; -static const WORD oftenProxyPorts[] = {1080, 1080, 1080, 8080, 8080, 8080}; - -#define M_REFRESHALL (WM_USER+100) -#define M_REFRESHENABLING (WM_USER+101) - -static void ShowMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state) -{ - for (int i = 0; i < cControls; i++) - ShowWindow(GetDlgItem(hwndDlg, controls[i]), state); -} - -static void EnableMultipleControls(HWND hwndDlg, const UINT *controls, int cControls, int state) -{ - for (int i = 0; i < cControls; i++) - EnableWindow(GetDlgItem(hwndDlg, controls[i]), state); -} - -static void AddProxyTypeItem(HWND hwndDlg, int type, int selectType) -{ - int i = SendDlgItemMessage(hwndDlg, IDC_PROXYTYPE, CB_ADDSTRING, 0, (LPARAM)(type == 0 ? TranslateTS(szProxyTypes[type]) : szProxyTypes[type])); - SendDlgItemMessage(hwndDlg, IDC_PROXYTYPE, CB_SETITEMDATA, i, type); - if (type == selectType) - SendDlgItemMessage(hwndDlg, IDC_PROXYTYPE, CB_SETCURSEL, i, 0); -} - -static void CopySettingsStruct(NETLIBUSERSETTINGS *dest, NETLIBUSERSETTINGS *source) -{ - *dest = *source; - if (dest->szIncomingPorts) dest->szIncomingPorts = mir_strdup(dest->szIncomingPorts); - if (dest->szOutgoingPorts) dest->szOutgoingPorts = mir_strdup(dest->szOutgoingPorts); - if (dest->szProxyAuthPassword) dest->szProxyAuthPassword = mir_strdup(dest->szProxyAuthPassword); - if (dest->szProxyAuthUser) dest->szProxyAuthUser = mir_strdup(dest->szProxyAuthUser); - if (dest->szProxyServer) dest->szProxyServer = mir_strdup(dest->szProxyServer); -} - -static void CombineSettingsStrings(char **dest, char **source) -{ - if (*dest != NULL && (*source == NULL || mir_strcmpi(*dest, *source))) { mir_free(*dest); *dest = NULL; } -} - -static void CombineSettingsStructs(NETLIBUSERSETTINGS *dest, DWORD *destFlags, NETLIBUSERSETTINGS *source, DWORD sourceFlags) -{ - if (sourceFlags&NUF_OUTGOING) { - if (*destFlags&NUF_OUTGOING) { - if (dest->validateSSL != source->validateSSL) dest->validateSSL = 2; - if (dest->useProxy != source->useProxy) dest->useProxy = 2; - if (dest->proxyType != source->proxyType) dest->proxyType = 0; - CombineSettingsStrings(&dest->szProxyServer, &source->szProxyServer); - if (dest->wProxyPort != source->wProxyPort) dest->wProxyPort = 0; - if (dest->useProxyAuth != source->useProxyAuth) dest->useProxyAuth = 2; - CombineSettingsStrings(&dest->szProxyAuthUser, &source->szProxyAuthUser); - CombineSettingsStrings(&dest->szProxyAuthPassword, &source->szProxyAuthPassword); - if (dest->dnsThroughProxy != source->dnsThroughProxy) dest->dnsThroughProxy = 2; - if (dest->specifyOutgoingPorts != source->specifyOutgoingPorts) dest->specifyOutgoingPorts = 2; - CombineSettingsStrings(&dest->szOutgoingPorts, &source->szOutgoingPorts); - } - else { - dest->validateSSL = source->validateSSL; - dest->useProxy = source->useProxy; - dest->proxyType = source->proxyType; - dest->szProxyServer = source->szProxyServer; - if (dest->szProxyServer) dest->szProxyServer = mir_strdup(dest->szProxyServer); - dest->wProxyPort = source->wProxyPort; - dest->useProxyAuth = source->useProxyAuth; - dest->szProxyAuthUser = source->szProxyAuthUser; - if (dest->szProxyAuthUser) dest->szProxyAuthUser = mir_strdup(dest->szProxyAuthUser); - dest->szProxyAuthPassword = source->szProxyAuthPassword; - if (dest->szProxyAuthPassword) dest->szProxyAuthPassword = mir_strdup(dest->szProxyAuthPassword); - dest->dnsThroughProxy = source->dnsThroughProxy; - dest->specifyOutgoingPorts = source->specifyOutgoingPorts; - dest->szOutgoingPorts = source->szOutgoingPorts; - if (dest->szOutgoingPorts) dest->szOutgoingPorts = mir_strdup(dest->szOutgoingPorts); - } - } - if (sourceFlags&NUF_INCOMING) { - if (*destFlags&NUF_INCOMING) { - if (dest->enableUPnP != source->enableUPnP) dest->enableUPnP = 2; - if (dest->specifyIncomingPorts != source->specifyIncomingPorts) dest->specifyIncomingPorts = 2; - CombineSettingsStrings(&dest->szIncomingPorts, &source->szIncomingPorts); - } - else { - dest->enableUPnP = source->enableUPnP; - dest->specifyIncomingPorts = source->specifyIncomingPorts; - dest->szIncomingPorts = source->szIncomingPorts; - if (dest->szIncomingPorts) dest->szIncomingPorts = mir_strdup(dest->szIncomingPorts); - } - } - if ((*destFlags&NUF_NOHTTPSOPTION) != (sourceFlags&NUF_NOHTTPSOPTION)) - *destFlags = (*destFlags | sourceFlags)&~NUF_NOHTTPSOPTION; - else *destFlags |= sourceFlags; -} - -static void ChangeSettingIntByCheckbox(HWND hwndDlg, UINT ctrlId, int iUser, int memberOffset) -{ - int newValue = IsDlgButtonChecked(hwndDlg, ctrlId) != BST_CHECKED; - CheckDlgButton(hwndDlg, ctrlId, newValue ? BST_CHECKED : BST_UNCHECKED); - if (iUser == -1) { - for (int i = 0; i < tempSettings.getCount(); i++) { - NetlibTempSettings *p = tempSettings[i]; - if (!(p->flags & NUF_NOOPTIONS)) - *(int*)(((PBYTE)&p->settings) + memberOffset) = newValue; - } - } - else *(int*)(((PBYTE)&tempSettings[iUser]->settings) + memberOffset) = newValue; - SendMessage(hwndDlg, M_REFRESHENABLING, 0, 0); -} - -static void ChangeSettingStringByEdit(HWND hwndDlg, UINT ctrlId, int iUser, int memberOffset) -{ - int newValueLen = GetWindowTextLength(GetDlgItem(hwndDlg, ctrlId)); - char *szNewValue = (char*)mir_alloc(newValueLen+1); - GetDlgItemTextA(hwndDlg, ctrlId, szNewValue, newValueLen+1); - if (iUser == -1) { - for (int i = 0; i < tempSettings.getCount(); i++) { - NetlibTempSettings *p = tempSettings[i]; - if (!(p->flags & NUF_NOOPTIONS)) { - char **ppszNew = (char**)(((PBYTE)&p->settings) + memberOffset); - mir_free(*ppszNew); - *ppszNew = mir_strdup(szNewValue); - } - } - mir_free(szNewValue); - } - else { - char **ppszNew = (char**)(((PBYTE)&tempSettings[iUser]->settings) + memberOffset); - mir_free(*ppszNew); - *ppszNew = szNewValue; - } -} - -static void WriteSettingsStructToDb(const char *szSettingsModule, NETLIBUSERSETTINGS *settings, DWORD flags) -{ - if (flags & NUF_OUTGOING) { - db_set_b(NULL, szSettingsModule, "NLValidateSSL", (BYTE)settings->validateSSL); - db_set_b(NULL, szSettingsModule, "NLUseProxy", (BYTE)settings->useProxy); - db_set_b(NULL, szSettingsModule, "NLProxyType", (BYTE)settings->proxyType); - db_set_s(NULL, szSettingsModule, "NLProxyServer", settings->szProxyServer ? settings->szProxyServer : ""); - db_set_w(NULL, szSettingsModule, "NLProxyPort", (WORD)settings->wProxyPort); - db_set_b(NULL, szSettingsModule, "NLUseProxyAuth", (BYTE)settings->useProxyAuth); - db_set_s(NULL, szSettingsModule, "NLProxyAuthUser", settings->szProxyAuthUser ? settings->szProxyAuthUser : ""); - db_set_s(NULL, szSettingsModule, "NLProxyAuthPassword", settings->szProxyAuthPassword ? settings->szProxyAuthPassword : ""); - db_set_b(NULL, szSettingsModule, "NLDnsThroughProxy", (BYTE)settings->dnsThroughProxy); - db_set_b(NULL, szSettingsModule, "NLSpecifyOutgoingPorts", (BYTE)settings->specifyOutgoingPorts); - db_set_s(NULL, szSettingsModule, "NLOutgoingPorts", settings->szOutgoingPorts ? settings->szOutgoingPorts : ""); - } - if (flags & NUF_INCOMING) { - db_set_b(NULL, szSettingsModule, "NLEnableUPnP", (BYTE)settings->enableUPnP); - db_set_b(NULL, szSettingsModule, "NLSpecifyIncomingPorts", (BYTE)settings->specifyIncomingPorts); - db_set_s(NULL, szSettingsModule, "NLIncomingPorts", settings->szIncomingPorts ? settings->szIncomingPorts : ""); - } -} - -void NetlibSaveUserSettingsStruct(const char *szSettingsModule, NETLIBUSERSETTINGS *settings) -{ - mir_cslock lck(csNetlibUser); - - NetlibUser tUser; - tUser.user.szSettingsModule = (char*)szSettingsModule; - NetlibUser *thisUser = netlibUser.find(&tUser); - if (thisUser == NULL) - return; - - NetlibFreeUserSettingsStruct(&thisUser->settings); - CopySettingsStruct(&thisUser->settings, settings); - WriteSettingsStructToDb(thisUser->user.szSettingsModule, &thisUser->settings, thisUser->user.flags); - - NETLIBUSERSETTINGS combinedSettings = { 0 }; - combinedSettings.cbSize = sizeof(combinedSettings); - - DWORD flags = 0; - for (int i = 0; i < netlibUser.getCount(); i++) { - if (thisUser->user.flags & NUF_NOOPTIONS) - continue; - CombineSettingsStructs(&combinedSettings, &flags, &thisUser->settings, thisUser->user.flags); - } - if (combinedSettings.validateSSL == 2) combinedSettings.validateSSL = 0; - if (combinedSettings.useProxy == 2) combinedSettings.useProxy = 0; - if (combinedSettings.proxyType == 0) combinedSettings.proxyType = PROXYTYPE_SOCKS5; - if (combinedSettings.useProxyAuth == 2) combinedSettings.useProxyAuth = 0; - if (combinedSettings.dnsThroughProxy == 2) combinedSettings.dnsThroughProxy = 1; - if (combinedSettings.enableUPnP == 2) combinedSettings.enableUPnP = 1; - if (combinedSettings.specifyIncomingPorts == 2) combinedSettings.specifyIncomingPorts = 0; - WriteSettingsStructToDb("Netlib", &combinedSettings, flags); - NetlibFreeUserSettingsStruct(&combinedSettings); -} - -static INT_PTR CALLBACK DlgProcNetlibOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - int iUser; - - switch (msg) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - { - int iItem = SendDlgItemMessage(hwndDlg, IDC_NETLIBUSERS, CB_ADDSTRING, 0, (LPARAM)TranslateT("")); - SendDlgItemMessage(hwndDlg, IDC_NETLIBUSERS, CB_SETITEMDATA, iItem, (LPARAM)-1); - SendDlgItemMessage(hwndDlg, IDC_NETLIBUSERS, CB_SETCURSEL, iItem, 0); - { - mir_cslock lck(csNetlibUser); - for (int i = 0; i < netlibUser.getCount(); ++i) { - NetlibTempSettings *thisSettings = (NetlibTempSettings*)mir_calloc(sizeof(NetlibTempSettings)); - thisSettings->flags = netlibUser[i]->user.flags; - thisSettings->szSettingsModule = mir_strdup(netlibUser[i]->user.szSettingsModule); - CopySettingsStruct(&thisSettings->settings, &netlibUser[i]->settings); - tempSettings.insert(thisSettings); - - if (netlibUser[i]->user.flags & NUF_NOOPTIONS) - continue; - iItem = SendDlgItemMessage(hwndDlg, IDC_NETLIBUSERS, CB_ADDSTRING, 0, (LPARAM)netlibUser[i]->user.ptszDescriptiveName); - SendDlgItemMessage(hwndDlg, IDC_NETLIBUSERS, CB_SETITEMDATA, iItem, i); - } - } - } - - SendMessage(hwndDlg, M_REFRESHALL, 0, 0); - return TRUE; - - case M_REFRESHALL: - iUser = SendDlgItemMessage(hwndDlg, IDC_NETLIBUSERS, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_NETLIBUSERS, CB_GETCURSEL, 0, 0), 0); - { - NETLIBUSERSETTINGS settings = { 0 }; - DWORD flags = 0; - - if (iUser == -1) { - settings.cbSize = sizeof(settings); - for (int i = 0; i < tempSettings.getCount(); i++) { - NetlibTempSettings *p = tempSettings[i]; - if (!(p->flags & NUF_NOOPTIONS)) - CombineSettingsStructs(&settings, &flags, &p->settings, p->flags); - } - } - else { - NetlibFreeUserSettingsStruct(&settings); - CopySettingsStruct(&settings, &tempSettings[iUser]->settings); - flags = tempSettings[iUser]->flags; - } - ShowMultipleControls(hwndDlg, outgoingConnectionsControls, SIZEOF(outgoingConnectionsControls), flags&NUF_OUTGOING ? SW_SHOW : SW_HIDE); - CheckDlgButton(hwndDlg, IDC_USEPROXY, settings.useProxy ? BST_CHECKED : BST_UNCHECKED); - SendDlgItemMessage(hwndDlg, IDC_PROXYTYPE, CB_RESETCONTENT, 0, 0); - if (settings.proxyType == 0) AddProxyTypeItem(hwndDlg, 0, settings.proxyType); - AddProxyTypeItem(hwndDlg, PROXYTYPE_SOCKS4, settings.proxyType); - AddProxyTypeItem(hwndDlg, PROXYTYPE_SOCKS5, settings.proxyType); - if (flags & (NUF_HTTPCONNS | NUF_HTTPGATEWAY)) AddProxyTypeItem(hwndDlg, PROXYTYPE_HTTP, settings.proxyType); - if (!(flags & NUF_NOHTTPSOPTION)) AddProxyTypeItem(hwndDlg, PROXYTYPE_HTTPS, settings.proxyType); - if (flags & (NUF_HTTPCONNS | NUF_HTTPGATEWAY) || !(flags & NUF_NOHTTPSOPTION)) - AddProxyTypeItem(hwndDlg, PROXYTYPE_IE, settings.proxyType); - SetDlgItemTextA(hwndDlg, IDC_PROXYHOST, settings.szProxyServer ? settings.szProxyServer : ""); - if (settings.wProxyPort) SetDlgItemInt(hwndDlg, IDC_PROXYPORT, settings.wProxyPort, FALSE); - else SetDlgItemTextA(hwndDlg, IDC_PROXYPORT, ""); - CheckDlgButton(hwndDlg, IDC_PROXYAUTH, settings.useProxyAuth ? BST_CHECKED : BST_UNCHECKED); - SetDlgItemTextA(hwndDlg, IDC_PROXYUSER, settings.szProxyAuthUser ? settings.szProxyAuthUser : ""); - SetDlgItemTextA(hwndDlg, IDC_PROXYPASS, settings.szProxyAuthPassword ? settings.szProxyAuthPassword : ""); - CheckDlgButton(hwndDlg, IDC_PROXYDNS, settings.dnsThroughProxy ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_VALIDATESSL, settings.validateSSL ? BST_CHECKED : BST_UNCHECKED); - - ShowMultipleControls(hwndDlg, incomingConnectionsControls, SIZEOF(incomingConnectionsControls), flags&NUF_INCOMING ? SW_SHOW : SW_HIDE); - CheckDlgButton(hwndDlg, IDC_SPECIFYPORTS, settings.specifyIncomingPorts ? BST_CHECKED : BST_UNCHECKED); - SetDlgItemTextA(hwndDlg, IDC_PORTSRANGE, settings.szIncomingPorts ? settings.szIncomingPorts : ""); - - CheckDlgButton(hwndDlg, IDC_SPECIFYPORTSO, settings.specifyOutgoingPorts ? BST_CHECKED : BST_UNCHECKED); - SetDlgItemTextA(hwndDlg, IDC_PORTSRANGEO, settings.szOutgoingPorts ? settings.szOutgoingPorts : ""); - - CheckDlgButton(hwndDlg, IDC_ENABLEUPNP, settings.enableUPnP ? BST_CHECKED : BST_UNCHECKED); - - NetlibFreeUserSettingsStruct(&settings); - SendMessage(hwndDlg, M_REFRESHENABLING, 0, 0); - } - break; - - case M_REFRESHENABLING: - TCHAR str[80]; - { - int selectedProxyType = SendDlgItemMessage(hwndDlg, IDC_PROXYTYPE, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROXYTYPE, CB_GETCURSEL, 0, 0), 0); - mir_sntprintf(str, SIZEOF(str), TranslateT("(often %d)"), oftenProxyPorts[selectedProxyType]); - SetDlgItemText(hwndDlg, IDC_STOFTENPORT, str); - if (IsDlgButtonChecked(hwndDlg, IDC_USEPROXY) != BST_UNCHECKED) { - int enableAuth = 0, enableUser = 0, enablePass = 0, enableServer = 1; - EnableMultipleControls(hwndDlg, useProxyControls, SIZEOF(useProxyControls), TRUE); - if (selectedProxyType == 0) { - for (int i = 0; i < tempSettings.getCount(); i++) { - NetlibTempSettings *p = tempSettings[i]; - if (!p->settings.useProxy || - p->flags & NUF_NOOPTIONS || !(p->flags & NUF_OUTGOING)) - continue; - - if (p->settings.proxyType == PROXYTYPE_SOCKS4) enableUser = 1; - else { - enableAuth = 1; - if (p->settings.useProxyAuth) - enableUser = enablePass = 1; - } - } - } - else { - if (selectedProxyType == PROXYTYPE_SOCKS4) enableUser = 1; - else { - if (selectedProxyType == PROXYTYPE_IE) enableServer = 0; - enableAuth = 1; - if (IsDlgButtonChecked(hwndDlg, IDC_PROXYAUTH) != BST_UNCHECKED) - enableUser = enablePass = 1; - } - } - EnableWindow(GetDlgItem(hwndDlg, IDC_PROXYAUTH), enableAuth); - EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC31), enableUser); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROXYUSER), enableUser); - EnableWindow(GetDlgItem(hwndDlg, IDC_STATIC32), enablePass); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROXYPASS), enablePass); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROXYHOST), enableServer); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROXYPORT), enableServer); - } - else EnableMultipleControls(hwndDlg, useProxyControls, SIZEOF(useProxyControls), FALSE); - EnableMultipleControls(hwndDlg, specifyPortsControls, SIZEOF(specifyPortsControls), IsDlgButtonChecked(hwndDlg, IDC_SPECIFYPORTS) != BST_UNCHECKED); - EnableMultipleControls(hwndDlg, specifyOPortsControls, SIZEOF(specifyOPortsControls), IsDlgButtonChecked(hwndDlg, IDC_SPECIFYPORTSO) != BST_UNCHECKED); - } - break; - - case WM_COMMAND: - iUser = SendDlgItemMessage(hwndDlg, IDC_NETLIBUSERS, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_NETLIBUSERS, CB_GETCURSEL, 0, 0), 0); - switch (LOWORD(wParam)) { - case IDC_NETLIBUSERS: - if (HIWORD(wParam) == CBN_SELCHANGE) SendMessage(hwndDlg, M_REFRESHALL, 0, 0); - return 0; - - case IDC_LOGOPTIONS: - NetlibLogShowOptions(); - return 0; - - case IDC_PROXYTYPE: - if (HIWORD(wParam) != CBN_SELCHANGE) return 0; - { - int newValue = SendDlgItemMessage(hwndDlg, IDC_PROXYTYPE, CB_GETITEMDATA, SendDlgItemMessage(hwndDlg, IDC_PROXYTYPE, CB_GETCURSEL, 0, 0), 0); - if (iUser == -1) { - if (newValue == 0) return 0; - for (int i=0; i < tempSettings.getCount(); i++) { - NetlibTempSettings *p = tempSettings[i]; - if (p->flags & NUF_NOOPTIONS) continue; - if (newValue == PROXYTYPE_HTTP && !(p->flags & (NUF_HTTPCONNS | NUF_HTTPGATEWAY))) - p->settings.proxyType = PROXYTYPE_HTTPS; - else if (newValue == PROXYTYPE_HTTPS && p->flags & NUF_NOHTTPSOPTION) - p->settings.proxyType = PROXYTYPE_HTTP; - else p->settings.proxyType = newValue; - } - SendMessage(hwndDlg, M_REFRESHALL, 0, 0); - } - else { - tempSettings[iUser]->settings.proxyType = newValue; - SendMessage(hwndDlg, M_REFRESHENABLING, 0, 0); - } - } - break; - case IDC_USEPROXY: - ChangeSettingIntByCheckbox(hwndDlg, LOWORD(wParam), iUser, offsetof(NETLIBUSERSETTINGS, useProxy)); - break; - case IDC_PROXYAUTH: - ChangeSettingIntByCheckbox(hwndDlg, LOWORD(wParam), iUser, offsetof(NETLIBUSERSETTINGS, useProxyAuth)); - break; - case IDC_PROXYDNS: - ChangeSettingIntByCheckbox(hwndDlg, LOWORD(wParam), iUser, offsetof(NETLIBUSERSETTINGS, dnsThroughProxy)); - break; - case IDC_SPECIFYPORTS: - ChangeSettingIntByCheckbox(hwndDlg, LOWORD(wParam), iUser, offsetof(NETLIBUSERSETTINGS, specifyIncomingPorts)); - break; - case IDC_SPECIFYPORTSO: - ChangeSettingIntByCheckbox(hwndDlg, LOWORD(wParam), iUser, offsetof(NETLIBUSERSETTINGS, specifyOutgoingPorts)); - break; - case IDC_ENABLEUPNP: - ChangeSettingIntByCheckbox(hwndDlg, LOWORD(wParam), iUser, offsetof(NETLIBUSERSETTINGS, enableUPnP)); - break; - case IDC_VALIDATESSL: - ChangeSettingIntByCheckbox(hwndDlg, LOWORD(wParam), iUser, offsetof(NETLIBUSERSETTINGS, validateSSL)); - break; - case IDC_PROXYHOST: - if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()) return 0; - ChangeSettingStringByEdit(hwndDlg, LOWORD(wParam), iUser, offsetof(NETLIBUSERSETTINGS, szProxyServer)); - break; - case IDC_PROXYPORT: - if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()) return 0; - { - int newValue = GetDlgItemInt(hwndDlg, LOWORD(wParam), NULL, FALSE); - if (iUser == -1) { - for (int i = 0; i < tempSettings.getCount(); i++) { - NetlibTempSettings *p = tempSettings[i]; - if (!(p->flags & NUF_NOOPTIONS)) - p->settings.wProxyPort = newValue; - } - } - else tempSettings[iUser]->settings.wProxyPort = newValue; - } - break; - case IDC_PROXYUSER: - if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()) return 0; - ChangeSettingStringByEdit(hwndDlg, LOWORD(wParam), iUser, offsetof(NETLIBUSERSETTINGS, szProxyAuthUser)); - break; - case IDC_PROXYPASS: - if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()) return 0; - ChangeSettingStringByEdit(hwndDlg, LOWORD(wParam), iUser, offsetof(NETLIBUSERSETTINGS, szProxyAuthPassword)); - break; - case IDC_PORTSRANGE: - if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()) return 0; - ChangeSettingStringByEdit(hwndDlg, LOWORD(wParam), iUser, offsetof(NETLIBUSERSETTINGS, szIncomingPorts)); - break; - case IDC_PORTSRANGEO: - if (HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus()) return 0; - ChangeSettingStringByEdit(hwndDlg, LOWORD(wParam), iUser, offsetof(NETLIBUSERSETTINGS, szOutgoingPorts)); - break; - } - ShowWindow(GetDlgItem(hwndDlg, IDC_RECONNECTREQD), SW_SHOW); - SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - break; - - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->idFrom) { - case 0: - switch (((LPNMHDR)lParam)->code) { - case PSN_APPLY: - for (iUser = 0; iUser < tempSettings.getCount(); iUser++) - NetlibSaveUserSettingsStruct(tempSettings[iUser]->szSettingsModule, - &tempSettings[iUser]->settings); - return TRUE; - } - break; - } - break; - - case WM_DESTROY: - for (int i = 0; i < tempSettings.getCount(); ++i) { - NetlibTempSettings *p = tempSettings[i]; - mir_free(p->szSettingsModule); - NetlibFreeUserSettingsStruct(&p->settings); - mir_free(tempSettings[i]); - } - tempSettings.destroy(); - break; - } - return FALSE; -} - -int NetlibOptInitialise(WPARAM wParam, LPARAM) -{ - int optionsCount = 0; - { - mir_cslock lck(csNetlibUser); - for (int i=0; i < netlibUser.getCount(); i++) - if (!(netlibUser[i]->user.flags & NUF_NOOPTIONS)) - ++optionsCount; - } - - if (optionsCount == 0) - return 0; - - OPTIONSDIALOGPAGE odp = { 0 }; - odp.position = 900000000; - odp.hInstance = hInst; - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_NETLIB); - odp.pszTitle = LPGEN("Network"); - odp.pfnDlgProc = DlgProcNetlibOpts; - odp.flags = ODPF_BOLDGROUPS; - Options_AddPage(wParam, &odp); - return 0; -} diff --git a/src/modules/netlib/netlibpktrecver.cpp b/src/modules/netlib/netlibpktrecver.cpp deleted file mode 100644 index 5783cda6b3..0000000000 --- a/src/modules/netlib/netlibpktrecver.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "..\..\core\commonheaders.h" -#include "netlib.h" - -INT_PTR NetlibPacketRecverCreate(WPARAM wParam, LPARAM lParam) -{ - NetlibConnection *nlc = (struct NetlibConnection*)wParam; - struct NetlibPacketRecver *nlpr; - - if (GetNetlibHandleType(nlc) != NLH_CONNECTION || lParam == 0) { - SetLastError(ERROR_INVALID_PARAMETER); - return (INT_PTR)(struct NetlibPacketRecver*)NULL; - } - nlpr = (struct NetlibPacketRecver*)mir_calloc(sizeof(struct NetlibPacketRecver)); - if (nlpr == NULL) { - SetLastError(ERROR_OUTOFMEMORY); - return (INT_PTR)(struct NetlibPacketRecver*)NULL; - } - nlpr->handleType = NLH_PACKETRECVER; - nlpr->nlc = nlc; - nlpr->packetRecver.cbSize = sizeof(nlpr->packetRecver); - nlpr->packetRecver.bufferSize = lParam; - nlpr->packetRecver.buffer = (PBYTE)mir_alloc(nlpr->packetRecver.bufferSize); - nlpr->packetRecver.bytesUsed = 0; - nlpr->packetRecver.bytesAvailable = 0; - return (INT_PTR)nlpr; -} - -INT_PTR NetlibPacketRecverGetMore(WPARAM wParam, LPARAM lParam) -{ - struct NetlibPacketRecver *nlpr = (struct NetlibPacketRecver*)wParam; - NETLIBPACKETRECVER *nlprParam = (NETLIBPACKETRECVER*)lParam; - - if (GetNetlibHandleType(nlpr) != NLH_PACKETRECVER || nlprParam == NULL || nlprParam->cbSize != sizeof(NETLIBPACKETRECVER) || nlprParam->bytesUsed > nlpr->packetRecver.bytesAvailable) { - SetLastError(ERROR_INVALID_PARAMETER); - return SOCKET_ERROR; - } - if (Miranda_Terminated()) { /* HACK: Lame, break while loops of protocols that can't kill their while loops, (cough, ICQ, cough) */ - SetLastError(ERROR_TIMEOUT); - return SOCKET_ERROR; - } - nlpr->packetRecver.dwTimeout = nlprParam->dwTimeout; - if (nlprParam->bytesUsed == 0) { - if (nlpr->packetRecver.bytesAvailable == nlpr->packetRecver.bufferSize) { - nlpr->packetRecver.bytesAvailable = 0; - NetlibLogf(nlpr->nlc->nlu, "Packet recver: packet overflowed buffer, ditching"); - } - } - else { - memmove(nlpr->packetRecver.buffer, nlpr->packetRecver.buffer + nlprParam->bytesUsed, nlpr->packetRecver.bytesAvailable - nlprParam->bytesUsed); - nlpr->packetRecver.bytesAvailable -= nlprParam->bytesUsed; - } - - if (nlprParam->dwTimeout != INFINITE) { - if (!si.pending(nlpr->nlc->hSsl) && WaitUntilReadable(nlpr->nlc->s, nlprParam->dwTimeout) <= 0) { - *nlprParam = nlpr->packetRecver; - return SOCKET_ERROR; - } - } - - INT_PTR recvResult = NLRecv(nlpr->nlc, (char*)nlpr->packetRecver.buffer + nlpr->packetRecver.bytesAvailable, nlpr->packetRecver.bufferSize - nlpr->packetRecver.bytesAvailable, 0); - if (recvResult > 0) - nlpr->packetRecver.bytesAvailable += recvResult; - *nlprParam = nlpr->packetRecver; - return recvResult; -} diff --git a/src/modules/netlib/netlibsecurity.cpp b/src/modules/netlib/netlibsecurity.cpp deleted file mode 100644 index 4c3cb4301c..0000000000 --- a/src/modules/netlib/netlibsecurity.cpp +++ /dev/null @@ -1,427 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "..\..\core\commonheaders.h" -#include "netlib.h" - -#define SECURITY_WIN32 -#include -#include - -#pragma comment(lib, "secur32.lib") - -struct NtlmHandleType -{ - CtxtHandle hClientContext; - CredHandle hClientCredential; - TCHAR* szProvider; - TCHAR* szPrincipal; - unsigned cbMaxToken; - bool hasDomain; -}; - -struct NTLM_String -{ - WORD len; - WORD allocedSpace; - DWORD offset; -}; - -struct NtlmType2packet -{ - char sign[8]; - DWORD type; // == 2 - NTLM_String targetName; - DWORD flags; - BYTE challenge[8]; - BYTE context[8]; - NTLM_String targetInfo; -}; - -static unsigned ntlmCnt = 0; -static mir_cs csSec; - -static void ReportSecError(SECURITY_STATUS scRet, int line) -{ - char szMsgBuf[256]; - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, scRet, LANG_USER_DEFAULT, szMsgBuf, SIZEOF(szMsgBuf), NULL); - - char *p = strchr(szMsgBuf, 13); if (p) *p = 0; - - NetlibLogf(NULL, "Security error 0x%x on line %u (%s)", scRet, line, szMsgBuf); -} - -HANDLE NetlibInitSecurityProvider(const TCHAR* szProvider, const TCHAR* szPrincipal) -{ - HANDLE hSecurity = NULL; - - if (mir_tstrcmpi(szProvider, _T("Basic")) == 0) { - NtlmHandleType* hNtlm = (NtlmHandleType*)mir_calloc(sizeof(NtlmHandleType)); - hNtlm->szProvider = mir_tstrdup(szProvider); - SecInvalidateHandle(&hNtlm->hClientContext); - SecInvalidateHandle(&hNtlm->hClientCredential); - ntlmCnt++; - - return hNtlm; - } - - mir_cslock lck(csSec); - - PSecPkgInfo ntlmSecurityPackageInfo; - bool isGSSAPI = mir_tstrcmpi(szProvider, _T("GSSAPI")) == 0; - const TCHAR *szProviderC = isGSSAPI ? _T("Kerberos") : szProvider; - SECURITY_STATUS sc = QuerySecurityPackageInfo((LPTSTR)szProviderC, &ntlmSecurityPackageInfo); - if (sc == SEC_E_OK) { - NtlmHandleType* hNtlm; - - hSecurity = hNtlm = (NtlmHandleType*)mir_calloc(sizeof(NtlmHandleType)); - hNtlm->cbMaxToken = ntlmSecurityPackageInfo->cbMaxToken; - FreeContextBuffer(ntlmSecurityPackageInfo); - - hNtlm->szProvider = mir_tstrdup(szProvider); - hNtlm->szPrincipal = mir_tstrdup(szPrincipal ? szPrincipal : _T("")); - SecInvalidateHandle(&hNtlm->hClientContext); - SecInvalidateHandle(&hNtlm->hClientCredential); - ntlmCnt++; - } - return hSecurity; -} - -HANDLE NetlibInitSecurityProvider(const char* szProvider, const char* szPrincipal) -{ - return NetlibInitSecurityProvider(_A2T(szProvider), _A2T(szPrincipal)); -} - -void NetlibDestroySecurityProvider(HANDLE hSecurity) -{ - if (hSecurity == NULL) - return; - - mir_cslock lck(csSec); - - if (ntlmCnt != 0) { - NtlmHandleType* hNtlm = (NtlmHandleType*)hSecurity; - if (hNtlm != NULL) { - if (SecIsValidHandle(&hNtlm->hClientContext)) - DeleteSecurityContext(&hNtlm->hClientContext); - if (SecIsValidHandle(&hNtlm->hClientCredential)) - FreeCredentialsHandle(&hNtlm->hClientCredential); - mir_free(hNtlm->szProvider); - mir_free(hNtlm->szPrincipal); - mir_free(hNtlm); - } - - --ntlmCnt; - } -} - -char* CompleteGssapi(HANDLE hSecurity, unsigned char *szChallenge, unsigned chlsz) -{ - if (!szChallenge || !szChallenge[0]) return NULL; - - NtlmHandleType* hNtlm = (NtlmHandleType*)hSecurity; - unsigned char inDataBuffer[1024]; - - SecBuffer inBuffers[2] = - { - { sizeof(inDataBuffer), SECBUFFER_DATA, inDataBuffer }, - { chlsz, SECBUFFER_STREAM, szChallenge } - }; - - SecBufferDesc inBuffersDesc = { SECBUFFER_VERSION, 2, inBuffers }; - - unsigned long qop = 0; - SECURITY_STATUS sc = DecryptMessage(&hNtlm->hClientContext, &inBuffersDesc, 0, &qop); - if (sc != SEC_E_OK) { - ReportSecError(sc, __LINE__); - return NULL; - } - - unsigned char LayerMask = inDataBuffer[0]; - unsigned int MaxMessageSize = htonl(*(unsigned*)&inDataBuffer[1]); - - SecPkgContext_Sizes sizes; - sc = QueryContextAttributes(&hNtlm->hClientContext, SECPKG_ATTR_SIZES, &sizes); - if (sc != SEC_E_OK) { - ReportSecError(sc, __LINE__); - return NULL; - } - - unsigned char *tokenBuffer = (unsigned char*)alloca(sizes.cbSecurityTrailer); - unsigned char *paddingBuffer = (unsigned char*)alloca(sizes.cbBlockSize); - - unsigned char outDataBuffer[4] = { 1, 0, 16, 0 }; - - SecBuffer outBuffers[3] = - { - { sizes.cbSecurityTrailer, SECBUFFER_TOKEN, tokenBuffer }, - { sizeof(outDataBuffer), SECBUFFER_DATA, outDataBuffer }, - { sizes.cbBlockSize, SECBUFFER_PADDING, paddingBuffer } - }; - SecBufferDesc outBuffersDesc = { SECBUFFER_VERSION, 3, outBuffers }; - - sc = EncryptMessage(&hNtlm->hClientContext, SECQOP_WRAP_NO_ENCRYPT, &outBuffersDesc, 0); - if (sc != SEC_E_OK) { - ReportSecError(sc, __LINE__); - return NULL; - } - - unsigned i, ressz = 0; - for (i = 0; i < outBuffersDesc.cBuffers; i++) - ressz += outBuffersDesc.pBuffers[i].cbBuffer; - - unsigned char *response = (unsigned char*)alloca(ressz), *p = response; - for (i = 0; i < outBuffersDesc.cBuffers; i++) { - memcpy(p, outBuffersDesc.pBuffers[i].pvBuffer, outBuffersDesc.pBuffers[i].cbBuffer); - p += outBuffersDesc.pBuffers[i].cbBuffer; - } - - return mir_base64_encode(response, ressz); -} - -char* NtlmCreateResponseFromChallenge(HANDLE hSecurity, const char *szChallenge, const TCHAR* login, const TCHAR* psw, bool http, unsigned& complete) -{ - if (hSecurity == NULL || ntlmCnt == 0) - return NULL; - - SecBufferDesc outputBufferDescriptor, inputBufferDescriptor; - SecBuffer outputSecurityToken, inputSecurityToken; - TimeStamp tokenExpiration; - ULONG contextAttributes; - char *szOutputToken; - - NtlmHandleType* hNtlm = (NtlmHandleType*)hSecurity; - if (mir_tstrcmpi(hNtlm->szProvider, _T("Basic"))) { - bool isGSSAPI = mir_tstrcmpi(hNtlm->szProvider, _T("GSSAPI")) == 0; - TCHAR *szProvider = isGSSAPI ? _T("Kerberos") : hNtlm->szProvider; - bool hasChallenge = szChallenge != NULL && szChallenge[0] != '\0'; - if (hasChallenge) { - unsigned tokenLen; - BYTE *token = (BYTE*)mir_base64_decode(szChallenge, &tokenLen); - if (token == NULL) - return NULL; - - if (isGSSAPI && complete) - return CompleteGssapi(hSecurity, token, tokenLen); - - inputBufferDescriptor.cBuffers = 1; - inputBufferDescriptor.pBuffers = &inputSecurityToken; - inputBufferDescriptor.ulVersion = SECBUFFER_VERSION; - inputSecurityToken.BufferType = SECBUFFER_TOKEN; - inputSecurityToken.cbBuffer = tokenLen; - inputSecurityToken.pvBuffer = token; - - // try to decode the domain name from the NTLM challenge - if (login != NULL && login[0] != '\0' && !hNtlm->hasDomain) { - NtlmType2packet* pkt = (NtlmType2packet*)token; - if (!strncmp(pkt->sign, "NTLMSSP", 8) && pkt->type == 2) { - - wchar_t* domainName = (wchar_t*)&token[pkt->targetName.offset]; - int domainLen = pkt->targetName.len; - - // Negotiate ANSI? if yes, convert the ANSI name to unicode - if ((pkt->flags & 1) == 0) { - int bufsz = MultiByteToWideChar(CP_ACP, 0, (char*)domainName, domainLen, NULL, 0); - wchar_t* buf = (wchar_t*)alloca(bufsz * sizeof(wchar_t)); - domainLen = MultiByteToWideChar(CP_ACP, 0, (char*)domainName, domainLen, buf, bufsz) - 1; - domainName = buf; - } - else domainLen /= sizeof(wchar_t); - - if (domainLen) { - size_t newLoginLen = mir_tstrlen(login) + domainLen + 1; - TCHAR *newLogin = (TCHAR*)alloca(newLoginLen * sizeof(TCHAR)); - - _tcsncpy(newLogin, domainName, domainLen); - newLogin[domainLen] = '\\'; - mir_tstrcpy(newLogin + domainLen + 1, login); - - char* szChl = NtlmCreateResponseFromChallenge(hSecurity, NULL, newLogin, psw, http, complete); - mir_free(szChl); - } - } - } - } - else { - if (SecIsValidHandle(&hNtlm->hClientContext)) - DeleteSecurityContext(&hNtlm->hClientContext); - if (SecIsValidHandle(&hNtlm->hClientCredential)) - FreeCredentialsHandle(&hNtlm->hClientCredential); - - SEC_WINNT_AUTH_IDENTITY auth; - - if (login != NULL && login[0] != '\0') { - memset(&auth, 0, sizeof(auth)); - - NetlibLogf(NULL, "Security login requested, user: %S pssw: %s", login, psw ? "(exist)" : "(no psw)"); - - const TCHAR* loginName = login; - const TCHAR* domainName = _tcschr(login, '\\'); - size_t domainLen = 0; - size_t loginLen = mir_tstrlen(loginName); - if (domainName != NULL) { - loginName = domainName + 1; - loginLen = mir_tstrlen(loginName); - domainLen = domainName - login; - domainName = login; - } - else if ((domainName = _tcschr(login, '@')) != NULL) { - loginName = login; - loginLen = domainName - login; - domainLen = mir_tstrlen(++domainName); - } - - auth.User = (PWORD)loginName; - auth.UserLength = (ULONG)loginLen; - auth.Password = (PWORD)psw; - auth.PasswordLength = (ULONG)mir_tstrlen(psw); - auth.Domain = (PWORD)domainName; - auth.DomainLength = (ULONG)domainLen; - auth.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - - hNtlm->hasDomain = domainLen != 0; - } - - SECURITY_STATUS sc = AcquireCredentialsHandle(NULL, szProvider, - SECPKG_CRED_OUTBOUND, NULL, hNtlm->hasDomain ? &auth : NULL, NULL, NULL, - &hNtlm->hClientCredential, &tokenExpiration); - if (sc != SEC_E_OK) { - ReportSecError(sc, __LINE__); - return NULL; - } - } - - outputBufferDescriptor.cBuffers = 1; - outputBufferDescriptor.pBuffers = &outputSecurityToken; - outputBufferDescriptor.ulVersion = SECBUFFER_VERSION; - outputSecurityToken.BufferType = SECBUFFER_TOKEN; - outputSecurityToken.cbBuffer = hNtlm->cbMaxToken; - outputSecurityToken.pvBuffer = alloca(outputSecurityToken.cbBuffer); - - SECURITY_STATUS sc = InitializeSecurityContext(&hNtlm->hClientCredential, - hasChallenge ? &hNtlm->hClientContext : NULL, - hNtlm->szPrincipal, isGSSAPI ? ISC_REQ_MUTUAL_AUTH | ISC_REQ_STREAM : 0, 0, SECURITY_NATIVE_DREP, - hasChallenge ? &inputBufferDescriptor : NULL, 0, &hNtlm->hClientContext, - &outputBufferDescriptor, &contextAttributes, &tokenExpiration); - - complete = (sc != SEC_I_COMPLETE_AND_CONTINUE && sc != SEC_I_CONTINUE_NEEDED); - - if (sc == SEC_I_COMPLETE_NEEDED || sc == SEC_I_COMPLETE_AND_CONTINUE) - sc = CompleteAuthToken(&hNtlm->hClientContext, &outputBufferDescriptor); - - if (sc != SEC_E_OK && sc != SEC_I_CONTINUE_NEEDED) { - ReportSecError(sc, __LINE__); - return NULL; - } - - szOutputToken = mir_base64_encode((PBYTE)outputSecurityToken.pvBuffer, outputSecurityToken.cbBuffer); - } - else { - if (!login || !psw) return NULL; - - char *szLogin = mir_t2a(login); - char *szPassw = mir_t2a(psw); - - size_t authLen = mir_strlen(szLogin) + mir_strlen(szPassw) + 5; - char *szAuth = (char*)alloca(authLen); - - int len = mir_snprintf(szAuth, authLen, "%s:%s", szLogin, szPassw); - szOutputToken = mir_base64_encode((BYTE*)szAuth, len); - complete = true; - - mir_free(szPassw); - mir_free(szLogin); - } - - if (szOutputToken == NULL) - return NULL; - - if (!http) - return szOutputToken; - - ptrA szProvider(mir_t2a(hNtlm->szProvider)); - size_t resLen = mir_strlen(szOutputToken) + mir_strlen(szProvider) + 10; - char *result = (char*)mir_alloc(resLen); - mir_snprintf(result, resLen, "%s %s", szProvider, szOutputToken); - mir_free(szOutputToken); - return result; -} - -/////////////////////////////////////////////////////////////////////////////// - -static INT_PTR InitSecurityProviderService(WPARAM, LPARAM lParam) -{ - HANDLE hSecurity = NetlibInitSecurityProvider((char*)lParam, NULL); - return (INT_PTR)hSecurity; -} - -static INT_PTR InitSecurityProviderService2(WPARAM, LPARAM lParam) -{ - NETLIBNTLMINIT2 *req = (NETLIBNTLMINIT2*)lParam; - if (req == NULL || req->cbSize < sizeof(*req)) - return 0; - - if (req->flags & NNR_UNICODE) - return (INT_PTR)NetlibInitSecurityProvider(req->szProviderName, req->szPrincipal); - return (INT_PTR)NetlibInitSecurityProvider((char*)req->szProviderName, (char*)req->szPrincipal); -} - -static INT_PTR DestroySecurityProviderService(WPARAM, LPARAM lParam) -{ - NetlibDestroySecurityProvider((HANDLE)lParam); - return 0; -} - -static INT_PTR NtlmCreateResponseService(WPARAM wParam, LPARAM lParam) -{ - NETLIBNTLMREQUEST *req = (NETLIBNTLMREQUEST*)lParam; - if (req == NULL) - return 0; - - unsigned complete = 0; - char *response = NtlmCreateResponseFromChallenge((HANDLE)wParam, req->szChallenge, _A2T(req->userName), _A2T(req->password), false, complete); - return (INT_PTR)response; -} - -static INT_PTR NtlmCreateResponseService2(WPARAM wParam, LPARAM lParam) -{ - NETLIBNTLMREQUEST2 *req = (NETLIBNTLMREQUEST2*)lParam; - if (req == NULL || req->cbSize < sizeof(*req)) - return 0; - - if (req->flags & NNR_UNICODE) - return (INT_PTR)NtlmCreateResponseFromChallenge((HANDLE)wParam, req->szChallenge, req->szUserName, req->szPassword, false, req->complete); - - return (INT_PTR)NtlmCreateResponseFromChallenge((HANDLE)wParam, req->szChallenge, _A2T((char*)req->szUserName), _A2T((char*)req->szPassword), false, req->complete); -} - -void NetlibSecurityInit(void) -{ - CreateServiceFunction(MS_NETLIB_INITSECURITYPROVIDER, InitSecurityProviderService); - CreateServiceFunction(MS_NETLIB_INITSECURITYPROVIDER2, InitSecurityProviderService2); - CreateServiceFunction(MS_NETLIB_DESTROYSECURITYPROVIDER, DestroySecurityProviderService); - CreateServiceFunction(MS_NETLIB_NTLMCREATERESPONSE, NtlmCreateResponseService); - CreateServiceFunction(MS_NETLIB_NTLMCREATERESPONSE2, NtlmCreateResponseService2); -} diff --git a/src/modules/netlib/netlibsock.cpp b/src/modules/netlib/netlibsock.cpp deleted file mode 100644 index e53e73bd89..0000000000 --- a/src/modules/netlib/netlibsock.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "..\..\core\commonheaders.h" -#include "netlib.h" - -extern HANDLE hConnectionHeaderMutex, hSendEvent, hRecvEvent; - -INT_PTR NetlibSend(WPARAM wParam, LPARAM lParam) -{ - NetlibConnection *nlc = (NetlibConnection*)wParam; - NETLIBBUFFER *nlb = (NETLIBBUFFER*)lParam; - INT_PTR result; - - if (nlb == NULL) { - SetLastError(ERROR_INVALID_PARAMETER); - return SOCKET_ERROR; - } - - if (!NetlibEnterNestedCS(nlc, NLNCS_SEND)) - return SOCKET_ERROR; - - if (nlc->usingHttpGateway && !(nlb->flags & MSG_RAW)) { - if (!(nlb->flags & MSG_NOHTTPGATEWAYWRAP) && nlc->nlu->user.pfnHttpGatewayWrapSend) { - NetlibDumpData(nlc, (PBYTE)nlb->buf, nlb->len, 1, nlb->flags); - result = nlc->nlu->user.pfnHttpGatewayWrapSend((HANDLE)nlc, (PBYTE)nlb->buf, nlb->len, nlb->flags | MSG_NOHTTPGATEWAYWRAP, NetlibSend); - } - else result = NetlibHttpGatewayPost(nlc, nlb->buf, nlb->len, nlb->flags); - } - else { - NetlibDumpData(nlc, (PBYTE)nlb->buf, nlb->len, 1, nlb->flags); - if (nlc->hSsl) - result = si.write(nlc->hSsl, nlb->buf, nlb->len); - else - result = send(nlc->s, nlb->buf, nlb->len, nlb->flags & 0xFFFF); - } - NetlibLeaveNestedCS(&nlc->ncsSend); - - NETLIBNOTIFY nln = { nlb, result }; - NotifyFastHook(hSendEvent, (WPARAM)&nln, (LPARAM)&nlc->nlu->user); - - return result; -} - -INT_PTR NetlibRecv(WPARAM wParam, LPARAM lParam) -{ - NetlibConnection *nlc = (NetlibConnection*)wParam; - NETLIBBUFFER* nlb = (NETLIBBUFFER*)lParam; - int recvResult; - - if (nlb == NULL) { - SetLastError(ERROR_INVALID_PARAMETER); - return SOCKET_ERROR; - } - - if (!NetlibEnterNestedCS(nlc, NLNCS_RECV)) - return SOCKET_ERROR; - - if (nlc->usingHttpGateway && !(nlb->flags & MSG_RAW)) - recvResult = NetlibHttpGatewayRecv(nlc, nlb->buf, nlb->len, nlb->flags); - else { - if (nlc->hSsl) - recvResult = si.read(nlc->hSsl, nlb->buf, nlb->len, (nlb->flags & MSG_PEEK) != 0); - else - recvResult = recv(nlc->s, nlb->buf, nlb->len, nlb->flags & 0xFFFF); - } - NetlibLeaveNestedCS(&nlc->ncsRecv); - if (recvResult <= 0) - return recvResult; - - NetlibDumpData(nlc, (PBYTE)nlb->buf, recvResult, 0, nlb->flags); - - if ((nlb->flags & MSG_PEEK) == 0) { - NETLIBNOTIFY nln = { nlb, recvResult }; - NotifyFastHook(hRecvEvent, (WPARAM)&nln, (LPARAM)&nlc->nlu->user); - } - return recvResult; -} - -static int ConnectionListToSocketList(HANDLE *hConns, fd_set *fd, int& pending) -{ - FD_ZERO(fd); - for (int i = 0; hConns[i] && hConns[i] != INVALID_HANDLE_VALUE && i < FD_SETSIZE; i++) { - NetlibConnection *nlcCheck = (NetlibConnection*)hConns[i]; - if (nlcCheck->handleType != NLH_CONNECTION && nlcCheck->handleType != NLH_BOUNDPORT) { - SetLastError(ERROR_INVALID_DATA); - return 0; - } - FD_SET(nlcCheck->s, fd); - if (si.pending(nlcCheck->hSsl)) - pending++; - } - return 1; -} - -INT_PTR NetlibSelect(WPARAM, LPARAM lParam) -{ - NETLIBSELECT *nls = (NETLIBSELECT*)lParam; - if (nls == NULL || nls->cbSize != sizeof(NETLIBSELECT)) { - SetLastError(ERROR_INVALID_PARAMETER); - return SOCKET_ERROR; - } - - TIMEVAL tv; - tv.tv_sec = nls->dwTimeout/1000; - tv.tv_usec = (nls->dwTimeout%1000)*1000; - - int pending = 0; - fd_set readfd, writefd, exceptfd; - WaitForSingleObject(hConnectionHeaderMutex, INFINITE); - if (!ConnectionListToSocketList(nls->hReadConns, &readfd, pending) - || !ConnectionListToSocketList(nls->hWriteConns, &writefd, pending) - || !ConnectionListToSocketList(nls->hExceptConns, &exceptfd, pending)) - { - ReleaseMutex(hConnectionHeaderMutex); - return SOCKET_ERROR; - } - ReleaseMutex(hConnectionHeaderMutex); - if (pending) - return 1; - - return select(0, &readfd, &writefd, &exceptfd, nls->dwTimeout == INFINITE ? NULL : &tv); -} - -INT_PTR NetlibSelectEx(WPARAM, LPARAM lParam) -{ - NETLIBSELECTEX *nls = (NETLIBSELECTEX*)lParam; - if (nls == NULL || nls->cbSize != sizeof(NETLIBSELECTEX)) { - SetLastError(ERROR_INVALID_PARAMETER); - return SOCKET_ERROR; - } - - TIMEVAL tv; - tv.tv_sec = nls->dwTimeout / 1000; - tv.tv_usec = (nls->dwTimeout % 1000) * 1000; - WaitForSingleObject(hConnectionHeaderMutex, INFINITE); - - int pending = 0; - fd_set readfd, writefd, exceptfd; - if (!ConnectionListToSocketList(nls->hReadConns, &readfd, pending) - || !ConnectionListToSocketList(nls->hWriteConns, &writefd, pending) - || !ConnectionListToSocketList(nls->hExceptConns, &exceptfd, pending)) - { - ReleaseMutex(hConnectionHeaderMutex); - return SOCKET_ERROR; - } - ReleaseMutex(hConnectionHeaderMutex); - - int rc = (pending) ? pending : select(0, &readfd, &writefd, &exceptfd, nls->dwTimeout == INFINITE ? NULL : &tv); - - WaitForSingleObject(hConnectionHeaderMutex, INFINITE); - /* go thru each passed HCONN array and grab its socket handle, then give it to FD_ISSET() - to see if an event happened for that socket, if it has it will be returned as TRUE (otherwise not) - This happens for read/write/except */ - NetlibConnection *conn = NULL; - int j; - for (j = 0; j < FD_SETSIZE; j++) { - conn = (NetlibConnection*)nls->hReadConns[j]; - if (conn == NULL || conn == INVALID_HANDLE_VALUE) break; - - if (si.pending(conn->hSsl)) - nls->hReadStatus[j] = TRUE; - if (conn->usingHttpGateway && conn->nlhpi.szHttpGetUrl == NULL && conn->dataBuffer == NULL) - nls->hReadStatus[j] = (conn->pHttpProxyPacketQueue != NULL); - else - nls->hReadStatus[j] = FD_ISSET(conn->s, &readfd); - } - for (j = 0; j < FD_SETSIZE; j++) { - conn = (NetlibConnection*)nls->hWriteConns[j]; - if (conn == NULL || conn == INVALID_HANDLE_VALUE) break; - nls->hWriteStatus[j] = FD_ISSET(conn->s, &writefd); - } - for (j = 0; j < FD_SETSIZE; j++) { - conn = (NetlibConnection*)nls->hExceptConns[j]; - if (conn == NULL || conn == INVALID_HANDLE_VALUE) break; - nls->hExceptStatus[j] = FD_ISSET(conn->s, &exceptfd); - } - ReleaseMutex(hConnectionHeaderMutex); - return rc; -} - -bool NetlibStringToAddress(const char* str, SOCKADDR_INET_M* addr) -{ - if (!str) return false; - - int len = sizeof(SOCKADDR_INET_M); - return !WSAStringToAddressA((char*)str, AF_INET6, NULL, (PSOCKADDR)addr, &len); -} - -char* NetlibAddressToString(SOCKADDR_INET_M* addr) -{ - char saddr[128]; - DWORD len = sizeof(saddr); - if (!WSAAddressToStringA((PSOCKADDR)addr, sizeof(*addr), NULL, saddr, &len)) - return mir_strdup(saddr); - - if (addr->si_family == AF_INET) { - char *szIp = inet_ntoa(addr->Ipv4.sin_addr); - if (addr->Ipv4.sin_port != 0) { - mir_snprintf(saddr, SIZEOF(saddr), "%s:%d", szIp, htons(addr->Ipv4.sin_port)); - return mir_strdup(saddr); - } - return mir_strdup(szIp); - } - return NULL; -} - -void NetlibGetConnectionInfo(NetlibConnection* nlc, NETLIBCONNINFO *connInfo) -{ - if (!nlc || !connInfo || connInfo->cbSize < sizeof(NETLIBCONNINFO)) return; - - SOCKADDR_INET_M sin = { 0 }; - int len = sizeof(sin); - if (!getsockname(nlc->s, (PSOCKADDR)&sin, &len)) { - connInfo->wPort = ntohs(sin.Ipv4.sin_port); - connInfo->dwIpv4 = sin.si_family == AF_INET ? htonl(sin.Ipv4.sin_addr.s_addr) : 0; - - char *szTmp = NetlibAddressToString(&sin); - strncpy(connInfo->szIpPort, szTmp, sizeof(connInfo->szIpPort)); - connInfo->szIpPort[sizeof(connInfo->szIpPort) - 1] = 0; - mir_free(szTmp); - } -} - -inline bool IsAddrGlobal(const IN6_ADDR *a) -{ - unsigned char High = a->s6_bytes[0] & 0xf0; - return High != 0 && High != 0xf0; -} - -static NETLIBIPLIST* GetMyIpv6(unsigned flags) -{ - addrinfo *air = NULL, *ai, hints = { 0 }; - const char *szMyHost = ""; - - hints.ai_family = AF_UNSPEC; - hints.ai_flags = AI_PASSIVE; - - if (GetAddrInfoA(szMyHost, NULL, &hints, &air)) - return NULL; - - unsigned n = 0; - for (ai = air; ai; ai = ai->ai_next) { - SOCKADDR_INET_M *iaddr = (SOCKADDR_INET_M*)ai->ai_addr; - if (ai->ai_family == AF_INET || (ai->ai_family == AF_INET6 && (!(flags & 1) || IsAddrGlobal(&iaddr->Ipv6.sin6_addr)))) - ++n; - } - - NETLIBIPLIST *addr = (NETLIBIPLIST*)mir_calloc(n * 64 + 4); - addr->cbNum = n; - - unsigned i = 0; - for (ai = air; ai; ai = ai->ai_next) { - SOCKADDR_INET_M *iaddr = (SOCKADDR_INET_M*)ai->ai_addr; - if (ai->ai_family == AF_INET || - (ai->ai_family == AF_INET6 && - (!(flags & 1) || IsAddrGlobal(&iaddr->Ipv6.sin6_addr)))) - { - char *szIp = NetlibAddressToString(iaddr); - if (szIp) - strncpy_s(addr->szIp[i++], szIp, _TRUNCATE); - mir_free(szIp); - } - } - FreeAddrInfoA(air); - return addr; -} - -static NETLIBIPLIST* GetMyIpv4(void) -{ - char hostname[256] = ""; - - gethostname(hostname, sizeof(hostname)); - PHOSTENT he = gethostbyname(hostname); - - unsigned n; - for (n = 0; he->h_addr_list[n]; ++n) - ; - - NETLIBIPLIST *addr = (NETLIBIPLIST*)mir_calloc(n * 64 + 4); - addr->cbNum = n; - - for (unsigned i = 0; i < n; i++) - strncpy_s(addr->szIp[i], inet_ntoa(*(PIN_ADDR)he->h_addr_list[i]), _TRUNCATE); - - return addr; -} - -NETLIBIPLIST* GetMyIp(unsigned flags) -{ - return GetMyIpv6(flags); -} diff --git a/src/modules/netlib/netlibupnp.cpp b/src/modules/netlib/netlibupnp.cpp deleted file mode 100644 index d3f30498d6..0000000000 --- a/src/modules/netlib/netlibupnp.cpp +++ /dev/null @@ -1,826 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -#include "..\..\core\commonheaders.h" -#include "netlib.h" - -static const char search_request_msg[] = - "M-SEARCH * HTTP/1.1\r\n" - "HOST: 239.255.255.250:1900\r\n" - "MAN: \"ssdp:discover\"\r\n" - "MX: 1\r\n" - "ST: urn:schemas-upnp-org:service:%s\r\n" - "\r\n"; - -static const char xml_get_hdr[] = - "GET %s HTTP/1.1\r\n" - "HOST: %s:%u\r\n" - "ACCEPT-LANGUAGE: *\r\n\r\n"; - -static const char soap_post_hdr[] = - "POST %s HTTP/1.1\r\n" - "HOST: %s:%u\r\n" - "CONTENT-LENGTH: %u\r\n" - "CONTENT-TYPE: text/xml; charset = \"utf-8\"\r\n" - "SOAPACTION: \"%s#%s\"\r\n\r\n" - "%s"; - -static const char soap_post_hdr_m[] = - "M-POST %s URL HTTP/1.1\r\n" - "HOST: %s:%u\r\n" - "CONTENT-LENGTH: %u\r\n" - "CONTENT-TYPE: text/xml; charset = \"utf-8\"\r\n" - "MAN: \"http://schemas.xmlsoap.org/soap/envelope/\"; ns = 01\r\n" - "01-SOAPACTION: \"%s#%s\"\r\n\r\n" - "%s"; - -static const char search_device[] = - "%s"; - -static const char soap_action[] = - "\r\n" - "\r\n" - " \r\n" - " \r\n" - "%s" - " \r\n" - " \r\n" - "\r\n"; - -static const char soap_query[] = - "\r\n" - " \r\n" - " \r\n" - " %s\r\n" - " \r\n" - " \r\n" - "\r\n"; - -static const char add_port_mapping[] = - " \r\n" - " %i\r\n" - " %s\r\n" - " %i\r\n" - " %s\r\n" - " 1\r\n" - " Miranda\r\n" - " 0\r\n"; - -static const char delete_port_mapping[] = - " \r\n" - " %i\r\n" - " %s\r\n"; - -static const char get_port_mapping[] = - " %i\r\n"; - -static bool gatewayFound; -static SOCKADDR_IN locIP; -static time_t lastDiscTime; -static int expireTime = 120; - -static int retryCount; -static SOCKET sock = INVALID_SOCKET; -static char szConnHost[256]; -static unsigned short sConnPort; - -static WORD *portList; -static unsigned numports, numportsAlloc; -static HANDLE portListMutex; - -static char szCtlUrl[256], szDev[256]; - -typedef enum -{ - DeviceGetReq, - ControlAction, - ControlQuery -} ReqType; - -static bool txtParseParam(char* szData, char* presearch, - char* start, char* finish, char* param, size_t size) -{ - char *cp, *cp1; - size_t len; - - *param = 0; - - if (presearch != NULL) { - cp1 = strstr(szData, presearch); - if (cp1 == NULL) return false; - } - else - cp1 = szData; - - cp = strstr(cp1, start); - if (cp == NULL) return false; - cp += mir_strlen(start); - while (*cp == ' ') ++cp; - - cp1 = strstr(cp, finish); - if (cp1 == NULL) return false; - while (*(cp1-1) == ' ' && cp1 > cp) --cp1; - - len = min((size_t)(cp1 - cp), size-1); - strncpy(param, cp, len); - param[len] = 0; - - return true; -} - -void parseURL(char* szUrl, char* szHost, unsigned short* sPort, char* szPath) -{ - char *ppath, *phost, *pport; - int sz; - - phost = strstr(szUrl, "://"); - if (phost == NULL) phost = szUrl; - else phost += 3; - - ppath = strchr(phost, '/'); - if (ppath == NULL) ppath = phost + mir_strlen(phost); - - pport = strchr(phost, ':'); - if (pport == NULL) pport = ppath; - - if (szHost != NULL) { - sz = pport - phost + 1; - if (sz > 256) sz = 256; - strncpy(szHost, phost, sz); - szHost[sz - 1] = 0; - } - - if (sPort != NULL) { - if (pport < ppath) { - long prt = atol(pport + 1); - *sPort = prt != 0 ? (unsigned short)prt : 80; - } - else - *sPort = 80; - } - - if (szPath != NULL) { - strncpy(szPath, ppath, 256); - szPath[255] = 0; - } -} - -static void LongLog(char* szData) -{ - CallService(MS_NETLIB_LOG, 0, (LPARAM)szData); -} - -static void closeRouterConnection(void) -{ - if (sock != INVALID_SOCKET) { - closesocket(sock); - sock = INVALID_SOCKET; - } -} - -static void validateSocket(void) -{ - static const TIMEVAL tv = { 0, 0 }; - fd_set rfd; - char buf[4]; - bool opened; - - if (sock == INVALID_SOCKET) - return; - - FD_ZERO(&rfd); - FD_SET(sock, &rfd); - - switch (select(1, &rfd, NULL, NULL, &tv)) { - case SOCKET_ERROR: - opened = false; - break; - - case 0: - opened = true; - break; - - case 1: - opened = recv(sock, buf, 1, MSG_PEEK) > 0; - break; - } - - if (!opened) - closeRouterConnection(); -} - -static int httpTransact(char* szUrl, char* szResult, int resSize, char* szActionName, ReqType reqtype) -{ - // Parse URL - char szHost[256], szPath[256], szRes[16]; - int sz = 0, res = 0; - unsigned short sPort; - bool needClose = false; - - const char* szPostHdr = soap_post_hdr; - char* szData = (char*)mir_alloc(4096); - char* szReq = NULL; - - parseURL(szUrl, szHost, &sPort, szPath); - - if (sPort != sConnPort || _stricmp(szHost, szConnHost)) - closeRouterConnection(); - else - validateSocket(); - - while (true) { - retryCount = 0; - switch (reqtype) { - case DeviceGetReq: - sz = mir_snprintf(szData, 4096, xml_get_hdr, szPath, szHost, sPort); - break; - - case ControlAction: - { - char szData1[1024]; - - szReq = mir_strdup(szResult); - sz = mir_snprintf(szData1, SIZEOF(szData1), - soap_action, szActionName, szDev, szReq, szActionName); - - sz = mir_snprintf(szData, 4096, - szPostHdr, szPath, szHost, sPort, - sz, szDev, szActionName, szData1); - } - break; - - case ControlQuery: - { - char szData1[1024]; - - sz = mir_snprintf(szData1, SIZEOF(szData1), - soap_query, szActionName); - - sz = mir_snprintf(szData, 4096, - szPostHdr, szPath, szHost, sPort, - sz, "urn:schemas-upnp-org:control-1-0", "QueryStateVariable", szData1); - } - break; - } - szResult[0] = 0; - { - static const TIMEVAL tv = { 6, 0 }; - static unsigned ttl = 4; - static u_long mode = 1; - fd_set rfd, wfd, efd; - SOCKADDR_IN enetaddr; - -retrycon: - if (sock == INVALID_SOCKET) { - sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - - enetaddr.sin_family = AF_INET; - enetaddr.sin_port = htons(sPort); - enetaddr.sin_addr.s_addr = inet_addr(szHost); - - // Resolve host name if needed - if (enetaddr.sin_addr.s_addr == INADDR_NONE) { - PHOSTENT he = gethostbyname(szHost); - if (he) - enetaddr.sin_addr.s_addr = *(unsigned*)he->h_addr_list[0]; - } - - NetlibLogf(NULL, "UPnP HTTP connection Host: %s Port: %u", szHost, sPort); - - FD_ZERO(&rfd); FD_ZERO(&wfd); FD_ZERO(&efd); - FD_SET(sock, &rfd); FD_SET(sock, &wfd); FD_SET(sock, &efd); - - // Limit the scope of the connection (does not work for - setsockopt(sock, IPPROTO_IP, IP_TTL, (char *)&ttl, sizeof(unsigned)); - - // Put socket into non-blocking mode for timeout on connect - ioctlsocket(sock, FIONBIO, &mode); - - // Connect to the remote host - if (connect(sock, (SOCKADDR*)&enetaddr, sizeof(enetaddr)) == SOCKET_ERROR) { - int err = WSAGetLastError(); - - // Socket connection failed - if (err != WSAEWOULDBLOCK) { - closeRouterConnection(); - NetlibLogf(NULL, "UPnP connect failed %d", err); - break; - } - // Wait for socket to connect - else if (select(1, &rfd, &wfd, &efd, &tv) != 1) { - closeRouterConnection(); - NetlibLogf(NULL, "UPnP connect timeout"); - break; - } - else if (!FD_ISSET(sock, &wfd)) { - closeRouterConnection(); - NetlibLogf(NULL, "UPnP connect failed"); - break; - } - } - strncpy_s(szConnHost, szHost, _TRUNCATE); - sConnPort = sPort; - } - - if (send(sock, szData, sz, 0) != SOCKET_ERROR) { - char *hdrend = NULL; - int acksz = 0, pktsz = 0; - - if (szActionName == NULL) { - int len = sizeof(locIP); - getsockname(sock, (SOCKADDR*)&locIP, &len); - if (locIP.sin_addr.S_un.S_addr == 0x0100007f) { - struct hostent *he; - - gethostname(szPath, sizeof(szPath)); - he = gethostbyname(szPath); - if (he != NULL) - locIP.sin_addr.S_un.S_addr = *(PDWORD)he->h_addr_list[0]; - } - } - - LongLog(szData); - sz = 0; - while (true) { - int bytesRecv; - - FD_ZERO(&rfd); - FD_SET(sock, &rfd); - - // Wait for the next packet - if (select(1, &rfd, NULL, NULL, &tv) != 1) { - closeRouterConnection(); - NetlibLogf(NULL, "UPnP recieve timeout"); - break; - } - - // - bytesRecv = recv(sock, &szResult[sz], resSize - sz, 0); - - // Connection closed or aborted, all data received - if (bytesRecv == 0 || bytesRecv == SOCKET_ERROR) { - closeRouterConnection(); - if ((bytesRecv == SOCKET_ERROR || sz == 0) && retryCount < 2) { - ++retryCount; - goto retrycon; - } - break; - } - - sz += bytesRecv; - - // Insert null terminator to use string functions - if (sz >= (resSize - 1)) { - szResult[resSize - 1] = 0; - break; - } - else - szResult[sz] = 0; - - // HTTP header found? - if (hdrend == NULL) { - // Find HTTP header end - hdrend = strstr(szResult, "\r\n\r\n"); - if (hdrend == NULL) { - hdrend = strstr(szResult, "\n\n"); - if (hdrend) hdrend += 2; - } - - else - hdrend += 4; - - if (hdrend != NULL) { - // Get packet size if provided - if (txtParseParam(szResult, NULL, "Content-Length:", "\n", szRes, sizeof(szRes)) || - txtParseParam(szResult, NULL, "CONTENT-LENGTH:", "\n", szRes, sizeof(szRes))) { - // Add size of HTTP header to the packet size to compute full transmission size - pktsz = atol(ltrimp(szRes)) + (hdrend - szResult); - } - // Get encoding type if provided - else if (txtParseParam(szResult, NULL, "Transfer-Encoding:", "\n", szRes, sizeof(szRes))) { - if (_stricmp(lrtrimp(szRes), "Chunked") == 0) - acksz = hdrend - szResult; - } - if (txtParseParam(szResult, NULL, "Connection:", "\n", szRes, sizeof(szRes))) { - needClose = (_stricmp(lrtrimp(szRes), "close") == 0); - } - } - } - - // Content-Length bytes reached, all data received - if (sz >= pktsz && pktsz != 0) { - szResult[pktsz] = 0; - break; - } - - // Chunked encoding processing - if (sz > acksz && acksz != 0) { -retry: - // Parse out chunk size - char* data = szResult + acksz; - char* peol1 = data == hdrend ? data - 1 : strchr(data, '\n'); - if (peol1 != NULL) { - char *peol2 = strchr(++peol1, '\n'); - if (peol2 != NULL) { - // Get chunk size - int chunkBytes = strtol(peol1, NULL, 16); - acksz += chunkBytes; - peol2++; - - memmove(data, peol2, mir_strlen(peol2) + 1); - sz -= peol2 - data; - - // Last chunk, all data received - if (chunkBytes == 0) break; - if (sz > acksz) goto retry; - } - } - } - } - LongLog(szResult); - } - else { - if (retryCount < 2) { - closeRouterConnection(); - ++retryCount; - goto retrycon; - } - else - NetlibLogf(NULL, "UPnP send failed %d", WSAGetLastError()); - } - } - txtParseParam(szResult, "HTTP", " ", " ", szRes, sizeof(szRes)); - res = atol(szRes); - if (szActionName != NULL && res == 405 && szPostHdr == soap_post_hdr) - szPostHdr = soap_post_hdr_m; - else - break; - } - - if (needClose) - closeRouterConnection(); - - mir_free(szData); - mir_free(szReq); - return res; -} - -static unsigned getExtIP(void) -{ - char szExtIP[30]; - char* szData = (char*)mir_alloc(4096); szData[0] = 0; - - unsigned extip = 0; - int res = httpTransact(szCtlUrl, szData, 4096, "GetExternalIPAddress", ControlAction); - if (res == 200 && txtParseParam(szData, "", "<", szExtIP, sizeof(szExtIP))) - extip = ntohl(inet_addr(szExtIP)); - - mir_free(szData); - return extip; -} - -static bool getUPnPURLs(char* szUrl, size_t sizeUrl) -{ - char* szData = (char*)mir_alloc(8192); - - gatewayFound = httpTransact(szUrl, szData, 8192, NULL, DeviceGetReq) == 200; - if (gatewayFound) { - char szTemp[256], *rpth; - size_t ctlLen; - - txtParseParam(szData, NULL, "", "", szTemp, sizeof(szTemp)); - strncpy(szCtlUrl, szTemp[0] ? szTemp : szUrl, sizeof(szCtlUrl)); - szCtlUrl[sizeof(szCtlUrl) - 1] = 0; - - mir_snprintf(szTemp, search_device, szDev); - txtParseParam(szData, szTemp, "", "", szUrl, sizeUrl); - - // URL combining per RFC 2396 - if (szUrl[0] != 0) { - if (strstr(szUrl, "://") != NULL) // absolute URI - rpth = szCtlUrl; - else if (strncmp(szUrl, "//", 2) == 0) // relative URI net_path - { - rpth = strstr(szCtlUrl, "//"); - if (rpth == NULL) rpth = szCtlUrl; - } - else if (szUrl[0] == '/') // relative URI abs_path - { - rpth = strstr(szCtlUrl, "//"); - rpth = rpth ? rpth + 2 : szCtlUrl; - - rpth = strchr(rpth, '/'); - if (rpth == NULL) rpth = szCtlUrl + mir_strlen(szCtlUrl); - } - else { // relative URI rel_path - size_t ctlCLen = mir_strlen(szCtlUrl); - rpth = szCtlUrl + ctlCLen; - if (ctlCLen != 0 && *(rpth - 1) != '/') - strncpy(rpth++, "/", sizeof(szCtlUrl) - ctlCLen); - } - - ctlLen = sizeof(szCtlUrl) - (rpth - szCtlUrl); - strncpy(rpth, szUrl, ctlLen); - szCtlUrl[sizeof(szCtlUrl) - 1] = 0; - } - else { - szCtlUrl[0] = 0; - gatewayFound = false; - } - } - mir_free(szData); - - return gatewayFound; -} - -static void discoverUPnP(void) -{ - char* buf; - int buflen; - unsigned i, j, nip = 0; - unsigned* ips = NULL; - - static const unsigned any = INADDR_ANY; - static const TIMEVAL tv = { 1, 600000 }; - - char szUrl[256] = ""; - char hostname[256]; - PHOSTENT he; - fd_set readfd; - - SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - - SOCKADDR_IN enetaddr; - enetaddr.sin_family = AF_INET; - enetaddr.sin_port = htons(1900); - enetaddr.sin_addr.s_addr = inet_addr("239.255.255.250"); - - gethostname(hostname, sizeof(hostname)); - he = gethostbyname(hostname); - - if (he) { - while (he->h_addr_list[nip]) ++nip; - - ips = (unsigned*)mir_alloc(nip * sizeof(unsigned)); - - for (j = 0; j < nip; j++) - ips[j] = *(unsigned*)he->h_addr_list[j]; - } - - buf = (char*)mir_alloc(1500); - - for (i = 3; --i && szUrl[0] == 0;) { - for (j = 0; j < nip; j++) { - if (ips) - setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (char *)&ips[j], sizeof(unsigned)); - - buflen = mir_snprintf(buf, 1500, search_request_msg, "WANIPConnection:1"); - sendto(sock, buf, buflen, 0, (SOCKADDR*)&enetaddr, sizeof(enetaddr)); - LongLog(buf); - - buflen = mir_snprintf(buf, 1500, search_request_msg, "WANPPPConnection:1"); - sendto(sock, buf, buflen, 0, (SOCKADDR*)&enetaddr, sizeof(enetaddr)); - LongLog(buf); - } - - if (Miranda_Terminated()) break; - - FD_ZERO(&readfd); - FD_SET(sock, &readfd); - - while (select(1, &readfd, NULL, NULL, &tv) >= 1) { - buflen = recv(sock, buf, 1500, 0); - if (buflen != SOCKET_ERROR) { - buf[buflen] = 0; - LongLog(buf); - - if (txtParseParam(buf, NULL, "LOCATION:", "\n", szUrl, sizeof(szUrl)) || - txtParseParam(buf, NULL, "Location:", "\n", szUrl, sizeof(szUrl))) { - char age[30]; - char szHostNew[256], szHostExist[256]; - - lrtrim(szUrl); - - parseURL(szUrl, szHostNew, NULL, NULL); - parseURL(szCtlUrl, szHostExist, NULL, NULL); - if (mir_strcmp(szHostNew, szHostExist) == 0) { - gatewayFound = true; - break; - } - - txtParseParam(buf, NULL, "ST:", "\n", szDev, sizeof(szDev)); - txtParseParam(buf, "max-age", " = ", "\n", age, sizeof(age)); - expireTime = atoi(lrtrimp(age)); - lrtrim(szDev); - - if (getUPnPURLs(szUrl, sizeof(szUrl))) { - gatewayFound = getExtIP() != 0; - if (gatewayFound) break; - } - } - } - FD_ZERO(&readfd); - FD_SET(sock, &readfd); - } - } - - mir_free(buf); - mir_free(ips); - setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (char *)&any, sizeof(unsigned)); - closesocket(sock); -} - -static bool findUPnPGateway(void) -{ - if ((time(NULL) - lastDiscTime) >= expireTime) { - WaitForSingleObject(portListMutex, INFINITE); - - time_t curTime = time(NULL); - - if ((curTime - lastDiscTime) >= expireTime) { - gatewayFound = false; - - discoverUPnP(); - lastDiscTime = curTime; - - NetlibLogf(NULL, "UPnP Gateway detected %d, Control URL: %s", gatewayFound, szCtlUrl); - } - - ReleaseMutex(portListMutex); - } - - return gatewayFound; -} - -bool NetlibUPnPAddPortMapping(WORD intport, char *proto, WORD *extport, DWORD *extip, bool search) -{ - int res = 0, i = 5; - - if (findUPnPGateway()) { - char* szData = (char*)mir_alloc(4096); - char szExtIP[30]; - - *extport = intport - 1; - *extip = ntohl(locIP.sin_addr.S_un.S_addr); - - WaitForSingleObject(portListMutex, INFINITE); - - do { - ++*extport; - mir_snprintf(szData, 4096, add_port_mapping, - *extport, proto, intport, inet_ntoa(locIP.sin_addr)); - res = httpTransact(szCtlUrl, szData, 4096, "AddPortMapping", ControlAction); - txtParseParam(szData, NULL, "", "", szExtIP, sizeof(szExtIP)); - - } while (search && res == 500 && atol(szExtIP) == 718 && --i); - - mir_free(szData); - - if (res == 200) { - unsigned ip = getExtIP(); - if (ip) *extip = ip; - - if (numports >= numportsAlloc) - mir_realloc(portList, sizeof(WORD)*(numportsAlloc += 10)); - portList[numports++] = *extport; - } - - ReleaseMutex(portListMutex); - } - - return res == 200; -} - -void NetlibUPnPDeletePortMapping(WORD extport, char* proto) -{ - if (extport == 0) - return; - - // findUPnPGateway(); - - if (gatewayFound) { - unsigned i; - char* szData = (char*)mir_alloc(4096); - - WaitForSingleObject(portListMutex, INFINITE); - mir_snprintf(szData, 4096, delete_port_mapping, extport, proto); - httpTransact(szCtlUrl, szData, 4096, "DeletePortMapping", ControlAction); - - for (i = 0; i < numports; i++) - if (portList[i] == extport && --numports > 0) - memmove(&portList[i], &portList[i + 1], (numports - i) * sizeof(WORD)); - - mir_free(szData); - ReleaseMutex(portListMutex); - } -} - -void NetlibUPnPCleanup(void*) -{ - // upnp is disabled globally, no need for a cleanup - if (db_get_b(NULL, "Netlib", "NLEnableUPnP", 1) == 0) - return; - - { - int incoming = 0; - mir_cslock lck(csNetlibUser); - for (int i = 0; i < netlibUser.getCount(); i++) - if (netlibUser[i]->user.flags & NUF_INCOMING) { - incoming = 1; - break; - } - - if (!incoming) - return; - } - - if (findUPnPGateway()) { - char *szData = (char*)alloca(4096); - char buf[50], lip[50]; - unsigned j = 0, k, num = 100; - - strncpy_s(lip, inet_ntoa(locIP.sin_addr), _TRUNCATE); - - WaitForSingleObject(portListMutex, INFINITE); - - if (httpTransact(szCtlUrl, szData, 4096, "PortMappingNumberOfEntries", ControlQuery) == 200 && - txtParseParam(szData, "QueryStateVariableResponse", "", "<", buf, sizeof(buf))) - num = atol(buf); - - WORD ports[30]; - for (unsigned i = 0; i < num && !Miranda_Terminated(); i++) { - mir_snprintf(szData, 4096, get_port_mapping, i); - - ReleaseMutex(portListMutex); - WaitForSingleObject(portListMutex, INFINITE); - - if (httpTransact(szCtlUrl, szData, 4096, "GetGenericPortMappingEntry", ControlAction) != 200) - break; - - if (!txtParseParam(szData, "", "<", buf, sizeof(buf)) || mir_strcmp(buf, "Miranda") != 0) - continue; - - if (!txtParseParam(szData, "", "<", buf, sizeof(buf)) || mir_strcmp(buf, lip) != 0) - continue; - - if (txtParseParam(szData, "", "<", buf, sizeof(buf))) { - WORD mport = (WORD)atol(buf); - - if (j >= SIZEOF(ports)) - break; - - for (k = 0; k < numports; ++k) - if (portList[k] == mport) - break; - - if (k >= numports) - ports[j++] = mport; - } - } - - ReleaseMutex(portListMutex); - - for (unsigned i = 0; i < j && !Miranda_Terminated(); i++) - NetlibUPnPDeletePortMapping(ports[i], "TCP"); - } -} - -void NetlibUPnPInit(void) -{ - numports = 0; - numportsAlloc = 10; - portList = (WORD*)mir_alloc(sizeof(WORD)*numportsAlloc); - - portListMutex = CreateMutex(NULL, FALSE, NULL); -} - -void NetlibUPnPDestroy(void) -{ - mir_free(portList); - CloseHandle(portListMutex); -} -- cgit v1.2.3