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