summaryrefslogtreecommitdiffstats
path: root/maildrop/message.h
diff options
context:
space:
mode:
Diffstat (limited to 'maildrop/message.h')
-rw-r--r--maildrop/message.h184
1 files changed, 184 insertions, 0 deletions
diff --git a/maildrop/message.h b/maildrop/message.h
new file mode 100644
index 0000000..0f6a5ee
--- /dev/null
+++ b/maildrop/message.h
@@ -0,0 +1,184 @@
+#ifndef message_h
+#define message_h
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// A Message object represents the message being filtered. It is expected
+// that the message is going to be scanned, repetitively, from start to
+// finish, in one direction. Therefore, access to the message contents is
+// sequential.
+//
+// A Message object can be initiated in two ways. It can be initiated from
+// a file. The Message object will check if the file is seekable. If so,
+// the Message object will simply use the Mio class to access the file.
+// If the file is not seekable, the message will be saved in a temporary
+// file, and the Mio class will be used to access the temporary file.
+//
+// However, if the message size turns out to be smaller the SMALLMSG bytes,
+// the message is saved in a memory buffer, and accessed from there, for
+// speed. We presume that most messages are less than SMALLMSG bytes long.
+//
+// The second way is for the messages contents to be manually specified.
+// For this initialization method, first the message is saved into the
+// memory buffer. If it proves to be too small, the message gets written
+// out into a temporary file.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include "config.h"
+#include "mio.h"
+#include "tempfile.h"
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#else
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+#endif
+
+class Buffer;
+
+class Message {
+ Mio mio;
+ TempFile tempfile;
+ char *buffer;
+ char *bufptr;
+ char *extra_headers;
+ char *extra_headersptr;
+ off_t msgsize;
+ off_t msglines;
+
+ static void readerr();
+ static void seekerr();
+public:
+ Message();
+ ~Message();
+ void Init(int); // Initialize from file descriptor
+
+ void Init(); // Begin initializing externally
+ void Init(const void *, unsigned); // From existing contents.
+ void ExtraHeaders(const Buffer &);
+ void Rewind(); // Start reading the message
+ void RewindIgnore(); // Rewind, ignore msginfo
+ int appendline(Buffer &, int=1); // Read newline-terminated line.
+ void seek(off_t);
+ off_t tell();
+ int get_c();
+ int peek();
+ off_t MessageSize();
+ off_t MessageLines() { return (msglines); }
+ void setmsgsize();
+ } ;
+
+#include "funcs.h"
+#include "maildrop.h"
+
+inline int Message::peek() // Current character.
+{
+ if (extra_headersptr)
+ return ( (unsigned char) *extra_headersptr );
+
+ if (mio.fd() >= 0)
+ {
+ errno=0;
+
+ int c=mio.peek();
+
+ if (c < 0 && errno) readerr();
+ return (c);
+ }
+
+ if (bufptr >= buffer + msgsize) return (-1);
+ return ( (int)(unsigned char)*bufptr );
+}
+
+inline int Message::get_c() // Get character.
+{
+int c;
+
+ if (extra_headersptr)
+ {
+ c= (unsigned char) *extra_headersptr++;
+ if (!*extra_headersptr) extra_headersptr=0;
+ return (c);
+ }
+
+ if (mio.fd() >= 0)
+ {
+ errno=0;
+
+ c=mio.get();
+ if (c < 0 && errno) readerr();
+ return (c);
+ }
+
+ if (bufptr >= buffer + msgsize) return (-1);
+ return ( (int)(unsigned char)*bufptr++ );
+}
+
+inline off_t Message::tell()
+{
+off_t pos;
+
+ if ( mio.fd() < 0)
+ pos=bufptr - buffer;
+ else
+ {
+ pos=mio.tell();
+ if (pos == -1) seekerr();
+ }
+ pos -= maildrop.msginfo.msgoffset;
+ if (extra_headersptr)
+ pos += extra_headersptr-extra_headers;
+ else
+ {
+ if (extra_headers) pos += strlen(extra_headers);
+ }
+ return (pos);
+}
+
+inline void Message::seek(off_t n)
+{
+int l=0;
+
+ if (extra_headers && n < (l=strlen(extra_headers)))
+ {
+ extra_headersptr= extra_headers + n;
+ n=0;
+ }
+ else
+ {
+ extra_headersptr=0;
+ n -= l;
+ }
+ n += maildrop.msginfo.msgoffset;
+
+ if (mio.fd() >= 0)
+ {
+ if (mio.seek(n, SEEK_SET) < 0) seekerr();
+ }
+ else
+ {
+ if (n > msgsize) n=msgsize;
+ bufptr=buffer+n;
+ }
+}
+
+inline off_t Message::MessageSize()
+{
+ off_t s=msgsize;
+ s -= maildrop.msginfo.msgoffset;
+ if (extra_headers)
+ s += strlen(extra_headers);
+
+ return (s);
+}
+
+#endif