+ /* check for missing subtype */
+ if (!*ci->ci_subtype)
+ ci->ci_subtype = add("rfc822", ci->ci_subtype);
+
+ /* match subtype */
+ for (kv = SubMessage; kv->kv_key; kv++)
+ if (!mh_strcasecmp(ci->ci_subtype, kv->kv_key))
+ break;
+ ct->c_subtype = kv->kv_value;
+
+ switch (ct->c_subtype) {
+ case MESSAGE_RFC822:
+ break;
+
+ case MESSAGE_PARTIAL:
+ {
+ char **ap, **ep;
+ struct partial *p;
+
+ if ((p = (struct partial *)
+ calloc(1, sizeof(*p))) == NULL)
+ adios(NULL, "out of memory");
+ ct->c_ctparams = (void *) p;
+
+ /*
+ ** scan for parameters "id", "number",
+ ** and "total"
+ */
+ for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) {
+ if (!mh_strcasecmp(*ap, "id")) {
+ p->pm_partid = getcpy(*ep);
+ continue;
+ }
+ if (!mh_strcasecmp(*ap, "number")) {
+ if (sscanf(*ep, "%d", &p->pm_partno) != 1 || p->pm_partno < 1) {
+invalid_param:
+ advise(NULL, "invalid %s parameter for \"%s/%s\" type in message %s's %s field", *ap, ci->ci_type, ci->ci_subtype, ct->c_file, TYPE_FIELD);
+ return NOTOK;
+ }
+ continue;
+ }
+ if (!mh_strcasecmp(*ap, "total")) {
+ if (sscanf(*ep, "%d", &p->pm_maxno) != 1 || p->pm_maxno < 1)
+ goto invalid_param;
+ continue;
+ }
+ }
+
+ if (!p->pm_partid || !p->pm_partno
+ || (p->pm_maxno && p->pm_partno > p->pm_maxno)) {
+ advise(NULL, "invalid parameters for \"%s/%s\" type in message %s's %s field", ci->ci_type, ci->ci_subtype, ct->c_file, TYPE_FIELD);
+ return NOTOK;
+ }
+ }
+ break;
+
+ case MESSAGE_EXTERNAL:
+ {
+ int exresult;
+ struct exbody *e;
+ CT p;
+ FILE *fp;
+
+ if ((e = (struct exbody *)
+ calloc(1, sizeof(*e))) == NULL)
+ adios(NULL, "out of memory");
+ ct->c_ctparams = (void *) e;
+
+ if (!ct->c_fp && (ct->c_fp = fopen(ct->c_file, "r")) == NULL) {
+ advise(ct->c_file, "unable to open for reading");
+ return NOTOK;
+ }
+
+ fseek(fp = ct->c_fp, ct->c_begin, SEEK_SET);
+
+ if (!(p = get_content(fp, ct->c_file, 0))) {
+ ct->c_fp = NULL;
+ return NOTOK;
+ }
+
+ e->eb_parent = ct;
+ e->eb_content = p;
+ p->c_ctexbody = e;
+ if ((exresult = params_external(ct, 0))
+ != NOTOK &&
+ p->c_ceopenfnx == openMail) {
+ int cc, size;
+ char *bp;
+
+ if ((size = ct->c_end - p->c_begin) <= 0) {
+ if (!e->eb_subject)
+ content_error(NULL, ct, "empty body for access-type=mail-server");
+ goto no_body;
+ }
+
+ e->eb_body = bp = mh_xmalloc((unsigned) size);
+ fseek(p->c_fp, p->c_begin, SEEK_SET);
+ while (size > 0)
+ switch (cc = fread(bp, sizeof(*bp), size, p->c_fp)) {
+ case NOTOK:
+ adios("failed", "fread");
+
+ case OK:
+ adios(NULL, "unexpected EOF from fread");
+
+ default:
+ bp += cc, size -= cc;
+ break;
+ }
+ *bp = 0;
+ }
+no_body:
+ p->c_fp = NULL;
+ p->c_end = p->c_begin;
+
+ fclose(ct->c_fp);
+ ct->c_fp = NULL;
+
+ if (exresult == NOTOK)
+ return NOTOK;
+ if (e->eb_flags == NOTOK)
+ return OK;
+
+ switch (p->c_type) {
+ case CT_MULTIPART:
+ break;
+
+ case CT_MESSAGE:
+ if (p->c_subtype != MESSAGE_RFC822)
+ break;
+ /* else fall... */
+ default:
+ e->eb_partno = ct->c_partno;
+ if (p->c_ctinitfnx)
+ (*p->c_ctinitfnx) (p);
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return OK;
+}
+
+
+int
+params_external(CT ct, int composing)
+{
+ char **ap, **ep;
+ struct exbody *e = (struct exbody *) ct->c_ctparams;
+ CI ci = &ct->c_ctinfo;
+
+ for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) {
+ if (!mh_strcasecmp(*ap, "access-type")) {
+ struct str2init *s2i;
+ CT p = e->eb_content;
+
+ for (s2i = str2methods; s2i->si_key; s2i++)
+ if (!mh_strcasecmp(*ep, s2i->si_key))
+ break;
+ if (!s2i->si_key) {
+ e->eb_access = *ep;
+ e->eb_flags = NOTOK;
+ p->c_encoding = CE_EXTERNAL;
+ continue;
+ }
+ e->eb_access = s2i->si_key;
+ e->eb_flags = s2i->si_val;
+ p->c_encoding = CE_EXTERNAL;
+
+ /* Call the Init function for this external type */
+ if ((*s2i->si_init)(p) == NOTOK)
+ return NOTOK;
+ continue;
+ }
+ if (!mh_strcasecmp(*ap, "name")) {
+ e->eb_name = *ep;
+ continue;
+ }
+ if (!mh_strcasecmp(*ap, "permission")) {
+ e->eb_permission = *ep;
+ continue;
+ }
+ if (!mh_strcasecmp(*ap, "site")) {
+ e->eb_site = *ep;
+ continue;
+ }
+ if (!mh_strcasecmp(*ap, "directory")) {
+ e->eb_dir = *ep;
+ continue;
+ }
+ if (!mh_strcasecmp(*ap, "mode")) {
+ e->eb_mode = *ep;
+ continue;
+ }
+ if (!mh_strcasecmp(*ap, "size")) {
+ sscanf(*ep, "%lu", &e->eb_size);
+ continue;
+ }
+ if (!mh_strcasecmp(*ap, "server")) {
+ e->eb_server = *ep;
+ continue;
+ }
+ if (!mh_strcasecmp(*ap, "subject")) {
+ e->eb_subject = *ep;
+ continue;
+ }
+ if (composing && !mh_strcasecmp(*ap, "body")) {
+ e->eb_body = getcpy(*ep);
+ continue;
+ }
+ }
+
+ if (!e->eb_access) {
+ advise(NULL, "invalid parameters for \"%s/%s\" type in message %s's %s field", ci->ci_type, ci->ci_subtype, ct->c_file, TYPE_FIELD);
+ return NOTOK;
+ }
+
+ return OK;
+}
+
+
+/*
+** APPLICATION
+*/
+
+static int
+InitApplication(CT ct)
+{
+ struct k2v *kv;
+ CI ci = &ct->c_ctinfo;
+
+ /* match subtype */
+ for (kv = SubApplication; kv->kv_key; kv++)
+ if (!mh_strcasecmp(ci->ci_subtype, kv->kv_key))
+ break;
+ ct->c_subtype = kv->kv_value;
+
+ return OK;
+}
+
+
+/*
+** TRANSFER ENCODINGS
+*/
+
+static int
+init_encoding(CT ct, OpenCEFunc openfnx)
+{
+ CE ce;
+
+ if ((ce = (CE) calloc(1, sizeof(*ce))) == NULL)
+ adios(NULL, "out of memory");
+
+ ct->c_cefile = ce;
+ ct->c_ceopenfnx = openfnx;
+ ct->c_ceclosefnx = close_encoding;
+ ct->c_cesizefnx = size_encoding;
+
+ return OK;
+}
+
+
+void
+close_encoding(CT ct)
+{
+ CE ce;
+
+ if (!(ce = ct->c_cefile))
+ return;
+
+ if (ce->ce_fp) {
+ fclose(ce->ce_fp);
+ ce->ce_fp = NULL;
+ }