#include #include #include #include #include #include #include #include "../global.h" #include "shared_cs_util.h" #include "shared_msg_line.h" #include "shared_translate_url.h" #include "shared_strtrm.h" LINE_NODE *line_head = 0; #define MAX_SMILE_CODE 12 const char *code[MAX_SMILE_CODE] = {":-)", ":lol:", ":-o", ":!:", ":?:", ":idea:", ":-(", ":shock:", ":-x", "8-)", ";-(", ":-?" }; const char *icon_img[MAX_SMILE_CODE] = {"icon_smile.gif", "icon_lol.gif", "icon_surprised.gif", "icon_exclaim.gif", "icon_question.gif", "icon_idea.gif", "icon_sad.gif", "icon_eek.gif", "icon_mad.gif", "icon_cool.gif", "icon_wink.gif", "icon_confused.gif"}; #define MAX_BB_CODE 7 #define BB_BOLD "**" #define BB_UNDER_LINE "__" #define BB_ITALIC "||" #define BB_HEADING_4 "!!" #define BB_HEADING_3 "!!!" #define BB_HEADING_2 "!!!!" #define BB_PRE "%%" const char *bb_code_array[MAX_BB_CODE] ={ BB_BOLD, BB_UNDER_LINE, BB_ITALIC, BB_HEADING_2, BB_HEADING_3, BB_HEADING_4, BB_PRE }; const char *start_tag_array[MAX_BB_CODE] ={ "", "", "", "", "", "", ""}; #define MINIMUM_SIZE 256 typedef struct mystring { int buf_len; int used_len; char *buf; }MYSTRING; void mystring_init(MYSTRING *the_string, int len) { the_string->buf = (char *) malloc(len * sizeof(char)); if(!the_string->buf) cs_critical_error(ERR_MALLOC_FAILED, "mystring_init()"); *the_string->buf = '\0'; the_string->buf_len = len; the_string->used_len = 0; } void mystring_free(MYSTRING *the_string) { if(the_string->buf) { free(the_string->buf); the_string->buf_len = 0; the_string->used_len = 0; } } void mystring_append(MYSTRING *the_string, const char *appended) { int append_len; int bytes_to_add; append_len = strlen(appended); if( (append_len + the_string->used_len + 1) > the_string->buf_len) { bytes_to_add = (append_len * 2) < MINIMUM_SIZE ? MINIMUM_SIZE : (append_len * 2); the_string->buf = realloc(the_string->buf, the_string->buf_len + bytes_to_add); if(!the_string->buf) cs_critical_error(ERR_MALLOC_FAILED, "mystring_append()"); the_string->buf_len += bytes_to_add; } strncat(the_string->buf, appended, append_len); the_string->used_len = strlen(the_string->buf); } void mystring_append_char(MYSTRING *the_string, char ch) { char charstring[2]; *charstring = ch; *(charstring + 1) = '\0'; mystring_append(the_string, charstring); } static char *shrink_copy(char *string) { char *result; int len; len = strlen(string) + 1; result = (char *) malloc(len * sizeof(char)); if(!result) cs_critical_error(ERR_MALLOC_FAILED, "shrink_copy()"); strncpy(result, string,len); return result; } /* a url path is at least 5 chars long and has at least one period */ static int is_url_path (char *string, int *count) { char *ptr; int dots; for (*count = 0, dots = 0, ptr = string; *ptr && !isspace (*ptr); ptr++, (*count)++) if (*ptr == '.') dots++; if ((dots < 1) || (*count < 5)) return 0; /* exclude trailing punctuation */ for (ptr--; (*count >= 5) && ispunct (*ptr); ptr--, (*count)--) if (*ptr == '.') dots--; return (dots >= 1) && (*count >= 5); } /* a mail address is at least 5 chars long and has just one @ and at least one periods */ static int is_mail_address (char *string, int *count) { char *ptr; int dots; int ats; for (*count = 0, dots = 0, ats = 0, ptr = string; *ptr && !isspace (*ptr); ptr++, (*count)++) { if (*ptr == '.') dots++; else if (*ptr == '@') ats++; } if ((dots < 1) || (*count < 5) || (ats != 1)) return 0; /* exclude trailing punctuation */ for (ptr--; (*count >= 5) && ispunct (*ptr); ptr--, (*count)--) { if (*ptr == '.') dots--; else if (*ptr == '@') ats--; } return (dots >= 1) && (*count >= 5) && (ats == 1); } static void append_anchor (const char *protocol, char *string, int count, MYSTRING *the_string) { char *ptr; int i; mystring_append (the_string, ""); } else mystring_append(the_string, "\">"); } int is_blank_line(char *line) { char *ptr; for(ptr=line; *ptr; ptr++) if(!isspace(*ptr)) return 0; return 1; } void alloc_formatted_line (char *line, int do_anchors, int insert_br, char **new_line) { char *ptr, *ptr2 =0, *ptr3 =0; char temp[20]; int do_slashes = 0; /* possibility of ftp://, telnet:// or http:// urls */ int do_mail = 0; int count; int i, j, start_bb_count =0, end_bb_count =0; int last_was_space = 0; char examined_char; MYSTRING result; int is_https; char icon_path[MAX_PATH +1]; char icon_end_path[MAX_PATH +1]; snprintf(icon_path, MAX_PATH +1, "\"\"/"); mystring_init(&result, MINIMUM_SIZE); /* do some checks to see if we need to look for URL's * */ if (do_anchors) { do_anchors = (int) strchr (line, ':'); /* must have at least a ':' */ do_slashes = do_anchors && (int) strstr (line, "://"); do_mail = do_anchors && (int) strchr (line, '@'); } if(insert_br && is_blank_line(line)) mystring_append(&result, "
"); else { for (ptr = line; *ptr;) { examined_char = *ptr; start_bb_count = 0; end_bb_count =0; switch (*ptr) { case '<': for(j =0; j') /* looks like " */ { ptr2 = strchr ("bBiIuU", *(ptr + 2)); if (ptr2) /* char after slash is biu */ { snprintf (temp, 20, "", *ptr2); mystring_append(&result, temp); ptr += 4; } else /* did not meet tests */ { mystring_append (&result, "<"); ptr++; } } else /* doesn't look like */ { mystring_append(&result,"<"); ptr++; } } else /* second char is one of 'bBuUIi' */ if (*(ptr + 2) == '>') /* then it's or etc */ { snprintf (temp, 20, "<%c>", *(ptr + 1)); mystring_append (&result,temp); ptr += 3; } else { mystring_append(&result, "<"); ptr++; } else /* not < followed by biu/ */ { mystring_append(&result, "<"); ptr++; } } else /* not at least two more characters after < */ { mystring_append(&result, "<"); ptr++; } } break; case '>': mystring_append(&result,">"); ptr++; break; case '&': mystring_append(&result, "&"); ptr++; break; case 'h': case 'H': if (!do_slashes || !(ptr == line || (*(ptr - 1) == ' ') || (*(ptr - 1) == '>'))) { mystring_append_char(&result, *ptr); ptr++; } else /* we know there's a space before the 'h' */ { *temp = '\0'; strncat (temp, ptr, 12); /* 12 = strlen("http://a.b.c") */ if (strlen (temp) != 12) { mystring_append_char(&result, *ptr); ptr++; } else { for (ptr2 = temp; *ptr2; ptr2++) *ptr2 = tolower (*ptr2); is_https = !strncmp(temp, "https://", 8); if (!is_https && strncmp (temp, "http://", 7) ) /* i.e. it's not http:// and it's not https:// */ { mystring_append_char(&result, *ptr); ptr++; } else { if (is_url_path (is_https?ptr + 8:ptr + 7, &count)) { append_anchor (is_https?"https://":"http://", is_https?ptr + 8:ptr + 7, count, &result); for (i = 1; i <= ((is_https?8:7) + count); i++) { mystring_append_char(&result, *ptr); ptr++; } mystring_append (&result, "
"); } else { mystring_append_char(&result, *ptr); ptr++; } } } } break; case 'f': case 'F': if (!do_slashes || !(ptr == line || (*(ptr - 1) == ' '))) { mystring_append_char (&result, *ptr); ptr++; } else /* we know there's a space before the 'f' */ { *temp = '\0'; strncat (temp, ptr, 11); /* 11 = strlen("ftp://a.b.c") */ if (strlen (temp) != 11) { mystring_append_char (&result, *ptr); ptr++; } else { for (ptr2 = temp; *ptr2; ptr2++) *ptr2 = tolower (*ptr2); if (strncmp (temp, "ftp://", 6)) { mystring_append_char (&result, *ptr); ptr++; } else { if (is_url_path (ptr + 6, &count)) { append_anchor ("ftp://", ptr + 6, count, &result); for (i = 1; i <= (6 + count); i++) { mystring_append_char (&result, *ptr); ptr++; } mystring_append (&result, ""); } else { mystring_append_char (&result, *ptr); ptr++; } } } } break; case 't': case 'T': if (!do_slashes || !(ptr == line || (*(ptr - 1) == ' '))) { mystring_append_char (&result, *ptr); ptr++; } else /* we know there's a space before the 't' */ { *temp = '\0'; strncat (temp, ptr, 14); /* 14 = strlen("telnet://a.b.c") */ if (strlen (temp) != 14) { mystring_append_char (&result, *ptr); ptr++; } else { for (ptr2 = temp; *ptr2; ptr2++) *ptr2 = tolower (*ptr2); if (strncmp (temp, "telnet://", 9)) { mystring_append_char (&result, *ptr); ptr++; } else { if (is_url_path (ptr + 9, &count)) { append_anchor ("telnet://", ptr + 9, count, &result); for (i = 1; i <= (9 + count); i++) { mystring_append_char (&result, *ptr); ptr++; } mystring_append (&result, ""); } else { mystring_append_char (&result, *ptr); ptr++; } } } } break; case 'm': case 'M': if (!do_mail || !(ptr == line || (*(ptr - 1) == ' '))) { mystring_append_char (&result, *ptr); ptr++; } else /* we know there's a space before the 'm' */ { *temp = '\0'; strncat (temp, ptr, 12); /* 12 = strlen("mailto:a@b.c") */ if (strlen (temp) != 12) { mystring_append_char (&result, *ptr); ptr++; } else { for (ptr2 = temp; *ptr2; ptr2++) *ptr2 = tolower (*ptr2); if (strncmp (temp, "mailto:", 7)) { mystring_append_char (&result, *ptr); ptr++; } else { if (is_mail_address (ptr + 7, &count)) { append_anchor ("mailto:", ptr + 7, count, &result); for (i = 1; i <= (7 + count); i++) { mystring_append_char (&result, *ptr); ptr++; } mystring_append (&result, ""); } else { mystring_append_char (&result, *ptr); ptr++; } } } } break; case ' ': if(last_was_space) mystring_append(&result, " "); else mystring_append_char(&result, ' '); ptr++; break; default: mystring_append_char (&result, *ptr); ptr++; break; } last_was_space = (examined_char == ' '); } } *new_line = shrink_copy(result.buf); mystring_free(&result); } /* does the string start with chars that typically start a url? * */ static int starts_with_url(char *string) { #define MIN_LEN 8 /* 8 is strlen("https://") */ char *ptr; char saved; char string_start[MIN_LEN + 1]; /* Assume that if the string is not at least as long as ** MIN_LEN, then it's not a URL. This is a safe assumption ** because if the string WAS shorter than that, it wouldn't ** have wrapped in the first place. */ if(strlen(string) < MIN_LEN) return 0; /* To facilitate the string comparisons, make a copy of ** the beginning of string into string_start */ saved = *(string + MIN_LEN); *(string + MIN_LEN) = '\0'; strncpy(string_start, string, MIN_LEN + 1); *(string + MIN_LEN) = saved; /* original string is back to where it started. ** string_start contains the first MIN_LEN chars ** of original string **/ /* convert (small) string start to lowercase for comparison */ for(ptr=string_start; *ptr; ptr++) *ptr = tolower(*ptr); /* does string_start start with the magic characters */ ptr = strstr(string_start,"https://"); if(!ptr) { ptr = strstr(string_start,"http://"); if(!ptr) { ptr = strstr(string_start,"ftp://"); } } return (ptr == string_start)? 1 : 0; #undef MIN_LEN } /* Returns a char pointer to the character in line_start, which ** marks the beginning of a url that has been wrapped to another line, ** or (char *) 0 if no wrapping of a url has occurred in this line. ** ** line_start is the beginning of the line. ** line_end points to the end of the line and *line_end == '\n' **/ static char *wrapped_url_start(char *line_start, char *line_end) { char *url_start; char *space_ptr; int is_url; /* A continued line will end with CONTINUATION_CHAR\n */ if( (line_start >= line_end - 1) || (*(line_end - 1) != CONTINUATION_CHAR)) return (char *) 0; /* line doesn't end with CONTINUATION_CHAR */ /* still here? Then the line MAY contain a wrapped URL */ *(line_end - 1) = '\0'; /* change CONTINUATION_CHAR to terminating NULL */ /* The message we are working on may contain a quote from a ** previous message. We'll try to maintain the URL linking even ** in these quoted messages. ** Skip past any leading QUOTE_CHAR **/ for(url_start = line_start; *url_start && (*url_start == QUOTE_CHAR); url_start++); /* skip leanding QUOTE_CHAR */ if(!*url_start) /* line had nothing but QUOTE_CHAR */ { *(line_end - 1) = CONTINUATION_CHAR; /* restore the string to its original contents */ return (char *) 0; /* no wrapped url found */ } /* Still here? Then url_start points to the first character in the line ** that is not a QUOTE_CHAR. ** The start of a wrapped URL is either here, or it's after the first space ** looking in reverse from the end of the string **/ space_ptr = strrchr(url_start,' '); /* search backwards for a space */ if(space_ptr) url_start = space_ptr + 1; /* At this point, url_start points to a string containing all non-blank characters ** This string was wrapped automatically when the message was sent. ** Does this string start with chars like "http://" ??? **/ is_url = starts_with_url(url_start); *(line_end - 1) = CONTINUATION_CHAR; /* restore original string */ if(is_url) return url_start; else return (char *) 0; } /** Returns a newly allocated string which contains a url of the form: *** "http://....." or "https:// ....." or "ftp://" *** *** line_start :points to the start of the ENTIRE remainder of the *** message. The wrapped url is known to start at: *** *** start_wrapped_url : points to the start of the wrapped url. *** line_start <= start_wrapped_url < line_end *** *** line_end: points to the first '\n' after line_start *** *** wrapped_url is a newly allocated string containing the url, which ** will be set by this function *** *** wrapped_url_line_count is set by this function and represents the *** number of lines we had to process before *** finding the end of the wrapped url *** *** This function returns a char pointer to the point in the original *** message string that contained the last character of the wrapped_url **/ static char *set_wrapped_url(char *line_start, char *line_end, char *start_wrapped_url, char **wrapped_url, int *wrapped_url_line_count) { int url_max; char saved_char; char *dest_ptr; char *src_ptr; char *end_wrapped_url; char *tmp_wrapped_url; int start_of_line; int done; /* How much memory to allocate? This may be wasteful, but ** we know the url cannot be longer then the length of the entire ** message, starting from the beginning of this line. ** ** This should allow no limits on the length of a wrapped URL. ** We'll shrink the allocated space down before returning. **/ url_max = strlen(line_start) + 50; /* this is actually the length of the entire msg, ** plus a fudge factor, starting from line_start */ /** allocate space for the url */ tmp_wrapped_url = (char *) malloc((url_max + 1) * sizeof(char)); if(!tmp_wrapped_url) cs_critical_error(ERR_MALLOC_FAILED, "set_wrapped_url()"); /* line_end points to the first '\n' ** the char before line_end is CONTINUATION_CHAR ** for simplicity, null terminate line_start at the CONTINUATION_CHAR */ saved_char = *(line_end -1 ); /* this SHOULD always be CONTINUATION_CHAR, or we wouldn't be here! */ *(line_end - 1) = '\0'; /** ASSUMES start_wrapped_url has been correctly set ** by other routines to be before line_end. ** ** Since start_wrapped_url points to the start of the ** URL, we can safely assume the wrapped_url starts here ** and extends to the end of the line */ strncpy(tmp_wrapped_url,start_wrapped_url, url_max + 1); /* restore original passed-in string **/ *(line_end - 1) = saved_char; /* We'll be adding a character at a time to the ** wrapped_url we started. Find the end of that ** string. */ dest_ptr = strchr(tmp_wrapped_url, '\0'); /* The above assignment should always find a null ** terminator. To be safe, test and bail with ** empty entries, which should be safe for the ** caller. **/ if(!dest_ptr) { *wrapped_url = (char *) malloc(sizeof(char)); **wrapped_url = '\0'; *wrapped_url_line_count = 0; return (char *) 0; } /** search forward through the message, building the *** tmp_wrapped_url string as we go, by copying *src_ptr to ** *dest_ptr, until we find a character *** that marks the end of the wrapped_url **/ done = 0; src_ptr = line_end + 1; /* start after that first '\n' */ start_of_line = 1; /* need to track when we are at the start of a line ** to know if we need to skip leading QUOTE_CHAR */ /* each iteration deals with exactly one character ** from the original message */ while(!done) { switch(*src_ptr) /* what is that character? */ { /* if it's a quote character at the start of a line, ** ignore it. If it's NOT at the start of a line ** then we've found the end of the url **/ case QUOTE_CHAR: if(!start_of_line) { done = 1; end_wrapped_url = src_ptr; /* mark the char after the end of the url */ } break; /* If we encounter a CONTINUATION_CHAR at the end of a line ** it means this url spans yet another line. If the ** CONTINUATION_CHAR is NOT at the end of a line, then it ** represents the end of the URL. **/ case CONTINUATION_CHAR: if(*(src_ptr + 1) != '\n') { done = 1; end_wrapped_url = src_ptr; } else { src_ptr++; /* LOOK- this skips the '\n' */ start_of_line = 1; } break; /** For any char other than QUOTE_CHAR and CONTINUATION_CHAR ***/ default: if(isspace(*src_ptr)) /* any whitespace ends the url */ { done = 1; end_wrapped_url = src_ptr; } else /* it's not a space - add it to the URL */ { *dest_ptr = *src_ptr; dest_ptr++; *dest_ptr = '\0'; /* leave dest_ptr --> '\0' */ start_of_line = 0; } break; } if(!done) src_ptr++; } /* now count how many lines the url spanned ** it's always one more than the number of \n's encountered, ** so we start the count at one **/ for(src_ptr = start_wrapped_url, *wrapped_url_line_count = 1; *src_ptr && (src_ptr < end_wrapped_url); src_ptr++) { if(*src_ptr == '\n') (*wrapped_url_line_count)++; } /* we (probably) allocated much too much memory ** shrink it down to size */ *wrapped_url = shrink_copy(tmp_wrapped_url); free(tmp_wrapped_url); return end_wrapped_url; } /** adds the null-terminated line to the linked list ***/ static void add_line_to_list(char *line, int reply_level) { LINE_NODE *line_ptr; LINE_NODE *new_node; new_node = (LINE_NODE *) malloc(sizeof(LINE_NODE)); if(!new_node) cs_critical_error(ERR_MALLOC_FAILED, "add_line_to_list()"); new_node->content = line; new_node->reply_level = reply_level; new_node->next = (LINE_NODE *) 0; if(!line_head) line_head = new_node; else { for(line_ptr=line_head; line_ptr->next; line_ptr = line_ptr->next); line_ptr->next = new_node; } } static int reply_level_count(char *string) { char *ptr; int reply_level; for(ptr = string, reply_level = 0; *ptr && (*ptr == QUOTE_CHAR); ptr++, reply_level++); return reply_level; } /** adds the line, which starts with line_start ** to the list. ** line_end points to a '\n' and marks the end ** of the line. **/ static void add_formatted_line(char *line_start, char *line_end) { char saved_char; char *formatted_line; int reply_level; saved_char = *line_end; *line_end = '\0'; reply_level = reply_level_count(line_start); alloc_formatted_line(line_start, 1, 1, &formatted_line); *line_end = saved_char; add_line_to_list(formatted_line, reply_level); } static void append_wrapped_anchor(char *wrapped_url, MYSTRING *thestring) { mystring_append(thestring, ""); } static void add_wrapped_url_line(char *line_start, char *line_end, char *start_wrapped_url, char *end_wrapped_url, char *wrapped_url) { char *formatted_line = 0; char saved_char; char *ptr; int reply_level; MYSTRING result; /* record number of leading QUOTE_CHARs before any formatting is ** done **/ saved_char = *line_end; *line_end = '\0'; reply_level = reply_level_count(line_start); *line_end = saved_char; /* start with a reasonable amount of space */ mystring_init(&result, MINIMUM_SIZE * 2); /* If the start of the wrapped URL is on this line, then ** we know the URL part must extend to the end of the line. ** ** 1) Write the part before the URL (formatted) ** 2) Write the url, which extends to the end of the line **/ if( (start_wrapped_url >= line_start) && (start_wrapped_url <= line_end)) { /* format from the beginning of the line to the start ** of the wrapped_url, and store that chunk in the ** string */ saved_char = *start_wrapped_url; *(start_wrapped_url) = '\0'; /* line_start points to the start of the string and ** ends right before the start of the wrapped url ** Format this chunk, and store it */ alloc_formatted_line(line_start, 1, 0, &formatted_line); if(formatted_line) { mystring_append(&result, formatted_line); free(formatted_line); formatted_line = 0; } *start_wrapped_url = saved_char; /* now store the hypertext anchor */ append_wrapped_anchor(wrapped_url, &result); /* write the text that's to be linked */ saved_char = *line_end; *line_end = '\0'; mystring_append(&result,start_wrapped_url); *line_end= saved_char; mystring_append(&result, "
"); } /*** ELSE **** The wrapped URL began on an earlier line. **** The URL begins at the start of this line (after we skip **** leading QUOTE_CHARS. The URL extends to the greater **** of line_end or end_wrapped_url ***/ else { /* process all leading QUOTE_CHARS */ for(ptr = line_start; (ptr < line_end) && (*ptr == QUOTE_CHAR); ptr++); if(ptr != line_start) { saved_char = *ptr; *ptr = '\0'; alloc_formatted_line(line_start, 1, 0, &formatted_line); /* add it to the string */ if(formatted_line) { mystring_append(&result, formatted_line); free(formatted_line); } *ptr = saved_char; } /* move line_start to the begining of the url */ line_start = ptr; /* write the html for the url */ append_wrapped_anchor(wrapped_url, &result); /* the url either extends to line_end, or stops at end_wrapped_url */ if(end_wrapped_url < line_end) { saved_char = *(end_wrapped_url + 1); /* since end_wrapped_url points to the last char of url */ *(end_wrapped_url + 1) = '\0'; mystring_append(&result, line_start); /* save the text to be hyperlinked */ *(end_wrapped_url + 1) = saved_char; mystring_append(&result, ""); /* end the hyperlink */ /* save the remainder of the line as formatted */ saved_char = *line_end; *line_end = '\0'; alloc_formatted_line(end_wrapped_url, 1, 0, &formatted_line); if(formatted_line) { mystring_append(&result, formatted_line); free(formatted_line); formatted_line = 0; } *line_end = saved_char; } else /* url extends to the end of the line */ { saved_char = *line_end; *line_end = '\0'; mystring_append(&result, line_start); mystring_append(&result, "
"); *line_end = saved_char; } } formatted_line = shrink_copy(result.buf); add_line_to_list(formatted_line, reply_level); mystring_free(&result); } /* Builds a linked list of formatted lines from original_msg ** assumes *original_msg is a NULL terminated string ending with a '\n' **/ LINE_NODE * build_formatted_line_list(char *original_msg) { /* we'll work on one line at a time ... */ char *line_start; /* points to the first char of the line */ char *line_end; /* points to the '\n' char at the end of the line */ char *wrapped_url; /* holds an http://... address that was wrapped across several lines */ char *start_wrapped_url; /* points to the char in original_msg where the wrapped url starts */ char *end_wrapped_url; /* points to one char beyond the end of the wrapped url in original_msg */ int wrapped_url_line_count; /* the wrapped url extends across this number of lines */ line_head = (LINE_NODE *) 0; /* start with empty line list */ line_start = original_msg; wrapped_url = (char *) 0; wrapped_url_line_count = 0; for(;;) { /* find the end of the next line to process ** Note that a line MUST end in a '\n' **/ for(line_end = line_start; *line_end && (*line_end != '\n'); line_end++); if(!*line_end) { break; /* break from loop when we hit a null terminator */ } /* if we're working on a line that contains a wrapped_url ** then process that line in a special way **/ if(wrapped_url && wrapped_url_line_count) { /* add this line to the list, accounting for the fact that it at least ** partially contains a wrapped url */ add_wrapped_url_line(line_start, line_end, start_wrapped_url, end_wrapped_url, wrapped_url); wrapped_url_line_count--; /* we've got one less wrapped_url line to deal with */ if(!wrapped_url_line_count) /* are we done with all wrapped_url lines ? */ { free(wrapped_url); /* if yes, then free memory */ wrapped_url = (char *) 0; } line_start = line_end + 1; } else /* we don't have a wrapped_url stored */ { /* If this line contains a the start of a wrapped url, ** then store the wrapped_url, count # of lines it spans, ** and record the place in original_msg where the wrapped ** url ends. Don't process this line now. The next ** loop will handle it. */ if((start_wrapped_url = wrapped_url_start(line_start, line_end))) { end_wrapped_url = set_wrapped_url(line_start, line_end, start_wrapped_url, &wrapped_url, &wrapped_url_line_count); } else /*this line does not contain a wrapped_url - handle it normally */ { add_formatted_line(line_start, line_end); line_start = line_end + 1; } } } return line_head; } LINE_NODE * free_formatted_line_list() { LINE_NODE *ptr; while(line_head) { ptr = line_head; line_head = line_head->next; if(ptr -> content) free(ptr->content); free(ptr); } return line_head; } static void set_link_data(const char *name_prefix, char *url, const char *inet_url) { char url_url[(5 * MAX_URL) + 2]; char tmp_url[MAX_URL *3 + 2]; char *ptr; char *new_str; char name[50]; strtrm (url); /* shared_strtrm.c */ strncpy (tmp_url, url, MAX_URL*3 +2); for (ptr = tmp_url; *ptr; ptr++) switch (*ptr) { case '?': *ptr = QMARK_SUB; break; case '&': *ptr = AMP_SUB; break; case '=': *ptr = EQUAL_SUB; break; case '#': *ptr = POUND_SUB; break; default: break; } snprintf (url_url, ( 5 * MAX_URL) + 2, "%s%s", inet_url, tmp_url); snprintf(name,50, "%sinet_url", name_prefix); cs_set_value(name, url_url); /* shared_cs_util.h */ cs_html_escape_string(url, &new_str); /* shared_cs_util.c */ if(new_str) { snprintf(name,50, "%sinet_link", name_prefix); cs_set_value(name, new_str); /* shared_cs_util.h */ free(new_str); } } static char * insert_smiley_faces(char *msg) { int len; char *new_str =0; char *ptr, *ptr2; int i; char img_str[MAX_PATH +1]; char *my_str =0; len = strlen(msg); ptr2 = msg; if(len) { for(i =0; i< MAX_SMILE_CODE; i++) { len = len *2; new_str = (char*)malloc(sizeof(char) * len +1); if(!new_str) cs_critical_error(ERR_MALLOC_FAILED, "new_str"); *new_str = '\0'; do{ ptr = strstr(ptr2, code[i]); if(ptr) { *ptr = '\0'; snprintf(img_str, MAX_PATH +1, "\"\"/", IMAGE_PATH, THEME_DIR_PREFIX, global_theme,icon_img[i]); if((strlen(new_str) + strlen(ptr2) + strlen(img_str) )>= len) { len = strlen(new_str) + strlen(ptr2) + strlen(img_str); new_str = realloc(new_str, len*2 +1); len = len *2; } if(ptr2 != ptr) strncat(new_str, ptr2, strlen(ptr2)); strncat(new_str, img_str, strlen(img_str)); ptr2 = ptr + strlen(code[i]); memset(img_str, 0, MAX_PATH +1); } else { if((strlen(new_str) + strlen(ptr2) )>= len) { len = strlen(new_str) + strlen(ptr2); new_str = realloc(new_str, len*2 +1); len = len *2; } strncat(new_str, ptr2, strlen(ptr2)); } }while(ptr); if(my_str) free(my_str); my_str = (char*)malloc(sizeof(char) * strlen(new_str) +1); memset(my_str, 0, strlen(new_str)+1); strncpy(my_str, new_str, strlen(new_str)); free(new_str); ptr2 = my_str; } } return my_str; } char *is_pair(char *start, const char *bb_code) { char *ptr, *ptr1; ptr = start + strlen(bb_code); if(isspace(*ptr)) return 0; do { ptr1 = strstr(ptr, bb_code); ptr = ptr1 + strlen(bb_code); }while(ptr1 && isspace(*(ptr1 -1))); if(ptr1 && !isspace(*(ptr1 -1))) return ptr1; else return 0; } int count_new_line(char *start, char *end) { int count =0; char *ptr; for(ptr = start; ptr < end; ptr++) { if( *ptr == '\n') count++; } return count; } char *add_bb_tag_between_line(char *start, char *end, int bb_index, int new_line_count) { char *ptr = 0; char *str; str = (char*)malloc(sizeof(char) * ((end - start) + strlen(start_tag_array[bb_index]) * new_line_count + strlen(end_tag_array[bb_index]) * new_line_count +1)); if(!str) cs_critical_error(ERR_MALLOC_FAILED, "add_bb_tag_between_line"); *str = '\0'; for(ptr = start; ptr < end; ptr++) { if(*ptr == '\r' && *(ptr +1) == '\n') { strncat(str, end_tag_array[bb_index], strlen(end_tag_array[bb_index])); strncat(str, ptr, 2); ptr++; if(*(ptr +1) == '>') { ptr = ptr +1; do { strncat(str, ptr, 1); ptr = ptr + 1; }while(*ptr == '>'); ptr = ptr -1; } strncat(str, start_tag_array[bb_index], strlen(start_tag_array[bb_index])); } else if(*ptr == '\n') { strncat(str, end_tag_array[bb_index], strlen(end_tag_array[bb_index])); strncat(str, ptr, 1); if(*(ptr +1) == '>') { ptr = ptr +1; do { strncat(str, ptr, 1); ptr = ptr +1; }while(*ptr == '>'); ptr = ptr -1; } strncat(str, start_tag_array[bb_index], strlen(start_tag_array[bb_index])); } else strncat(str, ptr, 1); } return str; } static char *bbcode2html(char *buffer) { char *new_str, *ptr, *ptr1 =0, *ptr2 =0, *ptr3; int i, len, sub_len, new_line_count =0; char *my_str =0, *add_bb_str =0; len = strlen(buffer); ptr = buffer; if(len) { for(i =0; i=len) { len = sub_len; new_str = realloc(new_str, len * 2 + 1); len = len*2; } if(ptr1 != ptr) strncat(new_str, ptr, strlen(ptr)); strncat(new_str, start_tag_array[i], strlen(start_tag_array[i])); if(new_line_count) { add_bb_str = add_bb_tag_between_line(ptr3, ptr2, i, new_line_count); if(add_bb_str) { strncat(new_str, add_bb_str, strlen(add_bb_str)); free(add_bb_str); } } else strncat(new_str, ptr3, (ptr2 -ptr3)); strncat(new_str, end_tag_array[i], strlen(end_tag_array[i])); ptr = ptr2 + strlen(bb_code_array[i]); } else { sub_len = strlen(ptr) + strlen(new_str); if(sub_len >= len) { len = sub_len; new_str = realloc(new_str, len*2 +1); len = len*2; } strncat(new_str, ptr, strlen(ptr)); } }while(ptr1 && ptr2); if(my_str) free(my_str); my_str = (char*) malloc(sizeof(char) * strlen(new_str) +1); memset(my_str, 0, strlen(new_str)+1); strncpy(my_str, new_str, strlen(new_str)); free(new_str); ptr = my_str; } } return my_str; } /** Some will paste from MS Word into the textarea for messages. *** Along with plain ascii, comes lots of junk, primarily 'smart quotes' *** This function attempts to find and destroy these smart quote characters *** *** used http://www.cs.tut.fi/~jkorpela/www/windows-chars.html as a reference **/ void remove_smart_quotes(char *buffer) { char *ptr; for(ptr = buffer; *ptr; ptr++) { switch((unsigned char) *ptr) { case 130: *ptr = '\''; break; /* basline single quote */ case 132: *ptr = '"'; break; /* baseline double quote */ case 133: *ptr = '.'; break; /* this is a horizontal ellipsis - replace with single period */ case 145: case 146: *ptr = '\''; break; /* left, and right single quote */ case 147: case 148: *ptr = '"'; break; /* left, and right double quotes */ case 149: *ptr = '*'; break; /* bullet */ case 150: case 151: *ptr = '-'; break; /* endash, emdash */ /* replace sequence of 226 128 147 with - ** This is an MS Word special symbol for a dash */ case 226: if( (*(ptr + 1) == -128) && (*(ptr + 2) == -109 ) ) { *ptr = ' '; ptr++; *ptr = '-'; ptr++; *ptr = ' '; } break; default: break; } } } void set_msg_body_data (const char *fullpath, const char *name_prefix, const char *inet_url) { FILE *fp; char *buffer = 0; /* stores the entire content of the msg file */ struct stat stat_buf; /* used for fstat() call */ char *ptr; char *buffer_icon = 0; char *buffer_bb = 0; char *url, one_char; int len, i, big = MAX_URL; LINE_NODE *l_head; /* LINE_NODE is in shared_msg_line.h */ LINE_NODE *l_ptr; int line; char hdf_content_name[50]; char hdf_reply_level_name[50]; fp = fopen (fullpath, "r"); if (!fp) cs_critical_error (ERR_FOPEN_READ_FAILED, fullpath); /* shared_cs_util.c */ if(fstat(fileno(fp),&stat_buf)) cs_critical_error(ERR_STAT_FAILED, fullpath); /* shared_cs_util.c */ if(*inet_url) { url = (char*) malloc(sizeof(char) * (MAX_URL+1)); if(!url) cs_critical_error(ERR_MALLOC_FAILED, "url"); *url = '\0'; i = 0; while((one_char = fgetc(fp)) != '\n') { len = strlen(url); if(len >= big) { url = realloc(url, (big * 2) + 1); big = big * 2; } url[i] = one_char; url[i + 1] = '\0'; i++; } stat_buf.st_size = stat_buf.st_size - strlen(url) - 1; /* since set_link_data() might change url */ set_link_data(name_prefix,url, inet_url); free(url); } /* handle empty message */ if(!stat_buf.st_size) { fclose(fp); return; } buffer = (char *) malloc((stat_buf.st_size + 2) * sizeof(char)); if(!buffer) cs_critical_error(ERR_MALLOC_FAILED, "set_msg_body_data()"); if(fread(buffer, stat_buf.st_size, 1, fp) != 1) cs_critical_error(ERR_FREAD_FAILED, fullpath); fclose(fp); ptr = buffer+stat_buf.st_size - 1; if(*ptr != '\n') { ptr++; *ptr = '\n'; } *(ptr + 1) = '\0'; remove_smart_quotes(buffer); buffer_icon = insert_smiley_faces(buffer); if(buffer) free(buffer); buffer_bb = bbcode2html(buffer_icon); if(buffer_icon) free(buffer_icon); l_head = build_formatted_line_list(buffer_bb); for(l_ptr = l_head, line= 0; l_ptr; l_ptr=l_ptr->next, line++) { snprintf(hdf_content_name, 50, "%sline.%d.content", name_prefix, line); cs_set_value(hdf_content_name,l_ptr->content); /* shared_cs_util.h */ if(l_ptr->reply_level) { snprintf(hdf_reply_level_name, 50, "%sline.%d.reply_level", name_prefix,line); cs_set_int_value(hdf_reply_level_name, l_ptr->reply_level); /* shared_cs_util.h */ } } l_head=free_formatted_line_list(); if(buffer_bb) free(buffer_bb); }
"};
const char *end_tag_array[MAX_BB_CODE] ={"", "", "", "", "", "", "