Example #1
0
int SSIEngine::startExecute( HttpSession *pSession, 
                             SSIScript * pScript )
{
    if ( !pScript )
        return SC_500;
    SSIRuntime * pRuntime = pSession->getReq()->getSSIRuntime();
    if ( !pRuntime )
    {
        char ct[]= "text/html";
        HttpReq * pReq = pSession->getReq();
        pRuntime = new SSIRuntime();
        if (!pRuntime )
            return SC_500;
        pRuntime->init();
        pRuntime->initConfig( pReq->getSSIConfig() );
        pReq->setSSIRuntime( pRuntime );
        pSession->getResp()->reset();
        //pSession->getResp()->prepareHeaders( pReq );
        //pSession->setupChunkOS( 0 );
        HttpCgiTool::processContentType( pReq, pSession->getResp(), 
                      ct , 9 );
//        pSession->setupRespCache();
        if ( pReq->isXbitHackFull() )
        {
            pSession->getResp()->appendLastMod( pReq->getLastMod() );
        }
        int status = pReq->getStatusCode();
        if (( status >= SC_300 )&&( status < SC_400 ))
        {
            if ( pReq->getLocation() != NULL )
            {
                pSession->addLocationHeader();
            }
        }
        pSession->setupGzipFilter();
        pReq->andGzip( ~GZIP_ENABLED );  //disable GZIP
    }
    if ( pRuntime->push( pScript ) == -1 )
        return SC_500;
    pSession->getReq()->backupPathInfo();
    pScript->resetRuntime();
    return resumeExecute( pSession );
}
Example #2
0
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 RequestVars::getReqVar( HttpSession *pSession, int type, char * &pValue, int bufLen)
{
    HttpReq * pReq = pSession->getReq();
    int i;
    char *p;
    if ( type < REF_STRING )
    {
        pValue = (char *)pReq->getHeader( type );
        if ( *pValue )
            return pReq->getHeaderLen( type );
        else
            return 0;
    }
    switch( type )
    {
    case REF_REMOTE_HOST:
        //FIXME: use remote addr for now
    case REF_REMOTE_ADDR:
        pValue = (char *)pSession->getPeerAddrString();
        return pSession->getPeerAddrStrLen();
    case REF_REMOTE_PORT:
        return snprintf( pValue, bufLen, "%hu", pSession->getRemotePort() );
    case REF_REMOTE_USER:
        pValue = (char *)pReq->getAuthUser();
        return strlen( pValue );
    case REF_REMOTE_IDENT:
        //do not support;
        return 0;
    case REF_REQ_METHOD:
        i = pReq->getMethod();
        strcpy(pValue, HttpMethod::get( i ) );
        return HttpMethod::getLen( i );
    case REF_QUERY_STRING:
        pValue = (char *)pReq->getQueryString();
        return pReq->getQueryStringLen();
    case REF_AUTH_TYPE:
        //FIXME: hard code for now
        strncpy( pValue, "Basic", 6 );
        return 5;
    case REF_REQUST_FN:
    case REF_SCRIPTFILENAME:
    case REF_SCRIPT_BASENAME:
    case REF_REQ_BASENAME: 
    {
        const AutoStr2 * psTemp = pReq->getRealPath();
        if ( psTemp )
        {
            if (( type == REF_SCRIPT_BASENAME )||
                ( type == REF_REQ_BASENAME ))
            {
                const char * pEnd = psTemp->c_str() + psTemp->len();
                pValue = (char *)pEnd;
                while( pValue[-1] != '/' )
                    --pValue;
                return pEnd - pValue;
            }
            pValue = (char *)psTemp->c_str();
            return psTemp->len();
        }
        else
            return 0;
    }
    case REF_SCRIPT_UID:
    case REF_SCRIPT_GID:
    case REF_SCRIPT_USERNAME:
    case REF_SCRIPT_GRPNAME:
    case REF_SCRIPT_MODE:
    {
        const AutoStr2 * psTemp = pReq->getRealPath();
        if ( psTemp )
        {
            struct stat& st = pReq->getFileStat();
            if ( type == REF_SCRIPT_UID )
            {
                return snprintf( pValue, bufLen, "%d", st.st_uid );
            }
            else if ( type == REF_SCRIPT_GID )
            {
                return snprintf( pValue, bufLen, "%d", st.st_gid );
            }
            else if ( type == REF_SCRIPT_MODE )
            {
                return snprintf( pValue, bufLen, "%o", st.st_mode );
            }
            else if ( type == REF_SCRIPT_USERNAME )
            {
                struct passwd * pw = getpwuid( st.st_uid );
                if ( pw )
                    return snprintf( pValue, bufLen, "%s", pw->pw_name );
            }
            else
            {
                struct group * gr = getgrgid( st.st_gid );
                if ( gr )
                    return snprintf( pValue, bufLen, "%s", gr->gr_name );
            }
        }
        return 0;
    }
    case REF_PATH_INFO:
        pValue = (char *)pReq->getPathInfo();
        return pReq->getPathInfoLen();

    case REF_SCRIPT_NAME:
        pValue = (char *)pReq->getURI();
        return pReq->getScriptNameLen();
    case REF_SCRIPT_URI:
        p = pValue;
        if ( pSession->isSSL() )
        {
            strcpy( p, "https://" );
            p += 8;
        }
        else
        {
            strcpy( p, "http://" );
            p += 7;
        }
        i = pReq->getHeaderLen( HttpHeader::H_HOST );
        memmove( p, pReq->getHeader( HttpHeader::H_HOST ), 
                    i );
        p += i;

        i = pReq->getOrgURILen();
        memmove( p, pReq->getOrgURI(), i );
        p += i;
        return p - pValue;

    case REF_ORG_REQ_URI:
        pValue = (char *)pReq->getOrgReqURL();
        return pReq->getOrgReqURILen();
    case REF_DOCUMENT_URI:
        return pReq->getDecodedOrgReqURI( pValue );
    case REF_REQ_URI:
        pValue = (char *)pReq->getOrgReqURL();
        return pReq->getOrgReqURLLen();

    case REF_DOC_ROOT:
        pValue = (char *)pReq->getDocRoot()->c_str();
        return pReq->getDocRoot()->len()-1;

    case REF_SERVER_ADMIN:
        if ( pReq->getVHost() )
        {
            const AutoStr2 * pEmail = pReq->getVHost()->getAdminEmails();
            pValue = (char *)pEmail->c_str();
            return pEmail->len();
        }
        return 0;
    case REF_VH_CNAME:
        if ( pReq->getVHost() )
        {
            pValue = (char *)pReq->getVHost()->getVhName( i );
            return i;
        }
        return 0;

    case REF_SERVER_NAME:
        pValue = (char *)pReq->getHostStr();
        return pReq->getHostStrLen();
    case REF_SERVER_ADDR:
        pValue = (char *)pReq->getLocalAddrStr()->c_str();
        return pReq->getLocalAddrStr()->len();
    case REF_SERVER_PORT:
        pValue = (char *)pReq->getPortStr().c_str();
        return pReq->getPortStr().len();
    case REF_SERVER_PROTO:
        i = pReq->getVersion();
        pValue = (char *)HttpVer::getVersionString( i );
        return HttpVer::getVersionStringLen( i );
    case REF_SERVER_SOFT:
        pValue = (char *)HttpServerVersion::getVersion();
        return HttpServerVersion::getVersionLen();
    case REF_REQ_LINE:
        pValue = (char *)pReq->getOrgReqLine();
        return pReq->getOrgReqLineLen();
    case REF_IS_SUBREQ:
        strcpy( pValue, "false" );
        return 5;

    case REF_RESP_BYTES:
        i = StringTool::str_off_t( pValue, bufLen, pSession->getResp()->getBodySent() );
        return i;
    //case REF_COOKIE_VAL
    //case REF_STRFTIME        155
    //case REF_CONN_STATE:
    case REF_REQ_TIME_MS:
    {
        struct timeval tv;
        gettimeofday( &tv, NULL );
        DateTime::s_curTime = tv.tv_sec;
        DateTime::s_curTimeUs = tv.tv_usec;

        long lReqTime =  (DateTime::s_curTime - pSession->getReqTime())*1000000 +
                    (DateTime::s_curTimeUs - pSession->getReqTimeUs());
        i = snprintf( pValue, bufLen, "%ld", lReqTime );
        return i;
    }
    case REF_REQ_TIME_SEC:
        i = snprintf( pValue, bufLen, "%ld",
                    (DateTime::s_curTime - pSession->getReqTime()) );
        return i;
    case REF_DUMMY:
        return 0;
    case REF_PID:
        i = snprintf( pValue, bufLen, "%d", getpid() );
        return i;
    case REF_STATUS_CODE:
        memmove( pValue, HttpStatusCode::getCodeString( pReq->getStatusCode() )+1, 3 );
        pValue[3] = 0;
        return 3;
    
    case REF_CUR_URI:
        pValue = (char *)pReq->getURI();
        i = pReq->getURILen();
        return i;
    case REF_BYTES_IN:
        i = StringTool::str_off_t( pValue, bufLen, pSession->getBytesRecv() );
        return i;
    case REF_BYTES_OUT:
        i = StringTool::str_off_t( pValue, bufLen, pSession->getBytesSent() );
        return i;

    case REF_HTTPS:
        i = snprintf( pValue, bufLen, "%s", pSession->isSSL()?"on":"off" );
        return i;

    case REF_DATE_GMT:
    case REF_DATE_LOCAL:
    case REF_LAST_MODIFIED:
    {
        time_t mtime = DateTime::s_curTime;
        struct tm * tm;
        if ( type == REF_LAST_MODIFIED )
        {
            if ( pReq->getSSIRuntime() && pReq->getSSIRuntime()->getCurrentScript() )
            {
                mtime = pReq->getSSIRuntime()->getCurrentScript()->getLastMod();
            }
            else
                mtime = pReq->getFileStat().st_mtime;
        }
        if ( type == REF_DATE_GMT )
            tm = gmtime( &mtime );
        else
            tm = localtime( &mtime );
        char fmt[101]; 
        memccpy( fmt, pValue, 0, 100 );
        fmt[100] = 0;
        i = strftime( pValue, bufLen, fmt, tm );
        return i;
    } 
    case REF_DOCUMENT_NAME:
    {
        const AutoStr2 * psTemp = pReq->getRealPath();
        if ( psTemp )
        {
            pValue = (char *)psTemp->c_str() + psTemp->len();
            while( *(pValue -1) != '/' )
                --pValue;
            return psTemp->c_str() + psTemp->len() - pValue;
        }
        else
            return 0;
    }

    case REF_QS_UNESCAPED:
    {
        int qsLen = pReq->getQueryStringLen();
        const char * pQS = pReq->getQueryString();
        if ( qsLen > 0 )
        {
            qsLen = HttpUtil::unescape_n( pQS, qsLen, pValue, bufLen );
        }
        return qsLen;
    }
    case REF_RESP_CONTENT_TYPE:
        i = 0;
        pValue = (char*)pSession->getResp()->getContentTypeHeader( i );
        return i;
    case REF_RESP_CONTENT_LENGTH:
    {   off_t l = pSession->getResp()->getContentLen();
        if ( l <= 0 )
            l = 0;
        i = StringTool::str_off_t( pValue, bufLen, l );
        return i;
    }
    case REF_RESP_BODY:
        return 0;
    default:
        if ( type >= REF_TIME )
        {
            time_t t = time(NULL);
            struct tm *tm = localtime(&t);
            switch( type )
            {
            case REF_TIME:
                i = snprintf( pValue, bufLen,
                            "%04d%02d%02d%02d%02d%02d", tm->tm_year + 1900,
                            tm->tm_mon+1, tm->tm_mday,
                            tm->tm_hour, tm->tm_min, tm->tm_sec);
                break;
            case REF_TIME_YEAR:
                i = snprintf( pValue, bufLen, "%04d", tm->tm_year + 1900);
                break;
            case REF_TIME_MON:
                i = snprintf( pValue, bufLen, "%02d", tm->tm_mon+1 );
                break;
            case REF_TIME_DAY:
                i = snprintf( pValue, bufLen, "%02d", tm->tm_mday);
                break;
            case REF_TIME_HOUR:
                i = snprintf( pValue, bufLen, "%02d", tm->tm_hour);
                break;
            case REF_TIME_MIN:
                i = snprintf( pValue, bufLen, "%02d", tm->tm_min);
                break;
            case REF_TIME_SEC:
                i = snprintf( pValue, bufLen, "%02d", tm->tm_sec);
                break;
            case REF_TIME_WDAY:
                i = snprintf( pValue, bufLen, "%d", tm->tm_wday);
                break;
            default:
                return 0;
            }
            return i;
        }
        return 0;
    }
    return 0;
    
}
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);
}
Example #5
0
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();
    }
}