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;
}