LIBETPAN_EXPORT int mailmime_field_parse(struct mailimf_optional_field * field, struct mailmime_field ** result) { char * name; char * value; int guessed_type; size_t cur_token; struct mailmime_content * content; struct mailmime_mechanism * encoding; char * id; char * description; uint32_t version; struct mailmime_field * mime_field; struct mailmime_language * language; struct mailmime_disposition * disposition; char * location; int res; int r; name = field->fld_name; value = field->fld_value; cur_token = 0; content = NULL; encoding = NULL; id = NULL; description = NULL; version = 0; disposition = NULL; language = NULL; location = NULL; guessed_type = guess_field_type(name); switch (guessed_type) { case MAILMIME_FIELD_TYPE: if (strcasecmp(name, "Content-Type") != 0) return MAILIMF_ERROR_PARSE; { size_t cur_token = 0; char * decoded_value; r = mailmime_encoded_phrase_parse("us-ascii", value, strlen(value), &cur_token, "utf-8", &decoded_value); if (r != MAILIMF_NO_ERROR) { cur_token = 0; r = mailmime_content_parse(value, strlen(value), &cur_token, &content); } else { cur_token = 0; r = mailmime_content_parse(decoded_value, strlen(decoded_value), &cur_token, &content); free(decoded_value); } if (r != MAILIMF_NO_ERROR) return r; } break; case MAILMIME_FIELD_TRANSFER_ENCODING: if (strcasecmp(name, "Content-Transfer-Encoding") != 0) return MAILIMF_ERROR_PARSE; r = mailmime_encoding_parse(value, strlen(value), &cur_token, &encoding); if (r != MAILIMF_NO_ERROR) return r; break; case MAILMIME_FIELD_ID: if (strcasecmp(name, "Content-ID") != 0) return MAILIMF_ERROR_PARSE; r = mailmime_id_parse(value, strlen(value), &cur_token, &id); if (r != MAILIMF_NO_ERROR) return r; break; case MAILMIME_FIELD_DESCRIPTION: if (strcasecmp(name, "Content-Description") != 0) return MAILIMF_ERROR_PARSE; r = mailmime_description_parse(value, strlen(value), &cur_token, &description); if (r != MAILIMF_NO_ERROR) return r; break; case MAILMIME_FIELD_VERSION: if (strcasecmp(name, "MIME-Version") != 0) return MAILIMF_ERROR_PARSE; r = mailmime_version_parse(value, strlen(value), &cur_token, &version); if (r != MAILIMF_NO_ERROR) return r; break; case MAILMIME_FIELD_DISPOSITION: if (strcasecmp(name, "Content-Disposition") != 0) return MAILIMF_ERROR_PARSE; r = mailmime_disposition_parse(value, strlen(value), &cur_token, &disposition); if (r != MAILIMF_NO_ERROR) return r; break; case MAILMIME_FIELD_LANGUAGE: if (strcasecmp(name, "Content-Language") != 0) return MAILIMF_ERROR_PARSE; r = mailmime_language_parse(value, strlen(value), &cur_token, &language); if (r != MAILIMF_NO_ERROR) return r; break; case MAILMIME_FIELD_LOCATION: if (strcasecmp(name, "Content-Location") != 0) return MAILIMF_ERROR_PARSE; r = mailmime_location_parse(value, strlen(value), &cur_token, &location); if (r != MAILIMF_NO_ERROR) return r; break; default: return MAILIMF_ERROR_PARSE; } mime_field = mailmime_field_new(guessed_type, content, encoding, id, description, version, disposition, language, location); if (mime_field == NULL) { res = MAILIMF_ERROR_MEMORY; goto free; } * result = mime_field; return MAILIMF_NO_ERROR; free: if (location != NULL) mailmime_location_free(location); if (language != NULL) mailmime_language_free(language); if (content != NULL) mailmime_content_free(content); if (encoding != NULL) mailmime_encoding_free(encoding); if (id != NULL) mailmime_id_free(id); if (description != NULL) mailmime_description_free(description); return res; }
static char * extract_subject(char * default_from, struct mailmessage_tree * tree, char * str) { char * subj; char * cur; char * write_pos; size_t len; size_t begin; char * decoded; size_t cur_token; int do_repeat_5; int do_repeat_6; int r; /* (1) Convert any RFC 2047 encoded-words in the subject to UTF-8. */ decoded = NULL; cur_token = 0; r = mailmime_encoded_phrase_parse(default_from, str, strlen(str), &cur_token, "utf-8", &decoded); if (r == MAILIMF_NO_ERROR) { subj = decoded; } else subj = strdup(str); 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 = TRUE; cur ++; while (* cur && cont) { switch (* cur) { case '\t': case '\r': case '\n': cont = TRUE; break; default: cont = FALSE; break; } cur ++; } * write_pos = ' '; write_pos ++; break; default: * write_pos = * cur; write_pos ++; cur ++; break; } } * write_pos = '\0'; begin = 0; do { do_repeat_6 = FALSE; /* (2) Remove all trailing text of the subject that matches the subj-trailer ABNF, repeat until no more matches are possible. */ while (len > 0) { int chg; chg = FALSE; /* 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; tree->node_is_reply = TRUE; } } do { size_t saved_begin; do_repeat_5 = FALSE; /* (3) Remove all prefix text of the subject that matches the subj-leader ABNF. */ if (skip_subj_leader(tree, subj, &begin, len)) do_repeat_5 = TRUE; /* (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)) { if (begin == len) { /* this will leave a empty subject base */ begin = saved_begin; } else do_repeat_5 = TRUE; } /* (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) { size_t saved_begin; saved_begin = begin; if (strncasecmp(subj + begin, "[fwd:", 5) == 0) { begin += 5; if (subj[len - 1] != ']') saved_begin = begin; else { tree->node_is_reply = TRUE; subj[len - 1] = '\0'; len --; do_repeat_6 = TRUE; } } } } 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 = (char) toupper((unsigned char) * cur); cur ++; write_pos ++; } * write_pos = '\0'; return subj; }