int inject_hashed_response_body()

in apache2/msc_crypt.c [1027:1254]


int inject_hashed_response_body(modsec_rec *msr, int elts) {
    xmlOutputBufferPtr output_buf = NULL;
    xmlCharEncodingHandlerPtr  handler = NULL;
    char *p = NULL;
    const char *ctype = NULL;
    const char *encoding = NULL;
    char *new_ct = NULL, *content_value = NULL;

    if(msr == NULL) return -1;

    if(msr->r == NULL) return -1;

    if (msr->crypto_html_tree == NULL) {
        if (msr->txcfg->debuglog_level >= 4)
            msr_log(msr, 4, "inject_hashed_response_body: Cannot parse NULL html tree");
        return -1;
    }

    if(msr->r->content_type != NULL)
        ctype = msr->r->content_type;

    encoding = (const char *) htmlGetMetaEncoding(msr->crypto_html_tree);

    if (ctype && encoding == NULL) {
        if (ctype && (p = m_strcasestr(ctype, "charset=") , p != NULL)) {
            p += 8 ;
            if (encoding = apr_pstrndup(msr->mp, p, strcspn(p, " ;") ), encoding) {
                xmlCharEncoding enc;
                enc = xmlParseCharEncoding(encoding);
                handler = xmlFindCharEncodingHandler(encoding);
            }
        }
    } else  {
        if(encoding != NULL)    {
            xmlCharEncoding enc;
            enc = xmlParseCharEncoding(encoding);
            handler = xmlFindCharEncodingHandler(encoding);
        }
    }

    if (msr->txcfg->debuglog_level >= 4)
        msr_log(msr, 4, "inject_hashed_response_body: Detected encoding type [%s].", encoding);

    if (handler == NULL)
        handler = xmlFindCharEncodingHandler("UTF-8");
    if (handler == NULL)
        handler = xmlFindCharEncodingHandler("ISO-8859-1");
    if (handler == NULL)
        handler = xmlFindCharEncodingHandler("HTML");
    if (handler == NULL)
        handler = xmlFindCharEncodingHandler("ascii");

    if(handler == NULL) {
        xmlFreeDoc(msr->crypto_html_tree);
        return -1;
    }

    apr_table_unset(msr->r->headers_out,"Content-Type");
    new_ct = (char*)apr_psprintf(msr->mp, "text/html;%s",handler->name);
    apr_table_set(msr->r->err_headers_out,"Content-Type",new_ct);

    if (msr->txcfg->debuglog_level >= 4)
        msr_log(msr, 4, "inject_hashed_response_body: Using content-type [%s].", handler->name);

    output_buf = xmlAllocOutputBuffer(handler);
    if (output_buf == NULL) {
        if (msr->txcfg->debuglog_level >= 4)
            msr_log(msr, 4, "inject_hashed_response_body: Unable to allocate memory buffer.");
        xmlFreeDoc(msr->crypto_html_tree);
        return -1;
    }

    htmlDocContentDumpFormatOutput(output_buf, msr->crypto_html_tree, NULL, 0);
    // Not necessary in 2.9.4+
    //xmlOutputBufferFlush(output_buf);

#ifdef  LIBXML2_NEW_BUFFER

    if (output_buf->conv == NULL || (output_buf->conv && xmlOutputBufferGetSize(output_buf) == 0)) {

        if(output_buf->buffer == NULL || xmlOutputBufferGetSize(output_buf) == 0)  {
            xmlOutputBufferClose(output_buf);
            xmlFreeDoc(msr->crypto_html_tree);
            msr->of_stream_changed = 0;
            msr_log(msr, 4, "inject_hashed_response_body: NEW_BUFFER Output buffer is null.");
            return -1;
        }

        if(msr->stream_output_data != NULL) {
            free(msr->stream_output_data);
            msr->stream_output_data =  NULL;
        }

        msr->stream_output_length = xmlOutputBufferGetSize(output_buf);
        msr->stream_output_data = (char *)malloc(msr->stream_output_length+1);

        if (msr->stream_output_data == NULL) {
            xmlOutputBufferClose(output_buf);
            xmlFreeDoc(msr->crypto_html_tree);
            msr_log(msr, 4, "inject_hashed_response_body: NEW BUFFER Stream Output is null.");
            return -1;
        }

        memset(msr->stream_output_data, 0x0, msr->stream_output_length+1);
        memcpy(msr->stream_output_data, xmlOutputBufferGetContent(output_buf), msr->stream_output_length);

        if (msr->txcfg->debuglog_level >= 4)
            msr_log(msr, 4, "inject_hashed_response_body: Copying XML tree from CONTENT to stream buffer [%zu] bytes.", xmlOutputBufferGetSize(output_buf));

    } else {

        if(output_buf->conv == NULL || xmlOutputBufferGetSize(output_buf) == 0)  {
            xmlOutputBufferClose(output_buf);
            xmlFreeDoc(msr->crypto_html_tree);
            msr->of_stream_changed = 0;
            msr_log(msr, 4, "inject_hashed_response_body: Conv is null.");
            return -1;
        }

        if(msr->stream_output_data != NULL) {
            free(msr->stream_output_data);
            msr->stream_output_data =  NULL;
        }

        msr->stream_output_length = xmlOutputBufferGetSize(output_buf);
        msr->stream_output_data = (char *)malloc(msr->stream_output_length+1);

        if (msr->stream_output_data == NULL) {
            msr_log(msr, 4, "inject_hashed_response_body: Stream Output data is NULL.");
            xmlOutputBufferClose(output_buf);
            xmlFreeDoc(msr->crypto_html_tree);
            return -1;
        }

        memset(msr->stream_output_data, 0x0, msr->stream_output_length+1);
        memcpy(msr->stream_output_data, xmlOutputBufferGetContent(output_buf), msr->stream_output_length);

        if (msr->txcfg->debuglog_level >= 4)
            msr_log(msr, 4, "inject_hashed_response_body: Copying XML tree from CONV to stream buffer [%zu] bytes.", xmlOutputBufferGetSize(output_buf));

    }

#else

    if (output_buf->conv == NULL || (output_buf->conv && output_buf->conv->use == 0)) {

        if(output_buf->buffer == NULL || output_buf->buffer->use == 0)  {
            xmlOutputBufferClose(output_buf);
            xmlFreeDoc(msr->crypto_html_tree);
            msr_log(msr, 4, "inject_hashed_response_body: Output buffer is null.");
            msr->of_stream_changed = 0;
            return -1;
        }

        if(msr->stream_output_data != NULL) {
            free(msr->stream_output_data);
            msr->stream_output_data =  NULL;
        }

        msr->stream_output_length = output_buf->buffer->use;
        msr->stream_output_data = (char *)malloc(msr->stream_output_length+1);

        if (msr->stream_output_data == NULL) {
            xmlOutputBufferClose(output_buf);
            xmlFreeDoc(msr->crypto_html_tree);
            msr_log(msr, 4, "inject_hashed_response_body: Stream Output is null.");
            return -1;
        }

        memset(msr->stream_output_data, 0x0, msr->stream_output_length+1);
        memcpy(msr->stream_output_data, (char *)xmlBufferContent(output_buf->buffer), msr->stream_output_length);
        //memcpy(msr->stream_output_data, output_buf->buffer->content, msr->stream_output_length);

        if (msr->txcfg->debuglog_level >= 4)
            msr_log(msr, 4, "inject_hashed_response_body: Copying XML tree from CONTENT to stream buffer [%d] bytes.", msr->stream_output_length);

    } else {

        if(output_buf->conv == NULL || output_buf->conv->use == 0)  {
            xmlOutputBufferClose(output_buf);
            xmlFreeDoc(msr->crypto_html_tree);
            msr->of_stream_changed = 0;
            msr_log(msr, 4, "inject_hashed_response_body: Stream Output is null.");
            return -1;
        }

        if(msr->stream_output_data != NULL) {
            free(msr->stream_output_data);
            msr->stream_output_data =  NULL;
        }

        msr->stream_output_length = output_buf->conv->use;
        msr->stream_output_data = (char *)malloc(msr->stream_output_length+1);

        if (msr->stream_output_data == NULL) {
            xmlOutputBufferClose(output_buf);
            xmlFreeDoc(msr->crypto_html_tree);
            msr_log(msr, 4, "inject_hashed_response_body: Stream Output Data is null.");
            return -1;
        }

        memset(msr->stream_output_data, 0x0, msr->stream_output_length+1);
        memcpy(msr->stream_output_data, (char *)xmlBufferContent(output_buf->conv), msr->stream_output_length);
        //memcpy(msr->stream_output_data, output_buf->conv->content, msr->stream_output_length);

        if (msr->txcfg->debuglog_level >= 4)
            msr_log(msr, 4, "inject_hashed_response_body: Copying XML tree from CONV to stream buffer [%d] bytes.", msr->stream_output_length);

    }

#endif

    xmlOutputBufferClose(output_buf);

    content_value = (char*)apr_psprintf(msr->mp, "%"APR_SIZE_T_FMT, msr->stream_output_length);
    apr_table_unset(msr->r->headers_out,"Content-Length");

    if (msr->txcfg->debuglog_level >= 4)
        msr_log(msr, 4, "inject_hashed_response_body: Setting new content value %s", content_value);
    apr_table_set(msr->r->headers_out, "Content-Length", content_value);

    xmlFreeDoc(msr->crypto_html_tree);

    if (msr->txcfg->debuglog_level >= 4)
        msr_log(msr, 4, "inject_hashed_response_body: Stream buffer [%"APR_SIZE_T_FMT"]. Done",msr->stream_output_length);

    return 1;
}