/* * 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 #include #include #include #include #include #include #include #include #include #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 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("disclaimer_text_processed = 0; current_state->disclaimer_html_processed = 0; return DISCLAIMER_SUCCESS; }