int CHttpControlSocket::FileTransferSend() { LogMessage(Debug_Verbose, _T("CHttpControlSocket::FileTransferSend()")); if (!m_pCurOpData) { LogMessage(__TFILE__, __LINE__, this, Debug_Info, _T("Empty m_pCurOpData")); ResetOperation(FZ_REPLY_INTERNALERROR); return FZ_REPLY_ERROR; } CHttpFileTransferOpData *pData = static_cast<CHttpFileTransferOpData *>(m_pCurOpData); if (pData->opState == filetransfer_waitfileexists) { pData->opState = filetransfer_transfer; pData->pFile = new wxFile(); CreateLocalDir(pData->localFile); if (!pData->pFile->Open(pData->localFile, wxFile::write)) { LogMessage(::Error, _("Failed to open \"%s\" for writing"), pData->localFile.c_str()); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } int res = InternalConnect(m_pCurrentServer->GetHost(), m_pCurrentServer->GetPort(), m_pCurrentServer->GetProtocol() == HTTPS); if (res != FZ_REPLY_OK) return res; } wxString location; wxString hostWithPort; if (pData->m_newLocation == _T("")) { if (m_pCurrentServer->GetProtocol() == HTTPS) location = _T("https://") + wxString(m_pCurrentServer->FormatHost()) + wxString(pData->remotePath.FormatFilename(pData->remoteFile).c_str()); else location = _T("http://") + wxString(m_pCurrentServer->FormatHost()) + wxString(pData->remotePath.FormatFilename(pData->remoteFile).c_str()); hostWithPort = wxString::Format(_T("%s:%d"), m_pCurrentServer->FormatHost(true).c_str(), m_pCurrentServer->GetPort()); } else { location = pData->m_newLocation; hostWithPort = pData->m_newHostWithPort; } wxString action = wxString::Format(_T("GET %s HTTP/1.1"), location.c_str()); LogMessageRaw(Command, action); wxString command = wxString::Format(_T("%s\r\nHost: %s\r\nUser-Agent: %s\r\nConnection: close\r\n\r\n"), action.c_str(), hostWithPort.c_str(), wxString(PACKAGE_STRING, wxConvLocal).c_str()); const wxWX2MBbuf str = command.mb_str(); if (!Send(str, strlen(str))) return FZ_REPLY_ERROR; return FZ_REPLY_WOULDBLOCK; }
void CControlSocket::ShowStatus(CString status, int type) const { if ( status.Left(5)==_T("PASS ") ) { int len=status.GetLength()-5; status=_T("PASS "); for (int i=0;i<len;i++) status+=_MPT("*"); } else if ( status.Left(5)==_T("ACCT ") ) { int len=status.GetLength()-5; status=_T("ACCT "); for (int i=0;i<len;i++) status+=_MPT("*"); } LogMessageRaw(type, (LPCTSTR)status); }
void CControlSocket::ShowStatus(CString status, int type) const { if (!COptions::GetOptionVal(OPTION_MPEXT_LOG_SENSITIVE)) { if ( status.Left(5)==_T("PASS ") ) { int len=status.GetLength()-5; status=_T("PASS "); for (int i=0;i<len;i++) status+=_MPT("*"); } else if ( status.Left(5)==_T("ACCT ") ) { int len=status.GetLength()-5; status=_T("ACCT "); for (int i=0;i<len;i++) status+=_MPT("*"); } } LogMessageRaw(type, (LPCTSTR)status); }
int CControlSocket::OnLayerCallback(rde::list<t_callbackMsg>& callbacks) { USES_CONVERSION; for (rde::list<t_callbackMsg>::iterator iter = callbacks.begin(); iter != callbacks.end(); iter++) { if (iter->nType == LAYERCALLBACK_STATECHANGE) { if (CAsyncSocketEx::LogStateChange(iter->nParam1, iter->nParam2)) { const TCHAR * state2Desc = CAsyncSocketEx::GetStateDesc(iter->nParam2); const TCHAR * state1Desc = CAsyncSocketEx::GetStateDesc(iter->nParam1); if (iter->pLayer == m_pProxyLayer) LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("Proxy layer changed state from %s to %s"), state2Desc, state1Desc); #ifndef MPEXT_NO_GSS else if (iter->pLayer == m_pGssLayer) LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("m_pGssLayer changed state from %s to %s"), state2Desc, state1Desc); #endif else LogMessage(__FILE__, __LINE__, this, FZ_LOG_INFO, _T("Layer @ %d changed state from %s to %s"), iter->pLayer, state2Desc, state1Desc); } } else if (iter->nType == LAYERCALLBACK_LAYERSPECIFIC) { if (iter->pLayer == m_pProxyLayer) { switch (iter->nParam1) { case PROXYERROR_NOERROR: ShowStatus(IDS_PROXY_CONNECTED, FZ_LOG_STATUS); break; case PROXYERROR_NOCONN: ShowStatus(IDS_ERRORMSG_PROXY_NOCONN, FZ_LOG_ERROR); break; case PROXYERROR_REQUESTFAILED: ShowStatus(IDS_ERRORMSG_PROXY_REQUESTFAILED, FZ_LOG_ERROR); if (iter->str) ShowStatus(A2T(iter->str), FZ_LOG_ERROR); break; case PROXYERROR_AUTHTYPEUNKNOWN: ShowStatus(IDS_ERRORMSG_PROXY_AUTHTYPEUNKNOWN, FZ_LOG_ERROR); break; case PROXYERROR_AUTHFAILED: ShowStatus(IDS_ERRORMSG_PROXY_AUTHFAILED, FZ_LOG_ERROR); break; case PROXYERROR_AUTHNOLOGON: ShowStatus(IDS_ERRORMSG_PROXY_AUTHNOLOGON, FZ_LOG_ERROR); break; case PROXYERROR_CANTRESOLVEHOST: ShowStatus(IDS_ERRORMSG_PROXY_CANTRESOLVEHOST, FZ_LOG_ERROR); break; default: LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Unknown proxy error") ); } } #ifndef MPEXT_NO_GSS else if (iter->pLayer == m_pGssLayer) { switch (iter->nParam1) { case GSS_INFO: LogMessageRaw(FZ_LOG_INFO, A2CT(iter->str)); break; case GSS_ERROR: LogMessageRaw(FZ_LOG_APIERROR, A2CT(iter->str)); break; case GSS_COMMAND: ShowStatus(A2CT(iter->str), FZ_LOG_COMMAND); break; case GSS_REPLY: ShowStatus(A2CT(iter->str), FZ_LOG_REPLY); break; } } #endif } nb_free(iter->str); } return 1; }
int CHttpControlSocket::ParseHeader(CHttpOpData* pData) { // Parse the HTTP header. // We do just the neccessary parsing and silently ignore most header fields // Redirects are supported though if the server sends the Location field. for (;;) { // Find line ending unsigned int i = 0; for (i = 0; (i + 1) < m_recvBufferPos; i++) { if (m_pRecvBuffer[i] == '\r') { if (m_pRecvBuffer[i + 1] != '\n') { LogMessage(::Error, _("Malformed reply, server not sending proper line endings")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } break; } } if ((i + 1) >= m_recvBufferPos) { if (m_recvBufferPos == m_recvBufferLen) { // We don't support header lines larger than 4096 LogMessage(::Error, _("Too long header line")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } return FZ_REPLY_WOULDBLOCK; } m_pRecvBuffer[i] = 0; const wxString& line = wxString(m_pRecvBuffer, wxConvLocal); if (line != _T("")) LogMessageRaw(Response, line); if (pData->m_responseCode == -1) { pData->m_responseString = line; if (m_recvBufferPos < 16 || memcmp(m_pRecvBuffer, "HTTP/1.", 7)) { // Invalid HTTP Status-Line LogMessage(::Error, _("Invalid HTTP Response")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } if (m_pRecvBuffer[9] < '1' || m_pRecvBuffer[9] > '5' || m_pRecvBuffer[10] < '0' || m_pRecvBuffer[10] > '9' || m_pRecvBuffer[11] < '0' || m_pRecvBuffer[11] > '9') { // Invalid response code LogMessage(::Error, _("Invalid response code")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } pData->m_responseCode = (m_pRecvBuffer[9] - '0') * 100 + (m_pRecvBuffer[10] - '0') * 10 + m_pRecvBuffer[11] - '0'; if (pData->m_responseCode >= 400) { // Failed request ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } if (pData->m_responseCode == 305) { // Unsupported redirect LogMessage(::Error, _("Unsupported redirect")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } } else { if (!i) { // End of header, data from now on // Redirect if neccessary if (pData->m_responseCode >= 300) { if (pData->m_redirectionCount++ == 5) { LogMessage(::Error, _("Too many redirects")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } ResetSocket(); ResetHttpData(pData); wxString host; enum ServerProtocol protocol; int pos; if ((pos = pData->m_newLocation.Find(_T("://"))) != -1) { protocol = CServer::GetProtocolFromPrefix(pData->m_newLocation.Left(pos)); host = pData->m_newLocation.Mid(pos + 3); } else { protocol = HTTP; host = pData->m_newLocation; } if ((pos = host.Find(_T("/"))) != -1) host = host.Left(pos); unsigned long port; if ((pos = host.Find(':', true)) != -1) { wxString strport = host.Mid(pos + 1); if (!strport.ToULong(&port) || port < 1 || port > 65535) { if (protocol == HTTPS) port = 443; else port = 80; } host = host.Left(pos); } else { if (protocol == HTTPS) port = 443; else port = 80; } if (host == _T("")) { // Unsupported redirect LogMessage(::Error, _("Redirection to invalid address")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } pData->m_newHostWithPort = wxString::Format(_T("%s:%d"), host.c_str(), (int)port); // International domain names host = ConvertDomainName(host); int res = InternalConnect(host, port, protocol == HTTPS); if (res == FZ_REPLY_WOULDBLOCK) res |= FZ_REPLY_REDIRECTED; return res; } pData->m_gotHeader = true; memmove(m_pRecvBuffer, m_pRecvBuffer + 2, m_recvBufferPos - 2); m_recvBufferPos -= 2; if (m_recvBufferPos) { int res; if (pData->m_transferEncoding == pData->chunked) res = OnChunkedData(pData); else { pData->m_receivedData += m_recvBufferPos; res = ProcessData(m_pRecvBuffer, m_recvBufferPos); m_recvBufferPos = 0; } return res; } return FZ_REPLY_WOULDBLOCK; } if (m_recvBufferPos > 12 && !memcmp(m_pRecvBuffer, "Location: ", 10)) { pData->m_newLocation = wxString(m_pRecvBuffer + 10, wxConvLocal); } else if (m_recvBufferPos > 21 && !memcmp(m_pRecvBuffer, "Transfer-Encoding: ", 19)) { if (!strcmp(m_pRecvBuffer + 19, "chunked")) pData->m_transferEncoding = CHttpOpData::chunked; else if (!strcmp(m_pRecvBuffer + 19, "identity")) pData->m_transferEncoding = CHttpOpData::identity; else pData->m_transferEncoding = CHttpOpData::unknown; } else if (i > 16 && !memcmp(m_pRecvBuffer, "Content-Length: ", 16)) { pData->m_totalSize = 0; char* p = m_pRecvBuffer + 16; while (*p) { if (*p < '0' || *p > '9') { LogMessage(::Error, _("Malformed header: %s"), _("Invalid Content-Length")); ResetOperation(FZ_REPLY_ERROR); return FZ_REPLY_ERROR; } pData->m_totalSize = pData->m_totalSize * 10 + *p++ - '0'; } } } memmove(m_pRecvBuffer, m_pRecvBuffer + i + 2, m_recvBufferPos - i - 2); m_recvBufferPos -= i + 2; if (!m_recvBufferPos) break; } return FZ_REPLY_WOULDBLOCK; }