const AutoStr2 * StringList::add( const char * pStr, int len )
{
    AutoStr2* pTemp = new AutoStr2();
    if ( !pTemp )
        return NULL;
    pTemp->setStr( pStr, len );
    push_back( pTemp );
    return pTemp;
}
//When checking we use lock for may need to update the conf file later
//If user RCS checkout a revision, a unlock should be used for next time checkin.
//Example: co -u1.1 httpd_config.conf
void plainconf::checkInFile(const char *path)
{
    if (access(path, 0) == -1)
        return ;

    //Backup file abd checkin and out
    char new_path[4096];
    strcpy(new_path, path);
    strcat(new_path, "0");

    AutoStr2 buf;
    buf.setStr("cp \"");
    buf.append(path, strlen(path));
    buf.append("\" \"", 3);
    buf.append(new_path, strlen(new_path));
    buf.append("\"", 1);
    int ret = system(buf.c_str());

    if (ret != 0)
    {
        logToMem(LOG_LEVEL_INFO, "Failed to backup the conf file %s, ret %d.",
                 path, ret);
        return ;
    }

    buf.setStr("ci -l -q -t-\"");
    buf.append(new_path, strlen(new_path));
    buf.append("\" -mUpdate \"", 12);
    buf.append(new_path, strlen(new_path));
    buf.append("\" >/dev/null 2>&1", 17);
    ret = system(buf.c_str());

    if (ret == 0)
        logToMem(LOG_LEVEL_INFO, "RCS checkin config file %s OK.", new_path);
    else
        logToMem(LOG_LEVEL_INFO,
                 "Failed to RCS checkin conf file %s, ret %d, error(%s). "
                 "Org command is %s.", new_path, ret, strerror(errno), buf.c_str());

    unlink(new_path);
}
static void setLastErrMsg(const char *format, ...)
{
    const unsigned int MAX_LINE_LENGTH = 1024;
    char s[MAX_LINE_LENGTH] = {0};
    va_list ap;
    va_start(ap, format);
    int ret = vsnprintf(s, MAX_LINE_LENGTH, format, ap);
    va_end(ap);

    if ((unsigned int)ret > MAX_LINE_LENGTH)
        ret = MAX_LINE_LENGTH;
    s_ErrMsg.setLen(0);
    s_ErrMsg.setStr(s, ret);
}
//name: form like "moduleName|submodlue|itemname"
const char *plainconf::getConfDeepValue(const XmlNode *pNode,
                                        const char *name)
{
    const char *p = strchr(name, '|');

    if (!p)
        return pNode->getChildValue(name);
    else
    {
        AutoStr2 subName;
        subName.setStr(name, p - name);
        const XmlNode *subNode = pNode->getChild(subName.c_str());

        if (subNode)
            return getConfDeepValue(subNode, p + 1);
        else
            return NULL;
    }
}
Exemple #5
0
const char *MIMESubMap::setMainType(const char *pType, int len)
{
    m_sMainType.setStr(pType, len);
    return m_sMainType.c_str();
}
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;
}
//This function may be recruse called
void plainconf::loadConfFile(const char *path)
{
    logToMem(LOG_LEVEL_INFO, "start parsing file %s", path);

    int type = checkFiletype(path);

    if (type == 0)
        return;

    else if (type == 2)
        loadDirectory(path, NULL);

    else if (type == 3)
    {
        AutoStr2 prefixPath = path;
        const char *p = strrchr(path, '/');

        if (p)
            prefixPath.setStr(path, p - path);

        struct stat sb;

        //removed the wildchar filename, should be a directory if exist
        if (stat(prefixPath.c_str(), &sb) == -1)
        {
            logToMem(LOG_LEVEL_ERR, "LoadConfFile error 1, path:%s directory:%s",
                     path, prefixPath.c_str());
            return ;
        }

        if ((sb.st_mode & S_IFMT) != S_IFDIR)
        {
            logToMem(LOG_LEVEL_ERR, "LoadConfFile error 2, path:%s directory:%s",
                     path, prefixPath.c_str());
            return ;
        }

        loadDirectory(prefixPath.c_str(), p + 1);
    }

    else //existed file
    {
        //gModuleList.push_back();
        //XmlNode *xmlNode = new XmlNode;
        FILE *fp = fopen(path, "r");

        if (fp == NULL)
        {
            logToMem(LOG_LEVEL_ERR, "Cannot open configuration file: %s", path);
            return;
        }


        const int MAX_LINE_LENGTH = 8192;
        char sLine[MAX_LINE_LENGTH];
        char *p;
        char sLines[MAX_LINE_LENGTH] = {0};
        int lineNumber = 0;
        const int MAX_MULLINE_SIGN_LENGTH = 128;
        char sMultiLineModeSign[MAX_MULLINE_SIGN_LENGTH] = {0};
        size_t  nMultiLineModeSignLen = 0;  //>0 is mulline mode

        while (fgets(sLine, MAX_LINE_LENGTH, fp), !feof(fp))
        {
            ++lineNumber;
            p = sLine;

            if (nMultiLineModeSignLen)
            {
                //Check if reach the END of the milline mode
                size_t len = 0;
                const char *pLineStart = getStrNoSpace(p, len);

                if (len == nMultiLineModeSignLen &&
                    strncasecmp(pLineStart, sMultiLineModeSign, nMultiLineModeSignLen) == 0)
                {
                    nMultiLineModeSignLen = 0;
                    removeSpace(sLines,
                                1);   //Remove the last \r\n so that if it is one line, it will still be one line
                    parseLine(path, lineNumber, sLines);
                    sLines[0] = 0x00;
                }
                else
                    strcat(sLines, p);

                continue;
            }

            removeSpace(p, 0);
            removeSpace(p, 1);

            if (!isValidline(p))
                continue;

            AutoStr2 pathInclude;

            if (isInclude(p, pathInclude))
            {
                char achBuf[512] = {0};
                getIncludeFile(pathInclude.c_str(), achBuf);
                loadConfFile(achBuf);
            }
            else
            {
                nMultiLineModeSignLen = checkMultiLineMode(p, sMultiLineModeSign,
                                        MAX_MULLINE_SIGN_LENGTH);

                if (nMultiLineModeSignLen > 0)
                    strncat(sLines, p, strlen(p) - (3 + nMultiLineModeSignLen));
                //need to continue
                else if (isChunkedLine(p))
                {
                    strncat(sLines, p, strlen(p) - 1);
                    //strcatchr(sLines, ' ', MAX_LINE_LENGTH); //add a space at the end of the line which has a '\\'
                }

                else
                {
                    strcat(sLines, p);
                    parseLine(path, lineNumber, sLines);
                    sLines[0] = 0x00;
                }
            }
        }

        fclose(fp);

        //Parsed, check in it
        checkInFile(path);
    }
}