int HttpCgiTool::parseRespHeader( HttpExtConnector * pExtConn, const char * pBuf, int size, int &status ) { const char * pEnd = pBuf + size; const char * pLineEnd; const char * pLineBegin; const char * pCur = pBuf; const char * pValue; while( pCur < pEnd ) { pLineBegin = pCur; pLineEnd = (const char *)memchr( pCur, '\n', pEnd - pCur ); if ( pLineEnd == NULL ) { break; } pCur = pLineEnd + 1; while(( pLineEnd > pLineBegin )&&(*(pLineEnd - 1) == '\r' )) --pLineEnd; if ( pLineEnd == pLineBegin ) { //empty line detected status |= HttpReq::HEADER_OK; break; } pValue = pLineBegin; while( (pLineEnd > pValue) &&(isspace( pLineEnd[-1] )) ) --pLineEnd; if ( pValue == pLineEnd ) continue; int index; if ( (*(pValue+4) == '/') && memcmp( pValue, "HTTP/1.", 7 ) == 0 ) { index = HttpStatusCode::codeToIndex( pValue + 9 ); if ( index != -1 ) { pExtConn->getHttpConn()->getReq()->updateNoRespBodyByStatus( index ); status |= HEC_RESP_NPH2; if (( status & HEC_RESP_AUTHORIZER )&&( index == SC_200)) status |= HEC_RESP_AUTHORIZED; } continue; } if ( processHeaderLine( pExtConn, pValue, pLineEnd, status ) == -1 ) return -1; } return pCur - pBuf; }
abyss_bool ConnReadHeader(TConn * const connectionP, char ** const headerP) { /*---------------------------------------------------------------------------- Read an HTTP header on connection *connectionP. An HTTP header is basically a line, except that if a line starts with white space, it's a continuation of the previous line. A line is delimited by either LF or CRLF. In the course of reading, we read at least one character past the line delimiter at the end of the header; we may read much more. We leave everything after the header (and its line delimiter) in the internal buffer, with the buffer pointer pointing to it. We use stuff already in the internal buffer (perhaps left by a previous call to this subroutine) before reading any more from from the socket. Return as *headerP the header value. This is in the connection's internal buffer. This contains no line delimiters. -----------------------------------------------------------------------------*/ uint32_t const deadline = time(NULL) + connectionP->server->srvP->timeout; abyss_bool retval; char * p; char * headerStart; abyss_bool error; abyss_bool gotHeader; p = connectionP->buffer + connectionP->bufferpos; headerStart = p; gotHeader = FALSE; error = FALSE; while (!gotHeader && !error) { int const timeLeft = deadline - time(NULL); if (timeLeft <= 0) error = TRUE; else { if (p >= connectionP->buffer + connectionP->buffersize) /* Need more data from the socket to chew on */ error = !ConnRead(connectionP, timeLeft); if (!error) { assert(connectionP->buffer + connectionP->buffersize > p); processHeaderLine(p, headerStart, connectionP, deadline, &gotHeader, &p, &error); } } } if (gotHeader) { /* We've consumed this part of the buffer (but be careful -- you can't reuse that part of the buffer because the string we're returning is in it! */ connectionP->bufferpos += p - headerStart; *headerP = headerStart; retval = TRUE; } else retval = FALSE; return retval; }