Exemplo n.º 1
0
int RewriteEngine::getSubstValue( const RewriteSubstItem * pItem, HttpConnection *pConn,
                        char * &pValue, int bufLen )
{
    HttpReq * pReq = pConn->getReq();
    int type = pItem->getType();
    int i;
    if ( type < REF_STRING )
    {
        pValue = (char *)pReq->getHeader( type );
        if ( *pValue )
            return pReq->getHeaderLen( type );
        else
            return 0;
    }

/*
    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;
    }
*/
    switch( type )
    {
    case REF_STRING:
        pValue = (char *)pItem->getStr()->c_str();
        return pItem->getStr()->len();
    case REF_MAP:
        {
            MapRefItem * pRef = pItem->getMapRef();
            int len = 1024;
            char achBuf[1024];
            if ( buildString( pRef->getKeyFormat(), pConn, achBuf, len ) == NULL )
                return 0;
            if ( (len = pRef->getMap()->lookup( achBuf, len, pValue, bufLen )) == -1 )
            {
                if ( pRef->getDefaultFormat() )
                {
                    if ( buildString( pRef->getDefaultFormat(), pConn,
                                    pValue, bufLen ) == NULL )
                        return 0;
                    len = bufLen;
                }        
                else
                    len = 0;
            }
            return len;
        }
        break;             
    case REF_RULE_SUBSTR:
        return getSubstr( m_pSourceURL, m_ruleVec, m_ruleMatches, pItem->getIndex(),
                    pValue, m_flag & RULE_FLAG_BR_ESCAPE );
    case REF_COND_SUBSTR:
        return getSubstr( m_pCondBuf, m_condVec, m_condMatches, pItem->getIndex(),
                    pValue, m_flag & RULE_FLAG_BR_ESCAPE );
    case REF_ENV:
        pValue = (char *)RequestVars::getEnv( pConn, pItem->getStr()->c_str(), 
                    pItem->getStr()->len(), i );
        if ( !pValue )
        {
            i = 0;
        }
        return i;
    case REF_HTTP_HEADER:
        pValue = (char *)pReq->getHeader( pItem->getStr()->c_str(),
                        pItem->getStr()->len(), i );
        if ( !pValue )
            i = 0;
        return i;
    case REF_REQUST_FN:
    case REF_SCRIPTFILENAME:
        if ( m_iScriptLen == -1 )
        {
            pReq->checkPathInfo( m_pSourceURL, m_sourceURLLen, m_iFilePathLen,
                            m_iScriptLen, m_iPathInfoLen, m_pContext );
        }
        pValue = HttpGlobals::g_achBuf;
        //if ( m_pStrip )
        //    return m_iFilePathLen;
        //else

        //   return m_iFilePathLen + m_iPathInfoLen;
        return m_iFilePathLen;
    case REF_PATH_INFO:
        if ( m_iScriptLen == -1 )
        {
            pReq->checkPathInfo( m_pSourceURL, m_sourceURLLen, m_iFilePathLen,
                            m_iScriptLen, m_iPathInfoLen, m_pContext );
        }
        pValue = &HttpGlobals::g_achBuf[ m_iFilePathLen ];
        return m_iPathInfoLen;
    case REF_SCRIPT_NAME:
        if ( m_iScriptLen == -1 )
        {
            pReq->checkPathInfo( m_pSourceURL, m_sourceURLLen, m_iFilePathLen,
                            m_iScriptLen, m_iPathInfoLen, m_pContext );
        }
        pValue = (char *)pReq->getOrgReqURL();
        return m_iScriptLen;
    case REF_REQ_URI:   //in rewrite rule, this does not include Query String part
        if ( pReq->getRedirects() == 0 )
        {
            pValue = (char *)pReq->getOrgReqURL();
            return pReq->getOrgReqURILen();
        }
        if ( m_pStrip )
        {
            memmove( pValue, m_pStrip->c_str(), m_pStrip->len() );
            memmove( pValue + m_pStrip->len(), m_pSourceURL, m_sourceURLLen );
            return m_pStrip->len() + m_sourceURLLen;
        }
        //fall through
    case REF_CUR_URI:
        pValue = (char *)m_pSourceURL;
        return m_sourceURLLen;
    case REF_QUERY_STRING:
        pValue = (char *)m_pQS;
        return m_qsLen;
    default:
        return RequestVars::getReqVar( pConn, type, pValue, bufLen );
    }
    return 0;
}
Exemplo n.º 2
0
int RewriteEngine::processRuleSet( const RewriteRuleList * pRuleList, HttpConnection * pConn,
            const HttpContext * pContext, const HttpContext * pRootContext )
{
    const RewriteRule * pRule = NULL;
    int loopCount = 0;
    int flag = 0;
    int ret;
    m_pContext = pContext;
    if ( pRuleList )
        pRule = pRuleList->begin();
    else
        pRule = getNextRule( NULL, pContext, pRootContext );
    if ( !pRule )
        return 0;
    HttpReq * pReq = pConn->getReq();
    const AutoStr2 * pBase = NULL;
    AutoStr2    sStrip;
    m_rewritten = 0;
    //initialize rewrite engine
    //strip prefix aka. RewriteBase
    m_logLevel = pReq->getRewriteLogLevel();
    m_pSourceURL = pReq->getURI();
    m_sourceURLLen = pReq->getURILen();
    m_pStrip = m_pBase = NULL;
    m_iScriptLen = -1;
    m_iPathInfoLen = 0;
    if ( m_pContext )
    {
        pBase = m_pContext->getContextURI();
        if (( pBase )&&
            ( strncmp( m_pSourceURL, pBase->c_str(), pBase->len() ) == 0 ))
        {
            m_pStrip = m_pBase = pBase;
        }
        else
        {
            m_pBase = pBase = m_pContext->getRewriteBase();
            if (( pBase )&&
                ( strncmp( m_pSourceURL, pBase->c_str(), pBase->len() ) == 0 ))
            {
                m_pStrip = m_pBase = pBase;
            }
            
        }
        
        if ( m_pContext->getRewriteBase() )
            m_pBase = m_pContext->getRewriteBase();
        if ( m_pStrip )
        {
            if ( m_logLevel > 4 )
                LOG_INFO(( pConn->getLogger(),
                        "[%s] [REWRITE] strip base: '%s' from URI: '%s'",
                        pConn->getLogId(), m_pStrip->c_str(), m_pSourceURL ));
            m_pSourceURL += m_pStrip->len();
            m_sourceURLLen -= m_pStrip->len();
        }
        else
        {
            if ( pConn->getReq()->isMatched() )
            {
                const char * pURL;
                int len;
                pConn->getReq()->stripRewriteBase( m_pContext,
                    pURL, len );
                if (( len < m_sourceURLLen )&&( strncmp( 
                        m_pSourceURL + m_sourceURLLen - len, pURL, len ) == 0 ))
                {
                    sStrip.setStr( m_pSourceURL, m_sourceURLLen - len );
                    m_pStrip = &sStrip;
                    if ( !m_pBase )
                        m_pBase = m_pStrip;
                }
                m_pSourceURL = pURL;
                m_sourceURLLen = len;
            }
        }
    }

    m_pQS = pReq->getQueryString();
    m_qsLen = pReq->getQueryStringLen();

    m_pOrgSourceURL = m_pSourceURL;
    m_orgSourceURLLen = m_sourceURLLen;

    m_condMatches = 0;
    m_pDestURLLen = 0;
    m_pDestURL = m_rewriteBuf[0];
    m_pCondBuf = m_rewriteBuf[1];
    m_pFreeBuf = m_rewriteBuf[2];
    m_action   = RULE_ACTION_NONE;
    m_flag     = 0;
    m_statusCode = 0;
    while( pRule )
    {
        flag = pRule->getFlag();
//        if (( flag & RULE_FLAG_NOSUBREQ )&&( pReq->isSubReq() > 0 ))
//            ret = -1;
//        else
            ret = processRule( pRule, pConn );
        if ( ret )
        {
            pRule = getNextRule( pRule, pContext, pRootContext );
            while( pRule && ( flag & RULE_FLAG_CHAIN ))
            {
                if ( m_logLevel > 5 )
                    LOG_INFO(( pConn->getLogger(),
                        "[%s] [REWRITE] skip chained rule: '%s'",
                        pConn->getLogId(), pRule->getPattern() ));
                flag = pRule->getFlag();
                pRule = getNextRule( pRule, pContext, pRootContext );
                            //(const RewriteRule *) pRule->next();
            }
            continue;
        }
        if (( flag & RULE_FLAG_LAST )&&!pRule->getSkip())
        {
            if ( m_logLevel > 5 )
                LOG_INFO(( pConn->getLogger(),
                    "[%s] [REWRITE] Last Rule, stop!",
                    pConn->getLogId() ));
            if ( flag & RULE_FLAG_END )
            {
                if ( m_logLevel > 5 )
                    LOG_INFO(( pConn->getLogger(),
                        "[%s] [REWRITE] End rewrite!",
                        pConn->getLogId() ));
                pConn->getReq()->orContextState( SKIP_REWRITE );
            }
            break;
        }
NEXT_RULE:
        if ( flag & RULE_FLAG_NEXT )
        {
            pContext = m_pContext;
            if ( pRuleList )
                pRule = pRuleList->begin();
            else
                pRule = getNextRule( NULL, pContext, pRootContext );
            if ( ++loopCount > 10 )
            {
                LOG_ERR(( pConn->getLogger(),
                        "[%s] [REWRITE] Rules loop 10 times, possible infinite loop!",
                        pConn->getLogId() ));
                break;
            }
            if ( m_logLevel > 5 )
                LOG_INFO(( pConn->getLogger(),
                    "[%s] [REWRITE] Next round, restart from the first rule",
                    pConn->getLogId() ));
            continue;
        }
        if ( !pRule )
            break;
        int n = pRule->getSkip()+1;
        if (( n > 1 )&&( m_logLevel > 5 ))
            LOG_INFO(( pConn->getLogger(),
                "[%s] [REWRITE] skip next %d rules",
                pConn->getLogId(), n - 1 ));
        while( pRule && n > 0 )
        {
            pRule = getNextRule( pRule, pContext, pRootContext );
                    //(const RewriteRule *) pRule->next();
            --n;
        }
    }
    if ( m_rewritten )
    {
        if (( m_action == RULE_ACTION_FORBID )||
            ( m_action == RULE_ACTION_GONE   ))
            return m_statusCode;
        if ( m_rewritten & 2 )
        {
            //set the final URL and query string
            if ( ! isAbsoluteURI( m_pSourceURL, m_sourceURLLen ) )
            {
                if ( *m_pSourceURL != '/' )
                {
                    // add missing prefix (RewriteBase)
                    char * pBuf = m_pFreeBuf;
                    int baseLen;
                    if ( !m_pBase )
                    {
                        baseLen   = 1;
                        *pBuf = '/';
                    }
                    else
                    {
                        baseLen = m_pBase->len();
                        memmove( pBuf, m_pBase->c_str(), baseLen );
                    }
                    if ( m_sourceURLLen > REWRITE_BUF_SIZE - 1 - baseLen )
                        m_sourceURLLen = REWRITE_BUF_SIZE - 1 - baseLen;
                    memmove( pBuf + baseLen, m_pSourceURL, m_sourceURLLen );
                    m_pFreeBuf = (char *)m_pSourceURL;
                    m_pSourceURL = pBuf;
                    m_sourceURLLen += baseLen;
                    pBuf[m_sourceURLLen] = 0;
                    if (( m_logLevel > 4 )&&( m_pBase ))
                        LOG_INFO(( pConn->getLogger(),
                                "[%s] [REWRITE] prepend rewrite base: '%s', final URI: '%s'",
                                pConn->getLogId(), m_pBase->c_str(), m_pSourceURL ));
                }
            }
            else if ( m_action == RULE_ACTION_NONE )
            {
                m_action = RULE_ACTION_REDIRECT;
                m_statusCode = SC_302;
            }
            if ( m_action == RULE_ACTION_NONE )
            {
                if ( !pReq->getRedirects() || pBase)
                {
                    ret = pReq->saveCurURL();
                    if ( ret )
                        return ret;
                }
                if ( m_pQS == m_qsBuf )
                    pReq->setRewriteQueryString( m_pQS, m_qsLen );
                m_statusCode = -3;  //rewritten to another url
            }
            else if ( m_action == RULE_ACTION_REDIRECT )
            {
                if ( pReq->detectLoopRedirect( (char *)m_pSourceURL, m_sourceURLLen,
                                        m_pQS, m_qsLen, pConn->isSSL() ) == 0 )
                {
                    pReq->setRewriteLocation( (char *)m_pSourceURL, m_sourceURLLen,
                                        m_pQS, m_qsLen, m_flag & RULE_FLAG_NOESCAPE );
                    pReq->orContextState( REWRITE_REDIR );
                }
                else
                {
                    LOG_INFO(( pConn->getLogger(),
                            "[%s] [REWRITE] detect external loop redirection with target URL: %s, skip.",
                                pConn->getLogId(), m_pSourceURL ));
                    m_rewritten = m_statusCode = 0;
                    m_pSourceURL = m_pOrgSourceURL;
                    m_sourceURLLen = m_orgSourceURLLen ;

                    goto NEXT_RULE;
                }
            }
            else if ( m_action == RULE_ACTION_PROXY )
            {
                if ( strncasecmp( m_pSourceURL, "http://", 7 ) != 0 )
                {
                    LOG_ERR(( "[REWRITE] Absolute URL with leading 'http://' is "
                              "required for proxy, URL: %s", m_pSourceURL ));
                    return SC_500;
                }
                char * pHost = (char *)m_pSourceURL + 7;
                char * pHostEnd = strchr( pHost, '/' );
                if (( !pHostEnd )||(pHostEnd == pHost))
                {
                    LOG_ERR(( "[REWRITE] Can not determine proxy host name" ));
                    return SC_500;
                }
                *pHostEnd = 0;
                const HttpHandler * pHandler = HandlerFactory::getInstance(
                        HandlerType::HT_PROXY, pHost );
                if ( !pHandler )
                {
                    LOG_ERR(( "[REWRITE] Proxy target is not defined on "
                              "external application list, please add a 'web server'"
                              " with name '%s'", pHost ));
                    return SC_500;
                }
                *pHostEnd = '/';
                pReq->setHandler( pHandler );

                //FIXME: change request header
                ret = pReq->internalRedirectURI( pHostEnd, 
                        m_pSourceURL + m_sourceURLLen - pHostEnd, 0,
                        m_flag & RULE_FLAG_NOESCAPE );
                if ( ret )
                    return SC_500;

                if ( m_pQS == m_qsBuf )
                    pReq->setRewriteQueryString( m_pQS, m_qsLen );
            }
        }
        else if ( m_action == RULE_ACTION_REDIRECT )
        {
            return 0;
        }
        return m_statusCode;
    }
    return 0;
}
Exemplo n.º 3
0
int ProxyConn::sendReqHeader()
{
    m_iovec.clear();
    HttpSession *pSession = getConnector()->getHttpSession();
    HttpReq *pReq = pSession->getReq();
    //remove the trailing "\r\n" before adding our headers
    const char *pBegin = pReq->getOrgReqLine();
    m_iTotalPending = pReq->getHttpHeaderLen();
    int newReqLineLen = 0;
    int headerLen = 17;
    char *pExtraHeader = &m_extraHeader[23];
    const char *pForward = pReq->getHeader(HttpHeader::H_X_FORWARDED_FOR);
    int len;
    if (*pForward != '\0')
    {
        len = pReq->getHeaderLen(HttpHeader::H_X_FORWARDED_FOR);
        if (len > 160)
            len = 160;
        memmove(&pExtraHeader[headerLen], pForward, len);
        headerLen += len;
        pExtraHeader[headerLen++] = ',';

    }
    //add "X-Forwarded-For" header
    memmove(&pExtraHeader[headerLen], pSession->getPeerAddrString(),
            pSession->getPeerAddrStrLen());
    headerLen += pSession->getPeerAddrStrLen();
    pExtraHeader[headerLen++] = '\r';
    pExtraHeader[headerLen++] = '\n';

#if 1       //always set "Accept-Encoding" header to "gzip"
    char *pAE = (char *)pReq->getHeader(HttpHeader::H_ACC_ENCODING);
    if (*pAE)
    {
        int len = pReq->getHeaderLen(HttpHeader::H_ACC_ENCODING);
        if (len >= 4)
        {
            memmove(pAE, "gzip", 4);
            memset(pAE + 4, ' ', len - 4);
        }
    }
    else
    {
        pExtraHeader = m_extraHeader;
        headerLen += 23;
    }
#endif

    if (*(pBegin + --m_iTotalPending - 1) == '\r')
        --m_iTotalPending;
    if (*pForward)
    {
        if ((pBegin + m_iTotalPending) -
            (pForward + pReq->getHeaderLen(HttpHeader::H_X_FORWARDED_FOR)) == 2)
        {
            const char *p = pForward -= 16;
            while (*(p - 1) != '\n')
                --p;
            m_iTotalPending = p - pBegin;
        }
    }

    //reconstruct request line if URL has been rewritten
    if (pReq->getRedirects() > 0)
    {
        const char *pReqLine = pReq->encodeReqLine(newReqLineLen);
        if (newReqLineLen > 0)
        {
            m_iovec.append(pReqLine, newReqLineLen);
            pBegin += pReq->getOrgReqLineLen() - 9;
            m_iTotalPending -= pReq->getOrgReqLineLen() - 9;
        }

    }

    int newHostLen = pReq->getNewHostLen();
    char *pHost = (char *)pReq->getHeader(HttpHeader::H_HOST);
    int hostLen = pReq->getHeaderLen(HttpHeader::H_HOST);
    if (newHostLen > 0)
    {
        if (*pHost)
        {
            m_iovec.append(pBegin, pHost - pBegin);
            m_iovec.append(pReq->getNewHost(), newHostLen);
            m_iovec.append(pHost + hostLen,
                           pBegin + m_iTotalPending - pHost - hostLen);
            m_iTotalPending += (newHostLen - hostLen);
        }
        else
        {
            m_iovec.append(pBegin, m_iTotalPending);
            m_iovec.append("Host: ", 6);
            m_iovec.append(pReq->getNewHost(), newHostLen);
            m_iovec.append("\r\n", 2);
            m_iTotalPending += newHostLen + 8;
        }
    }
    else
        m_iovec.append(pBegin, m_iTotalPending);
    m_iTotalPending += newReqLineLen;

    if (hostLen)
    {
        m_iovec.append(s_achForwardHost, sizeof(s_achForwardHost) - 1);
        m_iovec.append(pHost, hostLen);
        m_iovec.append("\r\n", 2);
        m_iTotalPending += hostLen + sizeof(s_achForwardHost) + 1 ;
    }

    if (pSession->isSSL())
    {
        m_iovec.append(s_achForwardHttps, sizeof(s_achForwardHttps) - 1);
        m_iTotalPending += sizeof(s_achForwardHttps) - 1;
    }

    //if ( headerLen > 0 )
    {
        pExtraHeader[headerLen++] = '\r';
        pExtraHeader[headerLen++] = '\n';
        m_iovec.append(pExtraHeader, headerLen);
        m_iTotalPending += headerLen;
    }
    m_iReqHeaderSize = m_iTotalPending;
    m_iReqBodySize = pReq->getContentFinished();
    setInProcess(1);
    return 1;
}