static int processFlvStream(HttpSession *pSession, off_t start)
{
    //HttpReq * pReq = pSession->getReq();
    SendFileInfo *pData = pSession->getSendFileInfo();

    FileCacheDataEx *&pECache = pData->getECache();
    int ret = pData->getFileData()->readyCacheData(pECache, 0);
    if (!ret)
    {
        HttpResp *pResp = pSession->getResp();
        pSession->resetResp();

        pResp->parseAdd(pData->getFileData()->getHeaderBuf(),
                        pData->getFileData()->getHeaderLen());

        pResp->setContentLen(pData->getECache()->getFileSize() -
                             start + FLV_HEADER_LEN);
        //TODO: must be sent out first. would like to avoid using dyn body.
        // just append it to stream level buffer.
        pSession->appendDynBody(FLV_HEADER, FLV_HEADER_LEN);
        pSession->setSendFileBeginEnd(start , pData->getECache()->getFileSize());
        ret = pSession->flush();
    }
    return ret;
}
int HttpCgiTool::processHeaderLine( HttpExtConnector * pExtConn, const char * pLineBegin,
                                const char * pLineEnd, int &status )
{
    int index;
    const char * pKeyEnd;
    const char * pValue = pLineBegin;
    char * p;
    HttpResp* pResp = pExtConn->getHttpConn()->getResp();
    HttpReq * pReq = pExtConn->getHttpConn()->getReq();
    
    index = HttpHeader::getRespHeaderIndex( pValue );
    if ( index < HttpHeader::H_HEADER_END )
    {
        pValue += HttpHeader::getHeaderStringLen( index );

        while( isspace(*pValue) )
            ++pValue;
        pKeyEnd = pValue;
        if ( *pValue != ':' )
        {
            index = HttpHeader::H_HEADER_END;
        }
        else
        {
            do { ++pValue; }
            while( isspace(*pValue) );
        }
    }
    if ( index == HttpHeader::H_HEADER_END )
    {
        pKeyEnd = (char *)memchr( pValue, ':', pLineEnd - pValue );
        if ( pKeyEnd != NULL )
        {
            pValue = pKeyEnd + 1;
            while( isspace(*pValue) )
                ++pValue;
        }
        else
        {
            if ( !isspace( *pLineBegin ) )
                return 0;
        }
    }
    switch( index )
    {
    case HttpHeader::H_CONTENT_TYPE:
        p = (char *)memchr( pValue, ';', pLineEnd - pValue );
        if ( pReq->gzipAcceptable() )
        {
            register char ch = 0;
            register char *p1;
            if ( p )
            {
                p1 = (char*)p;
            }
            else
                p1 = (char*)pLineEnd;
            ch = *p1;
            *p1 = 0;
            if ( !HttpGlobals::getMime()->compressable( pValue ) )
                pReq->setGzip( 0 );
            *p1 = ch;
        }
        if ( pReq->isKeepAlive() )
            pReq->smartKeepAlive( pValue );
        {
            if ( !HttpMime::needCharset( pValue ) )
                break;
            const AutoStr2 * pCharset = pReq->getDefaultCharset();
            if ( !pCharset )
                break;
            if ( p )
            {
                while( isspace( *(++p) ) )
                    ;
                if ( strncmp( p, "charset=", 8 ) == 0 )
                    break;
            }
            AutoBuf& buf = pResp->getOutputBuf();
            if ( buf.available() < pLineEnd - pLineBegin + pCharset->len() + 4 )
            {
                buf.grow( pLineEnd - pLineBegin + pCharset->len() + 4 );
            }
            buf.appendNoCheck( pLineBegin, pLineEnd - pLineBegin );
            buf.appendNoCheck( pCharset->c_str(), pCharset->len() );
            buf.appendNoCheck( "\r\n", 2 );
        }
        return 0;
    case HttpHeader::H_CONTENT_ENCODING:
        pReq->setGzip( 0 );
        break;
    case HttpHeader::H_LOCATION:
        if ( pReq->getStatusCode() != SC_200 )
            break;
        if ( *pValue != '/' )
        {
            //set status code to 307
            pReq->setStatusCode( SC_302 );
        }
        else
        {
            pReq->setLocation( pValue, pLineEnd - pValue );
            return 0;
        }
        break;
    case HttpHeader::CGI_STATUS:
        index = HttpStatusCode::codeToIndex( pValue );
        if ( index != -1 )
        {
            pReq->updateNoRespBodyByStatus( index );
            if (( index >= SC_300 )&&( index < SC_400 ))
            {
                if ( *pReq->getLocation() )
                {
                    pResp->appendHeader( "Location: ", 10,
                        pReq->getLocation(), pReq->getLocationLen() );
                    pReq->clearLocation();    
                }
            }
            if (( status & HEC_RESP_AUTHORIZER )&&( index == SC_200))
                status |= HEC_RESP_AUTHORIZED;
        }
        return 0;
    case HttpHeader::H_TRANSFER_ENCODING:
        pResp->setContentLen( -1 );
        return 0;
    case HttpHeader::H_PROXY_CONNECTION:
    case HttpHeader::H_CONNECTION:
        if ( strncasecmp( pValue, "close", 5 ) == 0 )
            status |= HEC_RESP_CONN_CLOSE;
        return 0;
    case HttpHeader::H_CONTENT_LENGTH:
        if ( pResp->getContentLen() >= 0 )
        {
            long lContentLen = strtol( pValue, NULL, 10 );
            if (( lContentLen >= 0 )&&( lContentLen != LONG_MAX ))
                pResp->setContentLen( lContentLen );
        }
        //fall through
    case HttpHeader::H_KEEP_ALIVE:
    case HttpHeader::H_SERVER:
    case HttpHeader::H_DATE:
        return 0;
    default:
        //"script-control: no-abort" is not supported
        break;
    }
    if ( status & HEC_RESP_AUTHORIZED )
    {
        if (strncasecmp( pLineBegin, "Variable-", 9 ) == 0 )
        {
            if ( pKeyEnd > pLineBegin + 9 )
                pReq->addEnv( pLineBegin + 9, pKeyEnd - pLineBegin - 9,
                            pValue, pLineEnd - pValue );
        }
        return 0;
    }
    return pResp->appendHeaderLine( pLineBegin, pLineEnd );
}
int HttpCgiTool::processHeaderLine(HttpExtConnector *pExtConn,
                                   const char  *pLineBegin,
                                   const char *pLineEnd, int &status)
{
    HttpRespHeaders::HEADERINDEX index;
    int tmpIndex;
    const char *pKeyEnd = NULL;
    const char *pValue = pLineBegin;
    char *p;
    HttpResp *pResp = pExtConn->getHttpSession()->getResp();
    HttpReq *pReq = pExtConn->getHttpSession()->getReq();

    index = HttpRespHeaders::getRespHeaderIndex(pValue);
    if (index < HttpRespHeaders::H_HEADER_END)
    {
        pValue += HttpRespHeaders::getHeaderStringLen(index);

        while (isspace(*pValue))
            ++pValue;
        pKeyEnd = pValue;
        if (*pValue != ':')
            index = HttpRespHeaders::H_HEADER_END;
        else
        {
            do { ++pValue; }
            while (isspace(*pValue));
        }
    }
    if (index == HttpRespHeaders::H_HEADER_END)
    {
        pKeyEnd = (char *)memchr(pValue, ':', pLineEnd - pValue);
        if (pKeyEnd != NULL)
        {
            pValue = pKeyEnd + 1;
            while (isspace(*pValue))
                ++pValue;
        }
        else
        {
            if (!isspace(*pLineBegin))
                return 0;
        }
    }
    switch (index)
    {
    case HttpRespHeaders::H_CONTENT_TYPE:
        if (pReq->getStatusCode() == SC_304)
            return 0;
        p = (char *)memchr(pValue, ';', pLineEnd - pValue);
        if (pReq->gzipAcceptable() == GZIP_REQUIRED)
        {
            char ch = 0;
            char *p1;
            if (p)
                p1 = (char *)p;
            else
                p1 = (char *)pLineEnd;
            ch = *p1;
            *p1 = 0;
            if (!HttpMime::getMime()->compressible(pValue))
                pReq->andGzip(~GZIP_ENABLED);
            *p1 = ch;
        }
        if (pReq->isKeepAlive())
            pReq->smartKeepAlive(pValue);
        {
            if (!HttpMime::needCharset(pValue))
                break;
            const AutoStr2 *pCharset = pReq->getDefaultCharset();
            if (!pCharset)
                break;
            if (p)
            {
                while (isspace(*(++p)))
                    ;
                if (strncmp(p, "charset=", 8) == 0)
                    break;
            }
            HttpRespHeaders &buf = pResp->getRespHeaders();
            AutoStr2 str = "";
            str.append(pLineBegin, pLineEnd - pLineBegin);
            str.append(pCharset->c_str(), pCharset->len());
            str.append("\r\n", 2);
            buf.parseAdd(str.c_str(), str.len(), LSI_HEADEROP_ADD);
        }
        return 0;
    case HttpRespHeaders::H_CONTENT_ENCODING:
        if (pReq->getStatusCode() == SC_304)
            return 0;
        if (strncasecmp(pValue, "gzip", 4) == 0)
            pReq->orGzip(UPSTREAM_GZIP);
        else if (strncasecmp(pValue, "deflate", 7) == 0)
            pReq->orGzip(UPSTREAM_DEFLATE);
//             if ( !(pReq->gzipAcceptable() & REQ_GZIP_ACCEPT) )
//                 return 0;
//         }
//         else //if ( strncasecmp( pValue, "deflate", 7 ) == 0 )
//         {
//             pReq->andGzip( ~GZIP_ENABLED );
//         }
        break;
    case HttpRespHeaders::H_LOCATION:
        if ((status & HEC_RESP_PROXY) || (pReq->getStatusCode() != SC_200))
            break;
    case HttpRespHeaders::H_LITESPEED_LOCATION:
        if (*pValue != '/')
        {
            //set status code to 307
            pReq->setStatusCode(SC_302);
        }
        else
        {
            if ((pReq->getStatusCode() == SC_404) ||
                (index == HttpRespHeaders::H_LITESPEED_LOCATION))
                pReq->setStatusCode(SC_200);
            if (index == HttpRespHeaders::H_LITESPEED_LOCATION)
            {
                char ch = *pLineEnd;
                *((char *)pLineEnd) = 0;
                pReq->locationToUrl(pValue, pLineEnd - pValue);
                *((char *)pLineEnd) = ch;
            }
            else
                pReq->setLocation(pValue, pLineEnd - pValue);
            pExtConn->getHttpSession()->changeHandler();
            //status |= HEC_RESP_LOC_SET;
            return 0;
        }
        break;
    case HttpRespHeaders::H_CGI_STATUS:
        tmpIndex = HttpStatusCode::getInstance().codeToIndex(pValue);
        if (tmpIndex != -1)
        {
            pReq->updateNoRespBodyByStatus(tmpIndex);
            if ((tmpIndex >= SC_300) && (tmpIndex < SC_400))
            {
                if (pReq->getLocation() != NULL)
                {
                    pResp->appendHeader("location: ", 10,
                                        pReq->getLocation(), pReq->getLocationLen());
                    pReq->clearLocation();
                }
            }
            if ((status & HEC_RESP_AUTHORIZER) && (tmpIndex == SC_200))
                status |= HEC_RESP_AUTHORIZED;
        }
        return 0;
    case HttpRespHeaders::H_TRANSFER_ENCODING:
        pResp->setContentLen(LSI_RSP_BODY_SIZE_CHUNKED);
        return 0;
        
    case HttpRespHeaders::H_SET_COOKIE:
        //pReq->getRespCacheCtrl().setHasCookie();
        pReq->processSetCookieHeader(pValue, pLineEnd - pValue);
        break;

    case HttpRespHeaders::H_PROXY_CONNECTION:
    case HttpRespHeaders::H_CONNECTION:
        if (strncasecmp(pValue, "close", 5) == 0)
            status |= HEC_RESP_CONN_CLOSE;
        return 0;
    case HttpRespHeaders::H_CONTENT_LENGTH:
        if (pResp->getContentLen() == LSI_RSP_BODY_SIZE_UNKNOWN)
        {
            off_t lContentLen = strtoll(pValue, NULL, 10);
            if ((lContentLen >= 0) && (lContentLen != LLONG_MAX))
            {
                pResp->setContentLen(lContentLen);
                status |= HEC_RESP_CONT_LEN;
                pReq->orContextState(RESP_CONT_LEN_SET);
            }
        }
    //fall through
    case HttpRespHeaders::H_KEEP_ALIVE:
    case HttpRespHeaders::H_SERVER:
    case HttpRespHeaders::H_DATE:
        return 0;
    default:
        //"script-control: no-abort" is not supported
        break;
    }
    if (status & HEC_RESP_AUTHORIZED)
    {
        if (strncasecmp(pLineBegin, "Variable-", 9) == 0)
        {
            if (pKeyEnd > pLineBegin + 9)
                RequestVars::setEnv(pExtConn->getHttpSession(), pLineBegin + 9,
                                    pKeyEnd - pLineBegin - 9,
                                    pValue, pLineEnd - pValue);
        }
        return 0;
    }
    assert(pKeyEnd);
    return pResp->appendHeader(pLineBegin, pKeyEnd - pLineBegin, pValue,
                               pLineEnd - pValue);
}
Exemple #4
0
int JConn::readRespHeader( unsigned char *&p, unsigned char *pEnd )
{
    while( m_iNumHeader > 0 )
    {
        if ( pEnd - p < 4 )
            return 0;
        unsigned char id1 = *p;
        unsigned char id2;
        int headerNameLen;
        const char * pHeaderName;
        unsigned char * p1;
        if ( id1 == 0xA0 )
        {
            id2 = *(p+1);
            if (( id2 > 0 )&&( id2 <= AJP_RESP_HEADERS_NUM ))
            {
                pHeaderName = JkAjp13::getRespHeaderById( id2 );
                headerNameLen = JkAjp13::getRespHeaderLenById( id2 );
                p1 = p + 2;
            }
            else
            {
                //invalid header id
                return -1;
            }
        }
        else
        {
            headerNameLen = id1 << 8 | *(p+1);
            if ( pEnd - p < headerNameLen + 5 )
                return 0;
            pHeaderName = (const char *)p + 2;
            p1 = p + headerNameLen + 3;
        }
        int headerValLen = peekInt( p1 );
        if ( pEnd - p1 < headerValLen + 3 )
            return 0;
        char * pHeaderVal = (char *)p1 + 2;
        p = p1 + headerValLen + 3;
        --m_iNumHeader;
        HttpResp * pResp = getConnector()->getHttpConn()->getResp();
        int ret = pResp->appendHeader(
                    pHeaderName, headerNameLen, pHeaderVal, headerValLen );
        if ( ret )
            return ret;
        HttpReq * pReq = getConnector()->getHttpConn()->getReq();
        if ( pReq->gzipAcceptable() )
        {
            if ( *pHeaderName == 'C' || *pHeaderName == 'c' )
            {
                if ( strcasecmp( pHeaderName, "content-type" ) == 0 )
                {
                    char * p = (char *)memchr( pHeaderVal, ';', headerValLen );
                    if ( !p )
                        p = pHeaderVal + headerValLen;
                    register char ch;
                    ch = *p;
                    *p = 0;
                    if ( !HttpGlobals::getMime()->compressable( pHeaderVal ) )
                        pReq->andGzip( ~GZIP_ENABLED );
                    *p = ch;
                }
                else if ( strcasecmp( pHeaderName, "content-encoding" ) == 0 )
                {
                    pReq->andGzip( ~GZIP_ENABLED );
                }
            }
        }
    }
    getConnector()->getRespState() |= HttpReq::HEADER_OK;
    return getConnector()->respHeaderDone( m_pCurPos - p );
}
void AccessLog::log( HttpConnection* pConn )
{
    int  n;
    HttpReq*  pReq  = pConn->getReq();
    HttpResp* pResp = pConn->getResp();
    const char * pUser = pReq->getAuthUser();
    long contentWritten = pResp->getBodySent();
    const ClientInfo * pInfo = pConn->getClientInfo();
    const char * pAddr = pInfo->getHostName();
    pResp->needLogAccess( 0 );
    if ( m_iPipedLog )
    {
        if ( !m_pManager )
            return;
        m_pAppender = m_pManager->getAppender();
        if ( !m_pAppender )
            return;
    }
    
    if ( m_pCustomFormat )
        return customLog( pConn );
    
    if (( pAddr )&&( *pAddr ))
    {
        n = pInfo->getHostNameLen();
    }
    else
    {
        pAddr = pInfo->getAddrString();
        n = pInfo->getAddrStrLen();
    }
    m_buf.appendNoCheck( pAddr, n );
    if ( ! *pUser )
    {
        m_buf.appendNoCheck( " - - ", 5 );
    }
    else
    {
        n = safe_snprintf( m_buf.end(), 70, " - \"%s\" ", pUser );
        m_buf.used( n );
    }

    DateTime::getLogTime( pConn->getReqTime(), m_buf.end() );
    m_buf.used( 30 );
    n = pReq->getOrgReqLineLen();
    char * pOrgReqLine = (char *)pReq->getOrgReqLine();
    if ( pReq->getVersion() == HTTP_1_0 )
        *(pOrgReqLine + n - 1) = '0';
    if (( n > 4096 )||( m_buf.available() < 100 + n ))
    {
        flush();
        m_pAppender->append( pOrgReqLine, n );
    }
    else
        m_buf.appendNoCheck(pOrgReqLine, n );
    m_buf.append( '"' );
    m_buf.appendNoCheck(
        HttpStatusCode::getCodeString( pReq->getStatusCode() ), 5 );
    if ( contentWritten == 0 )
    {
        m_buf.append( '-' );
    }
    else
    {
        n = safe_snprintf( m_buf.end(), 20, "%ld", contentWritten );
        m_buf.used( n );
    }
    if ( getAccessLogHeader() & LOG_REFERER )
    {
        m_buf.append( ' ' );
        appendStr( pReq->getHeader( HttpHeader::H_REFERER ),
                pReq->getHeaderLen( HttpHeader::H_REFERER ));
    }
    if ( getAccessLogHeader() & LOG_USERAGENT )
    {
        m_buf.append( ' ' );
        appendStr( pReq->getHeader( HttpHeader::H_USERAGENT),
                pReq->getHeaderLen( HttpHeader::H_USERAGENT) );
    }
    if ( getAccessLogHeader() & LOG_VHOST )
    {
        m_buf.append( ' ' );
        appendStr( pReq->getHeader( HttpHeader::H_HOST ),
                pReq->getHeaderLen( HttpHeader::H_HOST ) );
    }
    m_buf.append( '\n' );
    if (( m_buf.available() < MAX_LOG_LINE_LEN )
        ||!asyncAccessLog() )
    {
        flush();
    }
}