move some files around.
[apps/madmutt.git] / lib-mime / rfc3676.c
diff --git a/lib-mime/rfc3676.c b/lib-mime/rfc3676.c
new file mode 100644 (file)
index 0000000..51b6450
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Parts were written/modified by:
+ * Andreas Krennmair <ak@synflood.at>
+ * Peter J. Holzer <hjp@hjp.net>
+ * Rocco Rutte <pdmef@cs.tu-berlin.de>
+ *
+ * This file is part of mutt-ng, see http://www.muttng.org/.
+ * It's licensed under the GNU General Public License,
+ * please see the file GPL in the top level source directory.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+
+#include <lib-lib/mem.h>
+#include <lib-lib/str.h>
+#include <lib-lib/ascii.h>
+#include <lib-lib/macros.h>
+#include <lib-lib/file.h>
+
+#include <lib-ui/curses.h>
+
+#include "mutt.h"
+#include "handler.h"
+#include "state.h"
+#include "lib.h"
+
+#define FLOWED_MAX 77
+
+static int get_quote_level (char *line)
+{
+  int quoted;
+
+  for (quoted = 0; line[quoted] == '>'; quoted++);
+  return quoted;
+}
+
+static void print_flowed_line (char *line, STATE * s, int ql) {
+  int width;
+  char *pos, *oldpos;
+  int len = m_strlen(line);
+  int i;
+
+  if (MaxLineLength > 0) {
+    width = MaxLineLength - WrapMargin - ql - 1;
+    if (!(s->flags & M_REPLYING) && option (OPTSTUFFQUOTED))
+      --width;
+    if (width < 0)
+      width = MaxLineLength;
+  }
+  else {
+    if (option (OPTMBOXPANE))
+      width = COLS - SidebarWidth - WrapMargin - ql - 1;
+    else
+      width = COLS - WrapMargin - ql - 1;
+
+    if (!(s->flags & M_REPLYING) && option (OPTSTUFFQUOTED))
+      --width;
+    if (width < 0)
+      width = COLS;
+  }
+
+  if (m_strlen(line) == 0) {
+    if (!(s->flags & M_REPLYING) || option (OPTQUOTEEMPTY)) {
+      if (s->prefix)
+        state_puts(s->prefix,s);
+      for (i=0;i<ql;++i) state_putc('>',s);
+      if (!(s->flags & M_REPLYING) && option(OPTSTUFFQUOTED))
+        state_putc(' ',s);
+    }
+    state_putc('\n',s);
+    return;
+  }
+
+  pos = line + width;
+  oldpos = line;
+
+  for (; oldpos < line + len; pos += width) {
+    /* only search a new position when we're not over
+     * the end of the string w/ pos */
+    if (pos < line + len) {
+      if (*pos == ' ') {
+        *pos = '\0';
+        ++pos;
+      }
+      else {
+        char *save = pos;
+
+        while (pos >= oldpos && *pos != ' ') {
+          --pos;
+        }
+        if (pos < oldpos) {
+          pos = save;
+          while (pos < line + len && *pos && *pos != ' ') {
+            ++pos;
+          }
+        }
+        *pos = '\0';
+        ++pos;
+      }
+    }
+
+    if (s->prefix)
+      state_puts (s->prefix, s);
+
+    for (i = 0; i < ql; ++i)
+      state_putc ('>', s);
+    if (!(s->flags & M_REPLYING) && option (OPTSTUFFQUOTED) &&
+        (ql > 0 || s->prefix))
+      state_putc (' ', s);
+    state_puts (oldpos, s);
+    /* fprintf(stderr,"print_flowed_line: `%s'\n",oldpos); */
+    if (pos < line + len)
+      state_putc (' ', s);
+    state_putc ('\n', s);
+    oldpos = pos;
+  }
+}
+
+int rfc3676_handler (BODY * a, STATE * s) {
+  int bytes = a->length;
+  char buf[LONG_STRING];
+  char *curline = p_new(char, 1);
+  char *t = NULL;
+  unsigned int curline_len = 1,
+               quotelevel = 0, newql = 0;
+  int buf_off, buf_len;
+  int delsp = 0, fixed = 0;
+
+  *curline='\0';
+
+  /* respect DelSP of RfC3676 only with f=f parts */
+  if ((t = (char*) mutt_get_parameter ("delsp", a->parameter))) {
+    delsp = m_strlen(t) == 3 && ascii_strncasecmp (t, "yes", 3) == 0;
+    t = NULL;
+  }
+
+
+  while (bytes > 0 && fgets (buf, sizeof (buf), s->fpin)) {
+
+    buf_len = m_strlen(buf);
+    bytes -= buf_len;
+
+    newql = get_quote_level (buf);
+
+    /* a change of quoting level in a paragraph - shouldn't happen, 
+     * but has to be handled - see RFC 3676, sec. 4.5.
+     */
+    if (newql != quotelevel && curline && *curline) {
+      print_flowed_line (curline, s, quotelevel);
+      *curline = '\0';
+      curline_len = 1;
+    }
+    quotelevel = newql;
+
+    /* XXX - If a line is longer than buf (shouldn't happen), it is split.
+     * This will almost always cause an unintended line break, and 
+     * possibly a change in quoting level. But that's better than not
+     * displaying it at all.
+     */
+    if ((t = strrchr (buf, '\r')) || (t = strrchr (buf, '\n'))) {
+      *t = '\0';
+      buf_len = t - buf;
+    }
+
+    buf_off = newql;
+    /* respect space-stuffing */
+    if (buf[buf_off] == ' ')
+      buf_off++;
+
+    /* for DelSp=yes, we need to strip one SP prior to CRLF
+     * which may make the line look like fixed although it wasn't
+     * so keep this in mind for later processing */
+    fixed = buf_len == 0 || buf[buf_len - 1] != ' ' ||
+            (strcmp(buf + buf_off, "-- ") == 0);
+
+    if (delsp && buf_len >= 1 && buf[buf_len-1] == ' ')
+      buf[--buf_len] = '\0';
+
+    /* we're here when last space removed 'cause of DelSp was
+     * the last space and there isn't more -> done */
+    if ((buf_len - buf_off) < 0) {
+      print_flowed_line (curline, s, quotelevel);
+      *curline = '\0';
+      curline_len = 1;
+      continue;
+    }
+
+    /* signature separator also flushes the previous paragraph */
+    if (strcmp(buf + buf_off, "-- ") == 0 && curline && *curline) {
+      print_flowed_line (curline, s, quotelevel);
+      *curline = '\0';
+      curline_len = 1;
+    }
+
+    p_realloc(&curline, curline_len + buf_len - buf_off);
+    strcpy (curline + curline_len - 1, buf + buf_off);
+    curline_len += buf_len - buf_off;
+
+    /* if this was a fixed line the paragraph is finished */
+    if (fixed) {
+      print_flowed_line (curline, s, quotelevel);
+      *curline = '\0';
+      curline_len = 1;
+    }
+
+  }
+  p_delete(&curline);
+  return (0);
+}
+
+void rfc3676_space_stuff (HEADER* hdr) {
+  FILE* in = NULL, *out = NULL;
+  char buf[LONG_STRING];
+  char tmpfile[_POSIX_PATH_MAX];
+
+  if (!hdr || !hdr->content || !hdr->content->filename)
+    return;
+
+  if ((in = safe_fopen (hdr->content->filename, "r")) == NULL)
+    return;
+  mutt_mktemp (tmpfile);
+  if ((out = safe_fopen (tmpfile, "w+")) == NULL) {
+    fclose (in);
+    return;
+  }
+
+  while (fgets (buf, sizeof (buf), in)) {
+    if (ascii_strncmp ("From ", buf, 4) == 0 || buf[0] == ' ') {
+      fputc (' ', out);
+    }
+    fputs (buf, out);
+  }
+  fclose (in);
+  fclose (out);
+  mutt_set_mtime (hdr->content->filename, tmpfile);
+  unlink (hdr->content->filename);
+  m_strreplace(&hdr->content->filename, tmpfile);
+}