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) ...@@ -1652,44 +1652,14 @@ parse_brace (char **pval, char **cmd, int c, struct compose_env *env)
1652 #define isdelim(c) (isspace (c) || strchr (";<[(", c)) 1652 #define isdelim(c) (isspace (c) || strchr (";<[(", c))
1653 #define skipws(ptr) do { while (*ptr && isspace (*ptr)) ptr++; } while (0) 1653 #define skipws(ptr) do { while (*ptr && isspace (*ptr)) ptr++; } while (0)
1654 1654
1655 /* cmd is: type "/" subtype
1656 0*(";" attribute "=" value)
1657 [ "(" comment ")" ]
1658 [ "<" id ">" ]
1659 [ "[" description "]" ]
1660 */
1661 int 1655 int
1662 parse_type_command (char **pcmd, struct compose_env *env, header_t hdr) 1656 parse_content_type (struct compose_env *env,
1657 struct obstack *stk, char **prest, char **id, char **descr)
1663 { 1658 {
1664 int status = 0, stop = 0; 1659 int status = 0, stop = 0;
1665 char *sp, c; 1660 char *rest = *prest;
1666 char *type = NULL; 1661 char *sp;
1667 char *subtype = NULL; 1662 char *comment = NULL;
1668 char *comment = NULL, *descr = NULL, *id = NULL;
1669 struct obstack stk;
1670 char *rest = *pcmd;
1671
1672 skipws (rest);
1673 for (sp = rest; *sp && !isdelim (*sp); sp++)
1674 ;
1675 c = *sp;
1676 *sp = 0;
1677 split_content (rest, &type, &subtype);
1678 *sp = c;
1679 rest = sp;
1680
1681 if (!subtype)
1682 {
1683 mh_error (_("%s:%lu: missing subtype"),
1684 input_file,
1685 (unsigned long) mhn_error_loc (env));
1686 return 1;
1687 }
1688
1689 obstack_init (&stk);
1690 obstack_grow (&stk, type, strlen (type));
1691 obstack_1grow (&stk, '/');
1692 obstack_grow (&stk, subtype, strlen (subtype));
1693 1663
1694 while (stop == 0 && status == 0 && *rest) 1664 while (stop == 0 && status == 0 && *rest)
1695 { 1665 {
...@@ -1708,7 +1678,16 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr) ...@@ -1708,7 +1678,16 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr)
1708 break; 1678 break;
1709 1679
1710 case '[': 1680 case '[':
1711 if (descr) 1681 if (!descr)
1682 {
1683 mh_error (_("%s:%lu: syntax error"),
1684 input_file,
1685 (unsigned long) mhn_error_loc (env));
1686 status = 1;
1687 break;
1688 }
1689
1690 if (*descr)
1712 { 1691 {
1713 mh_error (_("%s:%lu: description redefined"), 1692 mh_error (_("%s:%lu: description redefined"),
1714 input_file, 1693 input_file,
...@@ -1716,11 +1695,11 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr) ...@@ -1716,11 +1695,11 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr)
1716 status = 1; 1695 status = 1;
1717 break; 1696 break;
1718 } 1697 }
1719 status = parse_brace (&descr, &rest, ']', env); 1698 status = parse_brace (descr, &rest, ']', env);
1720 break; 1699 break;
1721 1700
1722 case '<': 1701 case '<':
1723 if (id) 1702 if (*id)
1724 { 1703 {
1725 mh_error (_("%s:%lu: content id redefined"), 1704 mh_error (_("%s:%lu: content id redefined"),
1726 input_file, 1705 input_file,
...@@ -1728,16 +1707,16 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr) ...@@ -1728,16 +1707,16 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr)
1728 status = 1; 1707 status = 1;
1729 break; 1708 break;
1730 } 1709 }
1731 status = parse_brace (&id, &rest, '>', env); 1710 status = parse_brace (id, &rest, '>', env);
1732 break; 1711 break;
1733 1712
1734 case ';': 1713 case ';':
1735 obstack_1grow (&stk, ';'); 1714 obstack_1grow (stk, ';');
1736 obstack_1grow (&stk, ' '); 1715 obstack_1grow (stk, ' ');
1737 skipws (rest); 1716 skipws (rest);
1738 sp = rest; 1717 sp = rest;
1739 for (; *rest && !isspace (*rest) && *rest != '='; rest++) 1718 for (; *rest && !isspace (*rest) && *rest != '='; rest++)
1740 obstack_1grow (&stk, *rest); 1719 obstack_1grow (stk, *rest);
1741 skipws (rest); 1720 skipws (rest);
1742 if (*rest != '=') 1721 if (*rest != '=')
1743 { 1722 {
...@@ -1748,13 +1727,13 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr) ...@@ -1748,13 +1727,13 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr)
1748 break; 1727 break;
1749 } 1728 }
1750 rest++; 1729 rest++;
1751 obstack_1grow (&stk, '='); 1730 obstack_1grow (stk, '=');
1752 skipws (rest); 1731 skipws (rest);
1753 for (; *rest; rest++) 1732 for (; *rest; rest++)
1754 { 1733 {
1755 if (isdelim (*rest)) 1734 if (isdelim (*rest))
1756 break; 1735 break;
1757 obstack_1grow (&stk, *rest); 1736 obstack_1grow (stk, *rest);
1758 } 1737 }
1759 break; 1738 break;
1760 1739
...@@ -1768,13 +1747,56 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr) ...@@ -1768,13 +1747,56 @@ parse_type_command (char **pcmd, struct compose_env *env, header_t hdr)
1768 1747
1769 if (comment) 1748 if (comment)
1770 { 1749 {
1771 obstack_grow (&stk, " (", 2); 1750 obstack_grow (stk, " (", 2);
1772 obstack_grow (&stk, comment, strlen (comment)); 1751 obstack_grow (stk, comment, strlen (comment));
1773 obstack_1grow (&stk, ')'); 1752 obstack_1grow (stk, ')');
1774 free (comment); 1753 free (comment);
1775 } 1754 }
1776 1755 *prest = rest;
1756 return status;
1757 }
1758
1759 /* cmd is: type "/" subtype
1760 0*(";" attribute "=" value)
1761 [ "(" comment ")" ]
1762 [ "<" id ">" ]
1763 [ "[" description "]" ]
1764 */
1765 int
1766 parse_type_command (char **pcmd, struct compose_env *env, header_t hdr)
1767 {
1768 int status = 0;
1769 char *sp, c;
1770 char *type = NULL;
1771 char *subtype = NULL;
1772 char *descr = NULL, *id = NULL;
1773 struct obstack stk;
1774 char *rest = *pcmd;
1775
1776 skipws (rest);
1777 for (sp = rest; *sp && !isdelim (*sp); sp++)
1778 ;
1779 c = *sp;
1780 *sp = 0;
1781 split_content (rest, &type, &subtype);
1782 *sp = c;
1783 rest = sp;
1784
1785 if (!subtype)
1786 {
1787 mh_error (_("%s:%lu: missing subtype"),
1788 input_file,
1789 (unsigned long) mhn_error_loc (env));
1790 return 1;
1791 }
1792
1793 obstack_init (&stk);
1794 obstack_grow (&stk, type, strlen (type));
1795 obstack_1grow (&stk, '/');
1796 obstack_grow (&stk, subtype, strlen (subtype));
1797 status = parse_content_type (env, &stk, &rest, &id, &descr);
1777 obstack_1grow (&stk, 0); 1798 obstack_1grow (&stk, 0);
1799
1778 header_set_value (hdr, MU_HEADER_CONTENT_TYPE, obstack_finish (&stk), 1); 1800 header_set_value (hdr, MU_HEADER_CONTENT_TYPE, obstack_finish (&stk), 1);
1779 obstack_free (&stk, NULL); 1801 obstack_free (&stk, NULL);
1780 1802
...@@ -1815,9 +1837,60 @@ finish_msg (struct compose_env *env, message_t *msg) ...@@ -1815,9 +1837,60 @@ finish_msg (struct compose_env *env, message_t *msg)
1815 *msg = NULL; 1837 *msg = NULL;
1816 } 1838 }
1817 1839
1840 #define EXTCONTENT "message/external-body"
1841
1818 int 1842 int
1819 edit_extern (char *cmd, struct compose_env *env, message_t *msg, int level) 1843 edit_extern (char *cmd, struct compose_env *env, message_t *msg, int level)
1820 { 1844 {
1845 int rc;
1846 char *rest;
1847 char *id = NULL;
1848 header_t hdr, hdr2;
1849 body_t body;
1850 stream_t in, out = NULL;
1851 struct obstack stk;
1852
1853 if (!*msg)
1854 message_create (msg, NULL);
1855
1856 if ((rc = header_create (&hdr2, NULL, 0, NULL)) != 0)
1857 {
1858 mh_error (_("cannot create header: %s"),
1859 mu_strerror (rc));
1860 return 1;
1861 }
1862
1863 rest = cmd;
1864 rc = parse_type_command (&rest, env, hdr2);
1865
1866 message_get_header (*msg, &hdr);
1867
1868 obstack_init (&stk);
1869 obstack_grow (&stk, EXTCONTENT, sizeof (EXTCONTENT) - 1);
1870 *--rest = ';'; /* FIXME */
1871 rc = parse_content_type (env, &stk, &rest, &id, NULL);
1872 obstack_1grow (&stk, 0);
1873 header_set_value (hdr, MU_HEADER_CONTENT_TYPE, obstack_finish (&stk), 1);
1874 obstack_free (&stk, NULL);
1875 if (rc)
1876 return 1;
1877
1878 message_get_body (*msg, &body);
1879 body_get_stream (body, &out);
1880 stream_seek (out, 0, SEEK_SET);
1881
1882 if (!id)
1883 id = mh_create_message_id (env->subpart);
1884 header_set_value (hdr2, MU_HEADER_CONTENT_ID, id, 1);
1885 free (id);
1886
1887 header_get_stream (hdr2, &in);
1888 stream_seek (in, 0, SEEK_SET);
1889 cat_message (out, in);
1890 stream_close (out);
1891 header_destroy (&hdr2, header_get_owner (hdr2));
1892
1893 finish_msg (env, msg);
1821 return 0; 1894 return 0;
1822 } 1895 }
1823 1896
......