2 * Parts were written/modified by:
3 * Andreas Krennmair <ak@synflood.at>
4 * Peter J. Holzer <hjp@hjp.net>
5 * Rocco Rutte <pdmef@cs.tu-berlin.de>
7 * This file is part of mutt-ng, see http://www.muttng.org/.
8 * It's licensed under the GNU General Public License,
9 * please see the file GPL in the top level source directory.
12 #include <lib-lib/lib-lib.h>
16 #include <lib-ui/curses.h>
23 static int get_quote_level (char *line)
27 for (quoted = 0; line[quoted] == '>'; quoted++);
31 static void print_flowed_line (char *line, STATE * s, int ql) {
34 int len = m_strlen(line);
37 if (MaxLineLength > 0) {
38 width = MaxLineLength - WrapMargin - ql - 1;
39 if (!(s->flags & M_REPLYING) && option (OPTSTUFFQUOTED))
42 width = MaxLineLength;
45 if (option (OPTMBOXPANE))
46 width = COLS - SidebarWidth - WrapMargin - ql - 1;
48 width = COLS - WrapMargin - ql - 1;
50 if (!(s->flags & M_REPLYING) && option (OPTSTUFFQUOTED))
56 if (m_strlen(line) == 0) {
57 if (!(s->flags & M_REPLYING) || option (OPTQUOTEEMPTY)) {
59 state_puts(s->prefix,s);
60 for (i=0;i<ql;++i) state_putc('>',s);
61 if (!(s->flags & M_REPLYING) && option(OPTSTUFFQUOTED))
71 for (; oldpos < line + len; pos += width) {
72 /* only search a new position when we're not over
73 * the end of the string w/ pos */
74 if (pos < line + len) {
82 while (pos >= oldpos && *pos != ' ') {
87 while (pos < line + len && *pos && *pos != ' ') {
97 state_puts (s->prefix, s);
99 for (i = 0; i < ql; ++i)
101 if (!(s->flags & M_REPLYING) && option (OPTSTUFFQUOTED) &&
102 (ql > 0 || s->prefix))
104 state_puts (oldpos, s);
105 /* fprintf(stderr,"print_flowed_line: `%s'\n",oldpos); */
106 if (pos < line + len)
108 state_putc ('\n', s);
113 int rfc3676_handler (BODY * a, STATE * s) {
114 int bytes = a->length;
115 char buf[LONG_STRING];
116 char *curline = p_new(char, 1);
118 unsigned int curline_len = 1,
119 quotelevel = 0, newql = 0;
120 int buf_off, buf_len;
121 int delsp = 0, fixed = 0;
125 /* respect DelSP of RfC3676 only with f=f parts */
126 if ((t = parameter_getval(a->parameter, "delsp"))) {
127 delsp = m_strlen(t) == 3 && ascii_strncasecmp (t, "yes", 3) == 0;
132 while (bytes > 0 && fgets (buf, sizeof (buf), s->fpin)) {
134 buf_len = m_strlen(buf);
137 newql = get_quote_level (buf);
139 /* a change of quoting level in a paragraph - shouldn't happen,
140 * but has to be handled - see RFC 3676, sec. 4.5.
142 if (newql != quotelevel && curline && *curline) {
143 print_flowed_line (curline, s, quotelevel);
149 /* XXX - If a line is longer than buf (shouldn't happen), it is split.
150 * This will almost always cause an unintended line break, and
151 * possibly a change in quoting level. But that's better than not
152 * displaying it at all.
154 if ((t = strrchr (buf, '\r')) || (t = strrchr (buf, '\n'))) {
160 /* respect space-stuffing */
161 if (buf[buf_off] == ' ')
164 /* for DelSp=yes, we need to strip one SP prior to CRLF
165 * which may make the line look like fixed although it wasn't
166 * so keep this in mind for later processing */
167 fixed = buf_len == 0 || buf[buf_len - 1] != ' ' ||
168 (m_strcmp(buf + buf_off, "-- ") == 0);
170 if (delsp && buf_len >= 1 && buf[buf_len-1] == ' ')
171 buf[--buf_len] = '\0';
173 /* we're here when last space removed 'cause of DelSp was
174 * the last space and there isn't more -> done */
175 if ((buf_len - buf_off) < 0) {
176 print_flowed_line (curline, s, quotelevel);
182 /* signature separator also flushes the previous paragraph */
183 if (m_strcmp(buf + buf_off, "-- ") == 0 && curline && *curline) {
184 print_flowed_line (curline, s, quotelevel);
189 p_realloc(&curline, curline_len + buf_len - buf_off);
190 m_strcpy(curline + curline_len - 1, buf_len - buf_off + 1, buf + buf_off);
191 curline_len += buf_len - buf_off;
193 /* if this was a fixed line the paragraph is finished */
195 print_flowed_line (curline, s, quotelevel);
205 /* sets mtime of 'to' to mtime of 'from' */
206 static void mutt_set_mtime (const char* from, const char* to) {
210 if (stat (from, &st) != -1) {
211 utim.actime = st.st_mtime;
212 utim.modtime = st.st_mtime;
217 void rfc3676_space_stuff (HEADER* hdr) {
218 FILE* in = NULL, *out = NULL;
219 char buf[LONG_STRING];
220 char tmpf[_POSIX_PATH_MAX];
222 if (!hdr || !hdr->content || !hdr->content->filename)
225 if ((in = safe_fopen (hdr->content->filename, "r")) == NULL)
228 out = m_tempfile(tmpf, sizeof(tmpf), NONULL(mod_core.tmpdir), NULL);
234 while (fgets(buf, sizeof (buf), in)) {
235 if (m_strncmp("From ", buf, 4) == 0 || buf[0] == ' ') {
242 mutt_set_mtime (hdr->content->filename, tmpf);
243 unlink (hdr->content->filename);
244 m_strreplace(&hdr->content->filename, tmpf);