static bool NetlibInitHttpsConnection(struct NetlibConnection *nlc, struct NetlibUser *nlu, NETLIBOPENCONNECTION *nloc) { //rfc2817 NETLIBHTTPREQUEST nlhrSend = {0}, *nlhrReply; 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, SIZEOF(szUrl), "%s:%u", nloc->szHost, nloc->wPort); } else { DWORD ip = DnsLookup(nlu, nloc->szHost); if (ip == 0) return false; mir_snprintf(szUrl, SIZEOF(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; } 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; }
int NetlibInitHttpConnection(NetlibConnection *nlc, NetlibUser *nlu, NETLIBOPENCONNECTION *nloc) { NETLIBHTTPREQUEST *nlhrReply = NULL; 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; }
static bool NetlibHttpGatewayOscarPost(NetlibConnection *nlc, const char *buf, int len, int flags) { NETLIBHTTPREQUEST *nlhrReply = NULL; 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); EnterCriticalSection(&nlc->csHttpSequenceNums); nlc->nlhpi.firstPostSequence++; if (nlc->nlhpi.flags & NLHPIF_GETPOSTSAMESEQUENCE) nlc->nlhpi.firstGetSequence++; LeaveCriticalSection(&nlc->csHttpSequenceNums); return res; }
static bool NetlibHttpGatewayOscarPost(NetlibConnection *nlc, const char *buf, int len, int flags) { NetlibConnection *nlcSend = new NetlibConnection(); 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)) { delete nlcSend; return false; } nlc->s2 = nlcSend->s; 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; } nlc->s2 = nlcSend->s; delete nlcSend; mir_cslock lck(nlc->csHttpSequenceNums); nlc->nlhpi.firstPostSequence++; if (nlc->nlhpi.flags & NLHPIF_GETPOSTSAMESEQUENCE) nlc->nlhpi.firstGetSequence++; return res; }
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 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 = 0; bool lastFirstLineFail = false; if (nlhr == NULL || nlhr->cbSize != sizeof(NETLIBHTTPREQUEST) || nlhr->szUrl == NULL || nlhr->szUrl[0] == '\0') { SetLastError(ERROR_INVALID_PARAMETER); return SOCKET_ERROR; } NetlibUser *nlu = nlc->nlu; if (GetNetlibHandleType(nlu) != NLH_USER) { 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 (GetNetlibHandleType(nlc) != NLH_CONNECTION) { nlc = NULL; bytesSent = SOCKET_ERROR; break; } 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(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 (nlu->szStickyHeaders != NULL) AppendToCharBuffer(&httpRequest, "%s\r\n", 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)) { DWORD err = GetLastError(); NetlibLogf(nlu, "%s %d: %s Failed (%u %u)", __FILE__, __LINE__, "HttpPeekFirstResponseLine", err, count); // connection died while we were waiting if (GetNetlibHandleType(nlc) != NLH_CONNECTION) { nlc = NULL; break; } 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, 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 && !nlc->usingHttpGateway) NetlibLeaveNestedCS(&nlc->ncsSend); return bytesSent; }
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; i < nlhrReply->headersCount; 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; }
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; }