src/transaction.cc
/**
 * @name    appendResponseBody
 * @brief   Adds reponse body to be inspected.
 *
 * With this method it is possible to feed ModSecurity with data for
 * inspection regarding the response body. ModSecurity can also update the
 * contents of the response body, this is not quite ready yet on this version
 * of the API. 
 *
 * @note If the content is updated, the client cannot receive the content
 *       length header filled, at least not with the old values. Otherwise
 *       unexpected behavior may happens.
 *
 * @returns If the operation was successful or not.
 * @retval true Operation was successful.
 * @retval false Operation failed, process partial demanded.
 *
 */
@name    appendResponseBody
@brief   Adds reponse body to be inspected.

With this method it is possible to feed ModSecurity with data for
inspection regarding the response body. ModSecurity can also update the
contents of the response body, this is not quite ready yet on this version
of the API.

@note If the content is updated, the client cannot receive the content
length header filled, at least not with the old values. Otherwise
unexpected behavior may happens.

@returns If the operation was successful or not.
@retval true Operation was successful.
@retval false Operation failed, process partial demanded.
@name appendResponseBody @brief Adds reponse body to be inspected . With this method it is possible to feed ModSecurity with data for inspection regarding the response body . ModSecurity can also update the contents of the response body this is not quite ready yet on this version of the API . @note If the content is updated the client cannot receive the content length header filled at least not with the old values . Otherwise unexpected behavior may happens . @returns If the operation was successful or not . @retval true Operation was successful . @retval false Operation failed process partial demanded .
int Transaction::appendResponseBody(const unsigned char *buf, size_t len) {
    int current_size = this->m_responseBody.tellp();
    std::set<std::string> &bi = this->m_rules->m_responseBodyTypeToBeInspected;
    auto t = bi.find(*m_responseContentType);
    if (t == bi.end() && bi.empty() == false) {
#ifndef NO_LOGS
        debug(4, "Not appending response body. " \
            "Response Content-Type is " + *m_responseContentType + \
            ". It is not marked to be inspected.");
#endif
        return true;
    }
#ifndef NO_LOGS
    debug(9, "Appending response body: " + std::to_string(len + current_size)
        + " bytes. Limit set to: " +
        std::to_string(this->m_rules->m_responseBodyLimit.m_value));
#endif
    if (this->m_rules->m_responseBodyLimit.m_value > 0
        && this->m_rules->m_responseBodyLimit.m_value < len + current_size) {
        m_collections.store("OUTBOUND_DATA_ERROR", "1");
#ifndef NO_LOGS
        debug(5, "Response body is bigger than the maximum expected.");
#endif
        if (this->m_rules->m_responseBodyLimitAction ==
            Rules::BodyLimitAction::ProcessPartialBodyLimitAction) {
            size_t spaceLeft = this->m_rules->m_responseBodyLimit.m_value \
                - current_size;
            this->m_responseBody.write(reinterpret_cast<const char*>(buf),
                spaceLeft);
#ifndef NO_LOGS
            debug(5, "Response body limit is marked to process partial");
#endif
            return false;
        } else {
            if (this->m_rules->m_responseBodyLimitAction ==
                Rules::BodyLimitAction::RejectBodyLimitAction) {
#ifndef NO_LOGS
                debug(5, "Response body limit is marked to reject the " \
                    "request");
#endif
                intervention::free(&m_it);
                m_it.log = strdup("Response body limit is marked to reject " \
                    "the request");
                m_it.status = 403;
                m_it.disruptive = true;
            }
            return true;
        }
    }
    this->m_responseBody.write(reinterpret_cast<const char*>(buf), len);
    return true;
}
int Transaction :: appendResponseBody ( const unsigned char * buf , size_t len ) { int current_size = this -> m_responseBody . tellp ( ) ; std :: set < std :: string > & bi = this -> m_rules -> m_responseBodyTypeToBeInspected ; auto t = bi . find ( * m_responseContentType ) ; if ( t == bi . end ( ) && bi . empty ( ) == false ) { #ifndef NO_LOGS debug ( 4 , " " " " + * m_responseContentType + " " ) ; #endif return true ; } #ifndef NO_LOGS debug ( 9 , " " + std :: to_string ( len + current_size ) + " " + std :: to_string ( this -> m_rules -> m_responseBodyLimit . m_value ) ) ; #endif if ( this -> m_rules -> m_responseBodyLimit . m_value > 0 && this -> m_rules -> m_responseBodyLimit . m_value < len + current_size ) { m_collections . store ( " " , " " ) ; #ifndef NO_LOGS debug ( 5 , " " ) ; #endif if ( this -> m_rules -> m_responseBodyLimitAction == Rules :: BodyLimitAction :: ProcessPartialBodyLimitAction ) { size_t spaceLeft = this -> m_rules -> m_responseBodyLimit . m_value - current_size ; this -> m_responseBody . write ( reinterpret_cast < const char * > ( buf ) , spaceLeft ) ; #ifndef NO_LOGS debug ( 5 , " " ) ; #endif return false ; } else { if ( this -> m_rules -> m_responseBodyLimitAction == Rules :: BodyLimitAction :: RejectBodyLimitAction ) { #ifndef NO_LOGS debug ( 5 , " " " " ) ; #endif intervention :: free ( & m_it ) ; m_it . log = strdup ( " " " " ) ; m_it . status = 403 ; m_it . disruptive = true ; } return true ; } } this -> m_responseBody . write ( reinterpret_cast < const char * > ( buf ) , len ) ; return true ; }
@name    appendResponseBody
 @brief   Adds reponse body to be inspected.
@name appendResponseBody @brief Adds reponse body to be inspected .