aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/basetypes/MCString.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/basetypes/MCString.cc')
-rw-r--r--src/core/basetypes/MCString.cc1390
1 files changed, 695 insertions, 695 deletions
diff --git a/src/core/basetypes/MCString.cc b/src/core/basetypes/MCString.cc
index d8863f44..d99931b6 100644
--- a/src/core/basetypes/MCString.cc
+++ b/src/core/basetypes/MCString.cc
@@ -38,48 +38,48 @@ void mailcore::setICUDataDirectory(String * directory)
static inline int to_be_quoted(const char * word, size_t size, int subject)
{
- int do_quote;
- const char * cur;
- size_t i;
-
- do_quote = 0;
- cur = word;
- for(i = 0 ; i < size ; i ++) {
- if (* cur == '=')
- do_quote = 1;
-
- if (!subject) {
- switch (* cur) {
- case ',':
- case ':':
- case '!':
- case '"':
- case '#':
- case '$':
- case '@':
- case '[':
- case '\\':
- case ']':
- case '^':
- case '`':
- case '{':
- case '|':
- case '}':
- case '~':
- case '=':
- case '?':
- case '_':
- do_quote = 1;
- break;
- }
- }
- if (((unsigned char) * cur) >= 128)
- do_quote = 1;
-
- cur ++;
- }
-
- return do_quote;
+ int do_quote;
+ const char * cur;
+ size_t i;
+
+ do_quote = 0;
+ cur = word;
+ for(i = 0 ; i < size ; i ++) {
+ if (* cur == '=')
+ do_quote = 1;
+
+ if (!subject) {
+ switch (* cur) {
+ case ',':
+ case ':':
+ case '!':
+ case '"':
+ case '#':
+ case '$':
+ case '@':
+ case '[':
+ case '\\':
+ case ']':
+ case '^':
+ case '`':
+ case '{':
+ case '|':
+ case '}':
+ case '~':
+ case '=':
+ case '?':
+ case '_':
+ do_quote = 1;
+ break;
+ }
+ }
+ if (((unsigned char) * cur) >= 128)
+ do_quote = 1;
+
+ cur ++;
+ }
+
+ return do_quote;
}
#define MAX_IMF_LINE 72
@@ -87,92 +87,92 @@ static inline int to_be_quoted(const char * word, size_t size, int subject)
static inline void quote_word(const char * display_charset,
MMAPString * mmapstr, const char * word, size_t size)
{
- const char * cur;
- size_t i;
- char hex[4];
- int col;
-
- mmap_string_append(mmapstr, "=?");
- mmap_string_append(mmapstr, display_charset);
- mmap_string_append(mmapstr, "?Q?");
-
- col = (int) mmapstr->len;
-
- cur = word;
- for(i = 0 ; i < size ; i ++) {
- int do_quote_char;
-
- do_quote_char = 0;
- switch (* cur) {
- case ',':
- case ':':
- case '!':
- case '"':
- case '#':
- case '$':
- case '@':
- case '[':
- case '\\':
- case ']':
- case '^':
- case '`':
- case '{':
- case '|':
- case '}':
- case '~':
- case '=':
- case '?':
- case '_':
- do_quote_char = 1;
- break;
-
- default:
- if (((unsigned char) * cur) >= 128)
- do_quote_char = 1;
- break;
- }
-
- if (do_quote_char) {
- snprintf(hex, 4, "=%2.2X", (unsigned char) * cur);
- mmap_string_append(mmapstr, hex);
- col += 3;
- }
- else {
- if (* cur == ' ') {
- mmap_string_append_c(mmapstr, '_');
- }
- else {
- mmap_string_append_c(mmapstr, * cur);
- }
- col += 3;
- }
- cur ++;
- }
-
- mmap_string_append(mmapstr, "?=");
+ const char * cur;
+ size_t i;
+ char hex[4];
+ int col;
+
+ mmap_string_append(mmapstr, "=?");
+ mmap_string_append(mmapstr, display_charset);
+ mmap_string_append(mmapstr, "?Q?");
+
+ col = (int) mmapstr->len;
+
+ cur = word;
+ for(i = 0 ; i < size ; i ++) {
+ int do_quote_char;
+
+ do_quote_char = 0;
+ switch (* cur) {
+ case ',':
+ case ':':
+ case '!':
+ case '"':
+ case '#':
+ case '$':
+ case '@':
+ case '[':
+ case '\\':
+ case ']':
+ case '^':
+ case '`':
+ case '{':
+ case '|':
+ case '}':
+ case '~':
+ case '=':
+ case '?':
+ case '_':
+ do_quote_char = 1;
+ break;
+
+ default:
+ if (((unsigned char) * cur) >= 128)
+ do_quote_char = 1;
+ break;
+ }
+
+ if (do_quote_char) {
+ snprintf(hex, 4, "=%2.2X", (unsigned char) * cur);
+ mmap_string_append(mmapstr, hex);
+ col += 3;
+ }
+ else {
+ if (* cur == ' ') {
+ mmap_string_append_c(mmapstr, '_');
+ }
+ else {
+ mmap_string_append_c(mmapstr, * cur);
+ }
+ col += 3;
+ }
+ cur ++;
+ }
+
+ mmap_string_append(mmapstr, "?=");
}
static inline void get_word(const char * begin, const char ** pend, int subject, int * pto_be_quoted)
{
- const char * cur;
-
- cur = begin;
-
- while ((* cur != ' ') && (* cur != '\t') && (* cur != '\0')) {
- cur ++;
- }
- while (((* cur == ' ') || (* cur == '\t')) && (* cur != '\0')) {
- cur ++;
- }
-
- if (cur - begin +
- 1 /* minimum column of string in a
+ const char * cur;
+
+ cur = begin;
+
+ while ((* cur != ' ') && (* cur != '\t') && (* cur != '\0')) {
+ cur ++;
+ }
+ while (((* cur == ' ') || (* cur == '\t')) && (* cur != '\0')) {
+ cur ++;
+ }
+
+ if (cur - begin +
+ 1 /* minimum column of string in a
folded header */ > MAX_IMF_LINE)
- * pto_be_quoted = 1;
- else
- * pto_be_quoted = to_be_quoted(begin, cur - begin, subject);
-
- * pend = cur;
+ * pto_be_quoted = 1;
+ else
+ * pto_be_quoted = to_be_quoted(begin, cur - begin, subject);
+
+ * pend = cur;
}
static char * etpan_make_full_quoted_printable(const char * display_charset,
@@ -193,266 +193,266 @@ static char * etpan_make_full_quoted_printable(const char * display_charset,
else {
str = strdup(phrase);
}
-
- return str;
+
+ return str;
}
static char * etpan_make_quoted_printable(const char * display_charset,
const char * phrase, int subject)
{
- char * str;
- const char * cur;
- MMAPString * mmapstr;
-
- mmapstr = mmap_string_new("");
-
- cur = phrase;
- while (* cur != '\0') {
- const char * begin;
- const char * end;
- int do_quote;
- int quote_words;
-
- begin = cur;
- end = begin;
- quote_words = 0;
- do_quote = 1;
-
- while (* cur != '\0') {
- get_word(cur, &cur, subject, &do_quote);
- if (do_quote) {
- quote_words = 1;
- end = cur;
- }
- else
- break;
- if (* cur != '\0')
- cur ++;
- }
-
- if (quote_words) {
- quote_word(display_charset, mmapstr, begin, end - begin);
-
- if ((* end == ' ') || (* end == '\t')) {
- mmap_string_append_c(mmapstr, * end);
- end ++;
- }
-
- if (* end != '\0') {
- mmap_string_append_len(mmapstr, end, cur - end);
- }
- }
- else {
- mmap_string_append_len(mmapstr, begin, cur - begin);
- }
-
- if ((* cur == ' ') || (* cur == '\t')) {
- mmap_string_append_c(mmapstr, * cur);
- cur ++;
- }
- }
-
- str = strdup(mmapstr->str);
- mmap_string_free(mmapstr);
-
- return str;
+ char * str;
+ const char * cur;
+ MMAPString * mmapstr;
+
+ mmapstr = mmap_string_new("");
+
+ cur = phrase;
+ while (* cur != '\0') {
+ const char * begin;
+ const char * end;
+ int do_quote;
+ int quote_words;
+
+ begin = cur;
+ end = begin;
+ quote_words = 0;
+ do_quote = 1;
+
+ while (* cur != '\0') {
+ get_word(cur, &cur, subject, &do_quote);
+ if (do_quote) {
+ quote_words = 1;
+ end = cur;
+ }
+ else
+ break;
+ if (* cur != '\0')
+ cur ++;
+ }
+
+ if (quote_words) {
+ quote_word(display_charset, mmapstr, begin, end - begin);
+
+ if ((* end == ' ') || (* end == '\t')) {
+ mmap_string_append_c(mmapstr, * end);
+ end ++;
+ }
+
+ if (* end != '\0') {
+ mmap_string_append_len(mmapstr, end, cur - end);
+ }
+ }
+ else {
+ mmap_string_append_len(mmapstr, begin, cur - begin);
+ }
+
+ if ((* cur == ' ') || (* cur == '\t')) {
+ mmap_string_append_c(mmapstr, * cur);
+ cur ++;
+ }
+ }
+
+ str = strdup(mmapstr->str);
+ mmap_string_free(mmapstr);
+
+ return str;
}
#pragma mark extract subject
static inline int skip_subj_blob(char * subj, size_t * begin,
- size_t length, int keep_bracket)
+ size_t length, int keep_bracket)
{
if (keep_bracket)
return 0;
- /* subj-blob = "[" *BLOBCHAR "]" *WSP */
- size_t cur_token;
-
- cur_token = * begin;
-
- if (subj[cur_token] != '[')
- return 0;
-
- cur_token ++;
-
- while (1) {
- if (cur_token >= length)
- return 0;
-
- if (subj[cur_token] == '[')
- return 0;
-
- if (subj[cur_token] == ']')
- break;
-
- cur_token ++;
- }
-
- cur_token ++;
-
- while (1) {
- if (cur_token >= length)
- break;
-
- if (subj[cur_token] != ' ')
- break;
-
- cur_token ++;
- }
-
- * begin = cur_token;
-
- return 1;
+ /* subj-blob = "[" *BLOBCHAR "]" *WSP */
+ size_t cur_token;
+
+ cur_token = * begin;
+
+ if (subj[cur_token] != '[')
+ return 0;
+
+ cur_token ++;
+
+ while (1) {
+ if (cur_token >= length)
+ return 0;
+
+ if (subj[cur_token] == '[')
+ return 0;
+
+ if (subj[cur_token] == ']')
+ break;
+
+ cur_token ++;
+ }
+
+ cur_token ++;
+
+ while (1) {
+ if (cur_token >= length)
+ break;
+
+ if (subj[cur_token] != ' ')
+ break;
+
+ cur_token ++;
+ }
+
+ * begin = cur_token;
+
+ return 1;
}
static inline int skip_subj_refwd(char * subj, size_t * begin,
- size_t length, int keep_bracket)
+ size_t length, int keep_bracket)
{
- /* subj-refwd = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":" */
- size_t cur_token;
- int prefix;
+ /* subj-refwd = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":" */
+ size_t cur_token;
+ int prefix;
int has_suffix;
-
- cur_token = * begin;
- prefix = 0;
+
+ cur_token = * begin;
+ prefix = 0;
+ if (!prefix) {
+ if (length - cur_token >= 18) {
+ if (strncasecmp(subj + cur_token, "Переслать", 18) == 0) {
+ cur_token += 18;
+ prefix = 1;
+ }
+ }
+ }
+ if (!prefix) {
+ if (length - cur_token >= 10) {
+ if (strncasecmp(subj + cur_token, "Ответ", 10) == 0) {
+ cur_token += 10;
+ prefix = 1;
+ }
+ }
+ }
+ if (!prefix) {
+ if (length - cur_token >= 7) {
+ if (strncasecmp(subj + cur_token, "Antwort", 7) == 0) {
+ cur_token += 7;
+ prefix = 1;
+ }
+ }
+ }
+ if (!prefix) {
+ if (length - cur_token >= 6) {
+ if (strncasecmp(subj + cur_token, "回复", 6) == 0) {
+ cur_token += 6;
+ prefix = 1;
+ }
+ else if (strncasecmp(subj + cur_token, "转发", 6) == 0) {
+ cur_token += 6;
+ prefix = 1;
+ }
+ }
+ }
+ if (!prefix) {
+ if (length - cur_token >= 5) {
+ // é is 2 chars in utf-8
+ if (strncasecmp(subj + cur_token, "réf.", 5) == 0) {
+ cur_token += 5;
+ prefix = 1;
+ }
+ else if (strncasecmp(subj + cur_token, "rép.", 5) == 0) {
+ cur_token += 5;
+ prefix = 1;
+ }
+ else if (strncasecmp(subj + cur_token, "trans", 5) == 0) {
+ cur_token += 5;
+ prefix = 1;
+ }
+ }
+ }
if (!prefix) {
- if (length - cur_token >= 18) {
- if (strncasecmp(subj + cur_token, "Переслать", 18) == 0) {
- cur_token += 18;
- prefix = 1;
- }
- }
+ if (length - cur_token >= 4) {
+ if (strncasecmp(subj + cur_token, "antw", 4) == 0) {
+ cur_token += 4;
+ prefix = 1;
+ }
+ }
}
if (!prefix) {
- if (length - cur_token >= 10) {
- if (strncasecmp(subj + cur_token, "Ответ", 10) == 0) {
- cur_token += 10;
- prefix = 1;
- }
- }
- }
- if (!prefix) {
- if (length - cur_token >= 7) {
- if (strncasecmp(subj + cur_token, "Antwort", 7) == 0) {
- cur_token += 7;
- prefix = 1;
- }
- }
- }
+ if (length - cur_token >= 3) {
+ if (strncasecmp(subj + cur_token, "fwd", 3) == 0) {
+ cur_token += 3;
+ prefix = 1;
+ }
+ else if (strncasecmp(subj + cur_token, "ogg", 3) == 0) {
+ cur_token += 3;
+ prefix = 1;
+ }
+ else if (strncasecmp(subj + cur_token, "odp", 3) == 0) {
+ cur_token += 3;
+ prefix = 1;
+ }
+ else if (strncasecmp(subj + cur_token, "res", 3) == 0) {
+ cur_token += 3;
+ prefix = 1;
+ }
+ else if (strncasecmp(subj + cur_token, "end", 3) == 0) {
+ cur_token += 3;
+ prefix = 1;
+ }
+ }
+ }
if (!prefix) {
- if (length - cur_token >= 6) {
- if (strncasecmp(subj + cur_token, "回复", 6) == 0) {
- cur_token += 6;
- prefix = 1;
- }
- else if (strncasecmp(subj + cur_token, "转发", 6) == 0) {
- cur_token += 6;
- prefix = 1;
- }
- }
- }
- if (!prefix) {
- if (length - cur_token >= 5) {
- // é is 2 chars in utf-8
- if (strncasecmp(subj + cur_token, "réf.", 5) == 0) {
- cur_token += 5;
- prefix = 1;
- }
- else if (strncasecmp(subj + cur_token, "rép.", 5) == 0) {
- cur_token += 5;
- prefix = 1;
- }
- else if (strncasecmp(subj + cur_token, "trans", 5) == 0) {
- cur_token += 5;
- prefix = 1;
- }
- }
- }
- if (!prefix) {
- if (length - cur_token >= 4) {
- if (strncasecmp(subj + cur_token, "antw", 4) == 0) {
- cur_token += 4;
- prefix = 1;
- }
- }
- }
- if (!prefix) {
- if (length - cur_token >= 3) {
- if (strncasecmp(subj + cur_token, "fwd", 3) == 0) {
- cur_token += 3;
- prefix = 1;
- }
- else if (strncasecmp(subj + cur_token, "ogg", 3) == 0) {
- cur_token += 3;
- prefix = 1;
- }
- else if (strncasecmp(subj + cur_token, "odp", 3) == 0) {
- cur_token += 3;
- prefix = 1;
- }
- else if (strncasecmp(subj + cur_token, "res", 3) == 0) {
- cur_token += 3;
- prefix = 1;
- }
- else if (strncasecmp(subj + cur_token, "end", 3) == 0) {
- cur_token += 3;
- prefix = 1;
- }
- }
- }
- if (!prefix) {
- if (length - cur_token >= 2) {
- if (strncasecmp(subj + cur_token, "fw", 2) == 0) {
- cur_token += 2;
- prefix = 1;
- }
- else if (strncasecmp(subj + cur_token, "re", 2) == 0) {
- cur_token += 2;
- prefix = 1;
- }
- else if (strncasecmp(subj + cur_token, "tr", 2) == 0) {
- cur_token += 2;
- prefix = 1;
- }
- else if (strncasecmp(subj + cur_token, "aw", 2) == 0) {
- cur_token += 2;
- prefix = 1;
- }
- else if (strncasecmp(subj + cur_token, "sv", 2) == 0) {
- cur_token += 2;
- prefix = 1;
- }
- else if (strncasecmp(subj + cur_token, "rv", 2) == 0) {
- cur_token += 2;
- prefix = 1;
- }
- }
- }
- if (!prefix) {
- if (length - cur_token >= 1) {
- if (strncasecmp(subj + cur_token, "r", 1) == 0) {
- cur_token += 1;
- prefix = 1;
- }
- }
- }
-
- if (!prefix)
- return 0;
-
- while (1) {
- if (cur_token >= length)
- break;
-
- if (subj[cur_token] != ' ')
- break;
-
- cur_token ++;
- }
-
- skip_subj_blob(subj, &cur_token, length, keep_bracket);
-
+ if (length - cur_token >= 2) {
+ if (strncasecmp(subj + cur_token, "fw", 2) == 0) {
+ cur_token += 2;
+ prefix = 1;
+ }
+ else if (strncasecmp(subj + cur_token, "re", 2) == 0) {
+ cur_token += 2;
+ prefix = 1;
+ }
+ else if (strncasecmp(subj + cur_token, "tr", 2) == 0) {
+ cur_token += 2;
+ prefix = 1;
+ }
+ else if (strncasecmp(subj + cur_token, "aw", 2) == 0) {
+ cur_token += 2;
+ prefix = 1;
+ }
+ else if (strncasecmp(subj + cur_token, "sv", 2) == 0) {
+ cur_token += 2;
+ prefix = 1;
+ }
+ else if (strncasecmp(subj + cur_token, "rv", 2) == 0) {
+ cur_token += 2;
+ prefix = 1;
+ }
+ }
+ }
+ if (!prefix) {
+ if (length - cur_token >= 1) {
+ if (strncasecmp(subj + cur_token, "r", 1) == 0) {
+ cur_token += 1;
+ prefix = 1;
+ }
+ }
+ }
+
+ if (!prefix)
+ return 0;
+
+ while (1) {
+ if (cur_token >= length)
+ break;
+
+ if (subj[cur_token] != ' ')
+ break;
+
+ cur_token ++;
+ }
+
+ skip_subj_blob(subj, &cur_token, length, keep_bracket);
+
has_suffix = 0;
if (!has_suffix) {
@@ -465,7 +465,7 @@ static inline int skip_subj_refwd(char * subj, size_t * begin,
}
if (!has_suffix) {
- if (cur_token < length) {
+ if (cur_token < length) {
if (subj[cur_token] == ':') {
cur_token ++;
has_suffix = 1;
@@ -477,212 +477,212 @@ static inline int skip_subj_refwd(char * subj, size_t * begin,
return 0;
}
- * begin = cur_token;
-
- return 1;
+ * begin = cur_token;
+
+ return 1;
}
static inline int skip_subj_leader(char * subj, size_t * begin,
- size_t length, int keep_bracket)
-{
- size_t cur_token;
-
- cur_token = * begin;
-
- /* subj-leader = (*subj-blob subj-refwd) / WSP */
-
- if (subj[cur_token] == ' ') {
- cur_token ++;
- }
- else {
- while (cur_token < length) {
- if (!skip_subj_blob(subj, &cur_token, length, keep_bracket))
- break;
- }
- if (!skip_subj_refwd(subj, &cur_token, length, keep_bracket))
- return 0;
- }
-
- * begin = cur_token;
-
- return 1;
+ size_t length, int keep_bracket)
+{
+ size_t cur_token;
+
+ cur_token = * begin;
+
+ /* subj-leader = (*subj-blob subj-refwd) / WSP */
+
+ if (subj[cur_token] == ' ') {
+ cur_token ++;
+ }
+ else {
+ while (cur_token < length) {
+ if (!skip_subj_blob(subj, &cur_token, length, keep_bracket))
+ break;
+ }
+ if (!skip_subj_refwd(subj, &cur_token, length, keep_bracket))
+ return 0;
+ }
+
+ * begin = cur_token;
+
+ return 1;
}
static char * extract_subject(char * str, int keep_bracket)
{
- char * subj;
- char * cur;
- char * write_pos;
- size_t len;
- size_t begin;
- int do_repeat_5;
- int do_repeat_6;
-
- /*
- (1) Convert any RFC 2047 encoded-words in the subject to
- UTF-8.
- We work on UTF-8 string -- DVH
- */
-
- subj = strdup(str);
- if (subj == NULL)
- return NULL;
-
- len = strlen(subj);
-
- /*
- Convert all tabs and continuations to space.
- Convert all multiple spaces to a single space.
- */
-
- cur = subj;
- write_pos = subj;
- while (* cur != '\0') {
- int cont;
-
- switch (* cur) {
- case '\t':
- case '\r':
- case '\n':
- cont = 1;
-
- cur ++;
- while (* cur && cont) {
- switch (* cur) {
- case '\t':
- case '\r':
- case '\n':
- cont = 1;
- break;
- default:
- cont = 0;
- break;
- }
- cur ++;
- }
-
- * write_pos = ' ';
- write_pos ++;
-
- break;
-
- default:
- * write_pos = * cur;
- write_pos ++;
-
- cur ++;
-
- break;
- }
- }
- * write_pos = '\0';
-
- begin = 0;
-
- do {
- do_repeat_6 = 0;
-
- /*
- (2) Remove all trailing text of the subject that matches
- the subj-trailer ABNF, repeat until no more matches are
- possible.
- */
-
- while (len > 0) {
- /* subj-trailer = "(fwd)" / WSP */
- if (subj[len - 1] == ' ') {
- subj[len - 1] = '\0';
- len --;
- }
- else {
- if (len < 5)
- break;
-
- if (strncasecmp(subj + len - 5, "(fwd)", 5) != 0)
- break;
-
- subj[len - 5] = '\0';
- len -= 5;
- }
- }
-
- do {
- size_t saved_begin;
-
- do_repeat_5 = 0;
-
- /*
- (3) Remove all prefix text of the subject that matches the
- subj-leader ABNF.
- */
-
- if (skip_subj_leader(subj, &begin, len, keep_bracket))
- do_repeat_5 = 1;
-
- /*
- (4) If there is prefix text of the subject that matches the
- subj-blob ABNF, and removing that prefix leaves a non-empty
- subj-base, then remove the prefix text.
- */
-
- saved_begin = begin;
- if (skip_subj_blob(subj, &begin, len, keep_bracket)) {
- if (begin == len) {
- /* this will leave a empty subject base */
- begin = saved_begin;
- }
- else
- do_repeat_5 = 1;
- }
-
- /*
- (5) Repeat (3) and (4) until no matches remain.
- Note: it is possible to defer step (2) until step (6),
- but this requires checking for subj-trailer in step (4).
- */
-
- }
- while (do_repeat_5);
-
- /*
- (6) If the resulting text begins with the subj-fwd-hdr ABNF
- and ends with the subj-fwd-trl ABNF, remove the
- subj-fwd-hdr and subj-fwd-trl and repeat from step (2).
- */
-
- if (len >= 5) {
- if (strncasecmp(subj + begin, "[fwd:", 5) == 0) {
- begin += 5;
-
- if (subj[len - 1] == ']') {
- subj[len - 1] = '\0';
- len --;
- do_repeat_6 = 1;
- }
- }
- }
-
- }
- while (do_repeat_6);
-
- /*
- (7) The resulting text is the "base subject" used in
- threading.
- */
-
- /* convert to upper case */
-
- cur = subj + begin;
- write_pos = subj;
-
- while (* cur != '\0') {
- * write_pos = * cur;
- cur ++;
- write_pos ++;
- }
- * write_pos = '\0';
-
- return subj;
+ char * subj;
+ char * cur;
+ char * write_pos;
+ size_t len;
+ size_t begin;
+ int do_repeat_5;
+ int do_repeat_6;
+
+ /*
+ (1) Convert any RFC 2047 encoded-words in the subject to
+ UTF-8.
+ We work on UTF-8 string -- DVH
+ */
+
+ subj = strdup(str);
+ if (subj == NULL)
+ return NULL;
+
+ len = strlen(subj);
+
+ /*
+ Convert all tabs and continuations to space.
+ Convert all multiple spaces to a single space.
+ */
+
+ cur = subj;
+ write_pos = subj;
+ while (* cur != '\0') {
+ int cont;
+
+ switch (* cur) {
+ case '\t':
+ case '\r':
+ case '\n':
+ cont = 1;
+
+ cur ++;
+ while (* cur && cont) {
+ switch (* cur) {
+ case '\t':
+ case '\r':
+ case '\n':
+ cont = 1;
+ break;
+ default:
+ cont = 0;
+ break;
+ }
+ cur ++;
+ }
+
+ * write_pos = ' ';
+ write_pos ++;
+
+ break;
+
+ default:
+ * write_pos = * cur;
+ write_pos ++;
+
+ cur ++;
+
+ break;
+ }
+ }
+ * write_pos = '\0';
+
+ begin = 0;
+
+ do {
+ do_repeat_6 = 0;
+
+ /*
+ (2) Remove all trailing text of the subject that matches
+ the subj-trailer ABNF, repeat until no more matches are
+ possible.
+ */
+
+ while (len > 0) {
+ /* subj-trailer = "(fwd)" / WSP */
+ if (subj[len - 1] == ' ') {
+ subj[len - 1] = '\0';
+ len --;
+ }
+ else {
+ if (len < 5)
+ break;
+
+ if (strncasecmp(subj + len - 5, "(fwd)", 5) != 0)
+ break;
+
+ subj[len - 5] = '\0';
+ len -= 5;
+ }
+ }
+
+ do {
+ size_t saved_begin;
+
+ do_repeat_5 = 0;
+
+ /*
+ (3) Remove all prefix text of the subject that matches the
+ subj-leader ABNF.
+ */
+
+ if (skip_subj_leader(subj, &begin, len, keep_bracket))
+ do_repeat_5 = 1;
+
+ /*
+ (4) If there is prefix text of the subject that matches the
+ subj-blob ABNF, and removing that prefix leaves a non-empty
+ subj-base, then remove the prefix text.
+ */
+
+ saved_begin = begin;
+ if (skip_subj_blob(subj, &begin, len, keep_bracket)) {
+ if (begin == len) {
+ /* this will leave a empty subject base */
+ begin = saved_begin;
+ }
+ else
+ do_repeat_5 = 1;
+ }
+
+ /*
+ (5) Repeat (3) and (4) until no matches remain.
+ Note: it is possible to defer step (2) until step (6),
+ but this requires checking for subj-trailer in step (4).
+ */
+
+ }
+ while (do_repeat_5);
+
+ /*
+ (6) If the resulting text begins with the subj-fwd-hdr ABNF
+ and ends with the subj-fwd-trl ABNF, remove the
+ subj-fwd-hdr and subj-fwd-trl and repeat from step (2).
+ */
+
+ if (len >= 5) {
+ if (strncasecmp(subj + begin, "[fwd:", 5) == 0) {
+ begin += 5;
+
+ if (subj[len - 1] == ']') {
+ subj[len - 1] = '\0';
+ len --;
+ do_repeat_6 = 1;
+ }
+ }
+ }
+
+ }
+ while (do_repeat_6);
+
+ /*
+ (7) The resulting text is the "base subject" used in
+ threading.
+ */
+
+ /* convert to upper case */
+
+ cur = subj + begin;
+ write_pos = subj;
+
+ while (* cur != '\0') {
+ * write_pos = * cur;
+ cur ++;
+ write_pos ++;
+ }
+ * write_pos = '\0';
+
+ return subj;
}
String::String(const UChar * unicodeChars)
@@ -768,12 +768,12 @@ String * String::stringWithData(Data * data, const char * charset)
String * String::stringWithUTF8Format(const char * format, ...)
{
- va_list argp;
-
- va_start(argp, format);
+ va_list argp;
+
+ va_start(argp, format);
String * result = stringWithVUTF8Format(format, argp);
- va_end(argp);
-
+ va_end(argp);
+
return result;
}
@@ -819,12 +819,12 @@ void String::appendString(String * otherString)
void String::appendUTF8Format(const char * format, ...)
{
- va_list argp;
-
- va_start(argp, format);
+ va_list argp;
+
+ va_start(argp, format);
String * otherString = stringWithVUTF8Format(format, argp);
- va_end(argp);
-
+ va_end(argp);
+
this->appendString(otherString);
}
@@ -910,12 +910,12 @@ String * String::stringByAppendingString(String * otherString)
String * String::stringByAppendingUTF8Format(const char * format, ...)
{
- va_list argp;
-
- va_start(argp, format);
+ va_list argp;
+
+ va_start(argp, format);
String * otherString = stringWithVUTF8Format(format, argp);
- va_end(argp);
-
+ va_end(argp);
+
return this->stringByAppendingString(otherString);
}
@@ -990,7 +990,7 @@ String * String::stringByDecodingMIMEHeaderValue(const char * phrase)
{
size_t cur_token;
char * decoded;
- String * result;
+ String * result;
bool hasEncoding;
if (phrase == NULL)
@@ -1027,44 +1027,44 @@ String * String::stringByDecodingMIMEHeaderValue(const char * phrase)
}
free(decoded);
-
- return result;
+
+ return result;
}
Data * String::encodedAddressDisplayNameValue()
{
- char * str;
- Data * result;
-
+ char * str;
+ Data * result;
+
str = etpan_make_full_quoted_printable(DEFAULT_DISPLAY_CHARSET, UTF8Characters());
result = Data::dataWithBytes(str, (unsigned int) strlen(str) + 1);
- free(str);
+ free(str);
return result;
}
Data * String::encodedMIMEHeaderValue()
{
- char * str;
- Data * result;
-
- str = etpan_make_quoted_printable(DEFAULT_DISPLAY_CHARSET, UTF8Characters(), 0);
+ char * str;
+ Data * result;
+
+ str = etpan_make_quoted_printable(DEFAULT_DISPLAY_CHARSET, UTF8Characters(), 0);
result = Data::dataWithBytes(str, (unsigned int) strlen(str) + 1);
- free(str);
-
- return result;
+ free(str);
+
+ return result;
}
Data * String::encodedMIMEHeaderValueForSubject()
{
- char * str;
- Data * result;
-
- str = etpan_make_quoted_printable(DEFAULT_DISPLAY_CHARSET, UTF8Characters(), 1);
- result = Data::dataWithBytes(str, (unsigned int) strlen(str) + 1);
- free(str);
-
- return result;
+ char * str;
+ Data * result;
+
+ str = etpan_make_quoted_printable(DEFAULT_DISPLAY_CHARSET, UTF8Characters(), 1);
+ result = Data::dataWithBytes(str, (unsigned int) strlen(str) + 1);
+ free(str);
+
+ return result;
}
int String::compareWithCaseSensitive(String * otherString, bool caseSensitive)
@@ -1182,14 +1182,14 @@ String * String::extractedSubject()
String * String::extractedSubjectAndKeepBracket(bool keepBracket)
{
- char * result;
- String * str;
-
- result = extract_subject((char *) UTF8Characters(), keepBracket);
- str = String::stringWithUTF8Characters(result);
- free(result);
-
- return str;
+ char * result;
+ String * str;
+
+ result = extract_subject((char *) UTF8Characters(), keepBracket);
+ str = String::stringWithUTF8Characters(result);
+ free(result);
+
+ return str;
}
String * String::uuidString()
@@ -1248,7 +1248,7 @@ unsigned int String::replaceOccurrencesOfString(String * occurrence, String * re
}
// copy remaining
if(p) {
- u_strcpy(dest_p, p);
+ u_strcpy(dest_p, p);
}
free(mUnicodeChars);
@@ -1292,11 +1292,11 @@ int String::locationOfString(String * occurrence)
#pragma mark strip HTML
struct parserState {
- int level;
- int enabled;
- int disabledLevel;
- String * result;
- int logEnabled;
+ int level;
+ int enabled;
+ int disabledLevel;
+ String * result;
+ int logEnabled;
int hasQuote;
int quoteLevel;
bool hasText;
@@ -1314,19 +1314,19 @@ static void charactersParsed(void * context,
const xmlChar * ch, int len)
/*" Callback function for stringByStrippingHTML. "*/
{
- struct parserState * state;
-
- state = (struct parserState *) context;
- String * result = state->result;
-
- if (!state->enabled) {
- return;
- }
-
- if (state->logEnabled) {
- MCLog("text %s", ch);
- }
- String * modifiedString;
+ struct parserState * state;
+
+ state = (struct parserState *) context;
+ String * result = state->result;
+
+ if (!state->enabled) {
+ return;
+ }
+
+ if (state->logEnabled) {
+ MCLog("text %s", ch);
+ }
+ String * modifiedString;
modifiedString = new String((const char *) ch, len);
modifiedString->replaceOccurrencesOfString(MCSTR("\n"), MCSTR(" "));
modifiedString->replaceOccurrencesOfString(MCSTR("\r"), MCSTR(" "));
@@ -1391,11 +1391,11 @@ static void charactersParsed(void * context,
/* GCS: custom error function to ignore errors */
static void structuredError(void * userData,
- xmlErrorPtr error)
+ xmlErrorPtr error)
{
- /* ignore all errors */
- (void)userData;
- (void)error;
+ /* ignore all errors */
+ (void)userData;
+ (void)error;
}
static void appendQuote(struct parserState * state)
@@ -1501,13 +1501,13 @@ static HashMap * dictionaryFromAttributes(const xmlChar ** atts)
static void elementStarted(void * ctx, const xmlChar * name, const xmlChar ** atts)
{
- struct parserState * state;
-
- state = (struct parserState *) ctx;
-
- if (state->logEnabled) {
- MCLog("parsed element %s", name);
- }
+ struct parserState * state;
+
+ state = (struct parserState *) ctx;
+
+ if (state->logEnabled) {
+ MCLog("parsed element %s", name);
+ }
if (strcasecmp((const char *) name, "blockquote") == 0) {
state->quoteLevel ++;
@@ -1565,22 +1565,22 @@ static void elementStarted(void * ctx, const xmlChar * name, const xmlChar ** at
state->paragraphSpacingStack->addObject(Value::valueWithBoolValue(hasSpacing));
}
- if (state->enabled) {
- if (state->level == 1) {
- if (strcasecmp((const char *) name, "head") == 0) {
- state->enabled = 0;
- state->disabledLevel = state->level;
- }
- }
- if (strcasecmp((const char *) name, "style") == 0) {
- state->enabled = 0;
- state->disabledLevel = state->level;
- }
- else if (strcasecmp((const char *) name, "script") == 0) {
- state->enabled = 0;
- state->disabledLevel = state->level;
- }
- else if (strcasecmp((const char *) name, "p") == 0) {
+ if (state->enabled) {
+ if (state->level == 1) {
+ if (strcasecmp((const char *) name, "head") == 0) {
+ state->enabled = 0;
+ state->disabledLevel = state->level;
+ }
+ }
+ if (strcasecmp((const char *) name, "style") == 0) {
+ state->enabled = 0;
+ state->disabledLevel = state->level;
+ }
+ else if (strcasecmp((const char *) name, "script") == 0) {
+ state->enabled = 0;
+ state->disabledLevel = state->level;
+ }
+ else if (strcasecmp((const char *) name, "p") == 0) {
returnToLineAtBeginningOfBlock(state);
if (((Value *) state->paragraphSpacingStack->lastObject())->boolValue()) {
returnToLine(state);
@@ -1589,7 +1589,7 @@ static void elementStarted(void * ctx, const xmlChar * name, const xmlChar ** at
else if (blockElements()->containsObject(String::stringWithUTF8Characters((const char *) name)->lowercaseString())) {
returnToLineAtBeginningOfBlock(state);
}
- else if (strcasecmp((const char *) name, "blockquote") == 0) {
+ else if (strcasecmp((const char *) name, "blockquote") == 0) {
if (!state->showBlockQuote) {
AutoreleasePool * pool;
String * type;
@@ -1620,38 +1620,38 @@ static void elementStarted(void * ctx, const xmlChar * name, const xmlChar ** at
else {
returnToLineAtBeginningOfBlock(state);
}
- }
+ }
else if (strcasecmp((const char *) name, "br") == 0) {
returnToLine(state);
state->hasReturnToLine = true;
}
- }
-
- state->level ++;
+ }
+
+ state->level ++;
}
static void elementEnded(void * ctx, const xmlChar * name)
{
- struct parserState * state;
+ struct parserState * state;
+
+ state = (struct parserState *) ctx;
- state = (struct parserState *) ctx;
-
- if (state->logEnabled) {
- MCLog("ended element %s", name);
- }
+ if (state->logEnabled) {
+ MCLog("ended element %s", name);
+ }
if (strcasecmp((const char *) name, "blockquote") == 0) {
state->quoteLevel --;
}
- state->level --;
- if (!state->enabled) {
- if (state->level == state->disabledLevel) {
- state->enabled = 1;
- }
- }
+ state->level --;
+ if (!state->enabled) {
+ if (state->level == state->disabledLevel) {
+ state->enabled = 1;
+ }
+ }
- bool hasReturnToLine;
+ bool hasReturnToLine;
hasReturnToLine = false;
if (strcasecmp((const char *) name, "a") == 0) {
@@ -1707,13 +1707,13 @@ static void elementEnded(void * ctx, const xmlChar * name)
static void commentParsed(void * ctx, const xmlChar * value)
{
- struct parserState * state;
-
- state = (struct parserState *) ctx;
-
- if (state->logEnabled) {
- MCLog("comments %s", value);
- }
+ struct parserState * state;
+
+ state = (struct parserState *) ctx;
+
+ if (state->logEnabled) {
+ MCLog("comments %s", value);
+ }
}
void initializeLibXML()
@@ -1740,20 +1740,20 @@ String * String::flattenHTMLAndShowBlockquoteAndLink(bool showBlockquote, bool s
{
initializeLibXML();
- int mem_base = xmlMemBlocks();
+ int mem_base = xmlMemBlocks();
String * result = String::string();
- xmlSAXHandler handler;
- bzero(&handler, sizeof(xmlSAXHandler));
- handler.characters = &charactersParsed;
- handler.startElement = elementStarted;
- handler.endElement = elementEnded;
- handler.comment = commentParsed;
- struct parserState state;
- state.result = result;
- state.level = 0;
- state.enabled = 1;
- state.logEnabled = 0;
- state.disabledLevel = 0;
+ xmlSAXHandler handler;
+ bzero(&handler, sizeof(xmlSAXHandler));
+ handler.characters = &charactersParsed;
+ handler.startElement = elementStarted;
+ handler.endElement = elementEnded;
+ handler.comment = commentParsed;
+ struct parserState state;
+ state.result = result;
+ state.level = 0;
+ state.enabled = 1;
+ state.logEnabled = 0;
+ state.disabledLevel = 0;
state.quoteLevel = 0;
state.hasText = false;
state.hasQuote = false;
@@ -1762,16 +1762,16 @@ String * String::flattenHTMLAndShowBlockquoteAndLink(bool showBlockquote, bool s
state.showLink = showLink;
state.lastCharIsWhitespace = true;
state.linkStack = new Array();
- state.paragraphSpacingStack = new Array();
+ state.paragraphSpacingStack = new Array();
const char * characters = cleanedHTMLString()->UTF8Characters();
- htmlSAXParseDoc((xmlChar*) characters, "utf-8", &handler, &state);
+ htmlSAXParseDoc((xmlChar*) characters, "utf-8", &handler, &state);
- if (mem_base != xmlMemBlocks()) {
- MCLog("Leak of %d blocks found in htmlSAXParseDoc",
+ if (mem_base != xmlMemBlocks()) {
+ MCLog("Leak of %d blocks found in htmlSAXParseDoc",
xmlMemBlocks() - mem_base);
- }
+ }
state.paragraphSpacingStack->release();
state.linkStack->release();
@@ -1781,7 +1781,7 @@ String * String::flattenHTMLAndShowBlockquoteAndLink(bool showBlockquote, bool s
ch[1] = 0;
result->replaceOccurrencesOfString(String::stringWithCharacters(ch), MCSTR(" "));
- return result;
+ return result;
}
String * String::flattenHTMLAndShowBlockquote(bool showBlockquote)