/*
* Program: Synonym
* File: disclaimer.c
* Author: Cristian Draghici
* Date: 09 Sep 2003
*
* $Id: disclaimer.c,v 1.3.2.1 2004/01/30 08:12:11 diciu Exp $
*
* Licensed under the Modulo Consulting Software License
* (see file license.txt)
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/stat.h>
#include <syslog.h>
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include "c-client/mail.h"
#include "c-client/osdep.h"
#include "c-client/rfc822.h"
#include "c-client/flstring.h"
#include "disclaimer.h"
#include "html_parser.h"
/* recursion level while parsing MIME parts. After this level we stop parsing considering attack. */
#define MIME_RECURSION_DEPTH 10
#define MAX_HOSTNAME_LENGTH 255
char SUBTYPE_PLAIN_STRING[] = "plain";
char SUBTYPE_HTML_STRING[] = "html";
#define print_debug syslog
/* declarations for internal use functions */
int disclaimer_text_read(char *buffer, int buffer_size, FILE*input_stream, disclaimer_state *current_state);
int disclaimer_html_read(char *buffer, int buffer_size, FILE*input_stream, disclaimer_state *current_state);
int disclaimer_html_read_encoding(char *buffer, int buffer_size, FILE*input_stream, disclaimer_state *current_state);
void read_text_offset(BODY * body,char * pfx,long i, disclaimer_state *current_state);
char *old_get_server_hostname(char *hostname);
int compute_additional_html_offset(char * buffer, int buffer_size, FILE * input_stream, disclaimer_state *current_state);
/* add the text disclaimer to a text part.
* content = the decoded content of the text/plain
* size = the size of the part.
*/
char * add_text_disclaimer(char *content, long size, long *processed_size, disclaimer_state *current_state)
{
char * processed_content = NULL;
/* skip end of string char */
long localsize = size - 1;
if(current_state->disclaimer_text == NULL)
return NULL;
processed_content = fs_get(localsize + strlen(current_state->disclaimer_text) + 1);
memcpy(processed_content, content, localsize);
memcpy((void *)(processed_content + localsize), current_state->disclaimer_text, strlen(current_state->disclaimer_text));
*processed_size = localsize + strlen(current_state->disclaimer_text) + 1;
/* mark the end of string for printf and friends */
processed_content[localsize + strlen(current_state->disclaimer_text)] = '\0';
current_state->disclaimer_text_processed = 1;
return processed_content;
}
char * add_html_disclaimer(char *content, long size, long *processed_size, disclaimer_state *current_state)
{
char * processed_content = NULL;
int end_of_body_offset = 0;
int column, line, retval;
/* skip end of string char */
long localsize = size - 1;
if(current_state->disclaimer_html == NULL)
return NULL;
processed_content = fs_get(localsize + strlen(current_state->disclaimer_html) + 1);
/* get the end of the body tag */
retval = locate_end_tag_in_string(content, processed_content,
size + strlen(current_state->disclaimer_html), &column, &line, localsize);
if(retval == DISCLAIMER_FAILURE)
{
print_debug(LOG_ERR, "Error in locate_end_tag_in_string result!");
/* TODO: treat this error */
return DISCLAIMER_FAILURE;
}
print_debug(LOG_DEBUG, "disclaimer: Body is ending at line %d and column %d", line, column);
/* transform the line/column offset into byte offset */
end_of_body_offset = linecolumn_to_byte(content, localsize, line, column);
memcpy(processed_content, content, end_of_body_offset);
memcpy((void *)(processed_content+end_of_body_offset), current_state->disclaimer_html,
strlen(current_state->disclaimer_html));
if(end_of_body_offset < localsize)
memcpy((void *)(processed_content+end_of_body_offset+strlen(current_state->disclaimer_html)),
(content+end_of_body_offset),
localsize-end_of_body_offset);
processed_content[localsize + strlen(current_state->disclaimer_html)] = '\0';
*processed_size = localsize + strlen(current_state->disclaimer_html) + 1;
current_state->disclaimer_html_processed = 1;
return processed_content;
}
/* Convert a line/column offset to byte offset.
* Line terminator is \r\n */
int linecolumn_to_byte(char *content, int size, int lin, int col)
{
char *pos;
int line_count = 0;
pos = content;
while(line_count < lin-1) //lin is 1 based, linecount is 0 based
{
//print_debug(LOG_DEBUG, "linecolumn_to_byte: at line %d", line_count);
if(pos != NULL)
{
if(pos+1 < content+size)
{
pos = memchr(pos+1, '\n', content+size-pos);
if(pos != NULL)
if(*(pos-1) == '\r')
line_count++;
}
else
{
/* this happens when the body tag is not closed or not present at all */
print_debug(LOG_DEBUG, "linecolumn_to_byte: Cannot reach line! Position would go over. Line count is %d, line offset is %d", line_count, lin-1);
break;
}
}
else
{
/* this happens when the body tag is not closed or not present at all */
print_debug(LOG_DEBUG, "linecolumn_to_byte: Cannot reach line! line count is %d, line offset is %d", line_count, lin-1);
break;
}
}
if(pos == NULL)
{
print_debug(LOG_DEBUG, "linecolumn_to_byte: Assertion failed! (the line offset is bigger than the total number of lines).");
pos = content + size;
}
else
{
if(pos + col <= content + size)
pos += (col-1);
else
print_debug(LOG_DEBUG, "linecolumn_to_byte: Assertion failed! (end of body exceeds end of HTML).");
}
/* if we found a position.
second condition is there because libxml simply reports the end of the file as </body> if the tag is missing, so we need to avoid deducting the size of the tag in that case*/
if(pos != NULL && *pos == '<')
{
return pos - content - 6; // 6 is strlen("</body");
}
else
return size; //if failure add at the end.
}
/* see header file for comments */
int disclaimer_init(disclaimer_state *current_state)
{
current_state->disclaimer_text_processed = 0;
current_state->disclaimer_html_processed = 0;
return DISCLAIMER_SUCCESS;
}
syntax highlighted by Code2HTML, v. 0.9.1