--- a
+++ b/src/bincimapmime/mime-inputsource.h
@@ -0,0 +1,166 @@
+/* -*- Mode: c++; -*- */
+/*  --------------------------------------------------------------------
+ *  Filename:
+ *    src/mime-inputsource.h
+ *  
+ *  Description:
+ *    The base class of the MIME input source
+ *  --------------------------------------------------------------------
+ *  Copyright 2002-2004 Andreas Aardal Hanssen
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *  --------------------------------------------------------------------
+ */
+#ifndef mime_inputsource_h_included
+#define mime_inputsource_h_included
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <unistd.h>
+
+namespace Binc {
+
+  class MimeInputSource {
+  public:
+    inline MimeInputSource(int fd, unsigned int start = 0);
+    virtual inline ~MimeInputSource(void);
+
+    virtual inline bool fillInputBuffer(void);
+    virtual inline void reset(void);
+
+    inline void seek(unsigned int offset);
+    inline bool getChar(char *c);
+    inline void ungetChar(void);
+    inline int getFileDescriptor(void) const;
+
+    inline unsigned int getOffset(void) const;
+
+  private:
+    int fd;
+    char data[16384];
+    unsigned int offset;
+    unsigned int tail;
+    unsigned int head;
+    unsigned int start;
+    char lastChar;
+  };
+
+  inline MimeInputSource::MimeInputSource(int fd, unsigned int start)
+  {
+    this->fd = fd;
+    this->start = start;
+    offset = 0;
+    tail = 0;
+    head = 0;
+    lastChar = '\0';
+    memset(data, '\0', sizeof(data));
+
+    seek(start);
+  }
+
+  inline MimeInputSource::~MimeInputSource(void)
+  {
+  }
+
+  inline bool MimeInputSource::fillInputBuffer(void)
+  {
+    char raw[4096];
+    ssize_t nbytes = read(fd, raw, sizeof(raw));
+    if (nbytes <= 0) {
+      // FIXME: If ferror(crlffile) we should log this.
+      return false;
+    }
+
+    for (ssize_t i = 0; i < nbytes; ++i) {
+      const char c = raw[i];
+      if (c == '\r') {
+	if (lastChar == '\r') {
+	  data[tail++ & (0x4000-1)] = '\r';
+	  data[tail++ & (0x4000-1)] = '\n';
+	}
+      } else if (c == '\n') {
+	data[tail++ & (0x4000-1)] = '\r';
+	data[tail++ & (0x4000-1)] = '\n';
+      } else {
+	if (lastChar == '\r') {
+	  data[tail++ & (0x4000-1)] = '\r';
+	  data[tail++ & (0x4000-1)] = '\n';
+	}
+
+	data[tail++ & (0x4000-1)] = c;
+      }
+      
+      lastChar = c;
+    }
+
+    return true;
+  }
+
+  inline void MimeInputSource::reset(void)
+  {
+    offset = head = tail = 0;
+    lastChar = '\0';
+
+    if (fd != -1)
+      lseek(fd, 0, SEEK_SET);
+  }
+
+  inline void MimeInputSource::seek(unsigned int seekToOffset)
+  {
+    if (offset > seekToOffset)
+      reset();
+   
+    char c;
+    int n = 0;
+    while (seekToOffset > offset) {
+      if (!getChar(&c))
+	break;
+      ++n;
+    }
+  }
+
+  inline bool MimeInputSource::getChar(char *c)
+  {
+    if (head == tail && !fillInputBuffer())
+      return false;
+
+    *c = data[head++ & (0x4000-1)];
+    ++offset;
+    return true;
+  }
+
+  inline void MimeInputSource::ungetChar()
+  {
+    --head;
+    --offset;
+  }
+
+  inline int MimeInputSource::getFileDescriptor(void) const
+  {
+    return fd;
+  }
+
+  inline unsigned int MimeInputSource::getOffset(void) const
+  {
+    return offset;
+  }
+}
+
+extern Binc::MimeInputSource *mimeSource;
+
+#endif