Commit fcadaeef fcadaeef1c45828497e7a3a77fc1cd48dbe467d3 by Sergey Poznyakoff

Implemented external-body.

1 parent 45ce2c09
Showing 1 changed file with 121 additions and 48 deletions
......@@ -1652,44 +1652,14 @@ parse_brace (char **pval, char **cmd, int c, struct compose_env *env)
#define isdelim(c) (isspace (c) || strchr (";<[(", c))
#define skipws(ptr) do { while (*ptr && isspace (*ptr)) ptr++; } while (0)
/* cmd is: type "/" subtype
0*(";" attribute "=" value)
[ "(" comment ")" ]
[ "<" id ">" ]
[ "[" description "]" ]
*/
int
parse_type_command (char **pcmd, struct compose_env *env, header_t hdr)
parse_content_type (struct compose_env *env,
struct obstack *stk, char **prest, char **id, char **descr)
{
int status = 0, stop = 0;
char *sp, c;
char *type = NULL;
char *subtype = NULL;
char *comment = NULL, *descr = NULL, *id = NULL;
struct obstack stk;
char *rest = *pcmd;
skipws (rest);
for (sp = rest; *sp && !isdelim (*sp); sp++)
;
c = *sp;
*sp = 0;
split_content (rest, &type, &subtype);
*sp = c;
rest = sp;
if (!subtype)
{
mh_error (_("%s:%lu: missing subtype"),
input_file,
(unsigned long) mhn_error_loc (env));
return 1;
}
obstack_init (&stk);
obstack_grow (&stk, type, strlen (type));
obstack_1grow (&stk, '/');
obstack_grow (&stk, subtype, strlen (subtype));
char *rest = *prest;
char *sp;
char *comment = NULL;
while (stop == 0 && status == 0 && *rest)
{
......@@ -1708,7 +1678,16 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr)
break;
case '[':
if (descr)
if (!descr)
{
mh_error (_("%s:%lu: syntax error"),
input_file,
(unsigned long) mhn_error_loc (env));
status = 1;
break;
}
if (*descr)
{
mh_error (_("%s:%lu: description redefined"),
input_file,
......@@ -1716,11 +1695,11 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr)
status = 1;
break;
}
status = parse_brace (&descr, &rest, ']', env);
status = parse_brace (descr, &rest, ']', env);
break;
case '<':
if (id)
if (*id)
{
mh_error (_("%s:%lu: content id redefined"),
input_file,
......@@ -1728,16 +1707,16 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr)
status = 1;
break;
}
status = parse_brace (&id, &rest, '>', env);
status = parse_brace (id, &rest, '>', env);
break;
case ';':
obstack_1grow (&stk, ';');
obstack_1grow (&stk, ' ');
obstack_1grow (stk, ';');
obstack_1grow (stk, ' ');
skipws (rest);
sp = rest;
for (; *rest && !isspace (*rest) && *rest != '='; rest++)
obstack_1grow (&stk, *rest);
obstack_1grow (stk, *rest);
skipws (rest);
if (*rest != '=')
{
......@@ -1748,13 +1727,13 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr)
break;
}
rest++;
obstack_1grow (&stk, '=');
obstack_1grow (stk, '=');
skipws (rest);
for (; *rest; rest++)
{
if (isdelim (*rest))
break;
obstack_1grow (&stk, *rest);
obstack_1grow (stk, *rest);
}
break;
......@@ -1768,13 +1747,56 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr)
if (comment)
{
obstack_grow (&stk, " (", 2);
obstack_grow (&stk, comment, strlen (comment));
obstack_1grow (&stk, ')');
obstack_grow (stk, " (", 2);
obstack_grow (stk, comment, strlen (comment));
obstack_1grow (stk, ')');
free (comment);
}
*prest = rest;
return status;
}
/* cmd is: type "/" subtype
0*(";" attribute "=" value)
[ "(" comment ")" ]
[ "<" id ">" ]
[ "[" description "]" ]
*/
int
parse_type_command (char **pcmd, struct compose_env *env, header_t hdr)
{
int status = 0;
char *sp, c;
char *type = NULL;
char *subtype = NULL;
char *descr = NULL, *id = NULL;
struct obstack stk;
char *rest = *pcmd;
skipws (rest);
for (sp = rest; *sp && !isdelim (*sp); sp++)
;
c = *sp;
*sp = 0;
split_content (rest, &type, &subtype);
*sp = c;
rest = sp;
if (!subtype)
{
mh_error (_("%s:%lu: missing subtype"),
input_file,
(unsigned long) mhn_error_loc (env));
return 1;
}
obstack_init (&stk);
obstack_grow (&stk, type, strlen (type));
obstack_1grow (&stk, '/');
obstack_grow (&stk, subtype, strlen (subtype));
status = parse_content_type (env, &stk, &rest, &id, &descr);
obstack_1grow (&stk, 0);
header_set_value (hdr, MU_HEADER_CONTENT_TYPE, obstack_finish (&stk), 1);
obstack_free (&stk, NULL);
......@@ -1815,9 +1837,60 @@ finish_msg (struct compose_env *env, message_t *msg)
*msg = NULL;
}
#define EXTCONTENT "message/external-body"
int
edit_extern (char *cmd, struct compose_env *env, message_t *msg, int level)
{
int rc;
char *rest;
char *id = NULL;
header_t hdr, hdr2;
body_t body;
stream_t in, out = NULL;
struct obstack stk;
if (!*msg)
message_create (msg, NULL);
if ((rc = header_create (&hdr2, NULL, 0, NULL)) != 0)
{
mh_error (_("cannot create header: %s"),
mu_strerror (rc));
return 1;
}
rest = cmd;
rc = parse_type_command (&rest, env, hdr2);
message_get_header (*msg, &hdr);
obstack_init (&stk);
obstack_grow (&stk, EXTCONTENT, sizeof (EXTCONTENT) - 1);
*--rest = ';'; /* FIXME */
rc = parse_content_type (env, &stk, &rest, &id, NULL);
obstack_1grow (&stk, 0);
header_set_value (hdr, MU_HEADER_CONTENT_TYPE, obstack_finish (&stk), 1);
obstack_free (&stk, NULL);
if (rc)
return 1;
message_get_body (*msg, &body);
body_get_stream (body, &out);
stream_seek (out, 0, SEEK_SET);
if (!id)
id = mh_create_message_id (env->subpart);
header_set_value (hdr2, MU_HEADER_CONTENT_ID, id, 1);
free (id);
header_get_stream (hdr2, &in);
stream_seek (in, 0, SEEK_SET);
cat_message (out, in);
stream_close (out);
header_destroy (&hdr2, header_get_owner (hdr2));
finish_msg (env, msg);
return 0;
}
......