initial import from bincimap-1.3.3

This commit is contained in:
dockes 2005-03-16 07:35:11 +00:00
parent 7ed16bcbf8
commit 670d7c2630
22 changed files with 3266 additions and 0 deletions

29
src/bincimapmime/Makefile Normal file
View File

@ -0,0 +1,29 @@
include ../mk/sysconf
LIBS = libmime.a
all: $(LIBS)
SRCS = mime-getpart.cc mime-parsefull.cc mime-parseonlyheader.cc \
mime-printbody.cc mime-printdoc.cc mime-printheader.cc mime.cc \
convert.cc iodevice.cc iofactory.cc
OBJS = mime-getpart.o mime-parsefull.o mime-parseonlyheader.o \
mime-printbody.o mime-printdoc.o mime-printheader.o mime.o \
convert.o iodevice.o iofactory.o
libmime.a : $(OBJS)
ar ru libmime.a $(OBJS)
# $(CXX) $(CXXFLAGS) -c $<
.cc .o :
$(CXX) $(CXXFLAGS) -c $<
clean:
rm -f *.o $(LIBS)
alldeps:depend
depend:
$(CXX) $(CXXFLAGS) -M $(SRCS) > alldeps
include alldeps

View File

@ -0,0 +1,88 @@
/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* address.cc
*
* Description:
* Implementation of the Address class.
* --------------------------------------------------------------------
* 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.
* --------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "address.h"
#include "convert.h"
#include <string>
using namespace ::std;
using namespace Binc;
//------------------------------------------------------------------------
Address::Address(const string &name, const string &addr)
{
string::size_type pos = addr.find('@');
this->name = name;
if (pos != string::npos) {
this->local = addr.substr(0, pos);
this->host = addr.substr(pos + 1);
} else this->local = addr;
}
//------------------------------------------------------------------------
Address::Address(const string &wholeaddress)
{
string::size_type start = wholeaddress.find('<');
string addr;
if (start != string::npos)
addr = wholeaddress.substr(start + 1);
else
addr = wholeaddress;
trim(addr, "<>");
if (start != string::npos)
name = wholeaddress.substr(0, start);
else
name = "";
trim(name);
trim(name, "\"");
start = addr.find('@');
local = addr.substr(0, start);
host = addr.substr(start + 1);
trim(local);
trim(host);
trim(name);
}
//------------------------------------------------------------------------
string Address::toParenList(void) const
{
string tmp = "(";
tmp += name == "" ? "NIL" : toImapString(name);
tmp += " NIL ";
tmp += local == "" ? "\"\"" : toImapString(local);
tmp += " ";
tmp += host == "" ? "\"\"" : toImapString(host);
tmp += ")";
return tmp;
}

View File

@ -0,0 +1,52 @@
/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* src/mailbox/address.h
*
* Description:
* Declaration of the Address class.
* --------------------------------------------------------------------
* 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.
* --------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef address_h_included
#define address_h_included
#include <string>
namespace Binc {
//------------------------------------------------------------------------
class Address {
public:
std::string name;
std::string local;
std::string host;
//--
std::string toParenList(void) const;
//--
Address(const std::string &name, const std::string &addr);
Address(const std::string &wholeaddr);
};
}
#endif

View File

131
src/bincimapmime/convert.cc Normal file
View File

@ -0,0 +1,131 @@
/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* convert.cc
*
* Description:
* Implementation of miscellaneous convertion functions.
* --------------------------------------------------------------------
* 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.
* --------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "convert.h"
#include <string>
using namespace ::std;
using namespace Binc;
//------------------------------------------------------------------------
BincStream::BincStream(void)
{
}
//------------------------------------------------------------------------
BincStream::~BincStream(void)
{
clear();
}
//------------------------------------------------------------------------
string BincStream::popString(unsigned int size)
{
if (size > nstr.length())
size = nstr.length();
string tmp = nstr.substr(0, size);
nstr = nstr.substr(size);
return tmp;
}
//------------------------------------------------------------------------
char BincStream::popChar(void)
{
if (nstr.length() == 0)
return '\0';
char c = nstr[0];
nstr = nstr.substr(1);
return c;
}
//------------------------------------------------------------------------
void BincStream::unpopChar(char c)
{
nstr = c + nstr;
}
//------------------------------------------------------------------------
void BincStream::unpopStr(const string &s)
{
nstr = s + nstr;
}
//------------------------------------------------------------------------
const string &BincStream::str(void) const
{
return nstr;
}
//------------------------------------------------------------------------
void BincStream::clear(void)
{
nstr = "";
}
//------------------------------------------------------------------------
unsigned int BincStream::getSize(void) const
{
return (unsigned int) nstr.length();
}
//------------------------------------------------------------------------
BincStream &BincStream::operator << (std::ostream&(*)(std::ostream&))
{
nstr += "\r\n";
return *this;
}
//------------------------------------------------------------------------
BincStream &BincStream::operator << (const string &t)
{
nstr += t;
return *this;
}
//------------------------------------------------------------------------
BincStream &BincStream::operator << (int t)
{
nstr += toString(t);
return *this;
}
//------------------------------------------------------------------------
BincStream &BincStream::operator << (unsigned int t)
{
nstr += toString(t);
return *this;
}
//------------------------------------------------------------------------
BincStream &BincStream::operator << (char t)
{
nstr += t;
return *this;
}

318
src/bincimapmime/convert.h Normal file
View File

@ -0,0 +1,318 @@
/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* src/util/convert.h
*
* Description:
* Declaration of miscellaneous convertion functions.
* --------------------------------------------------------------------
* 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.
* --------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef convert_h_included
#define convert_h_included
#include <string>
#include <vector>
#include <iomanip>
#include <iostream>
#include <stdio.h>
#include <sys/stat.h>
#include "address.h"
#include "depot.h"
namespace Binc {
//----------------------------------------------------------------------
inline std::string toString(int i_in)
{
char intbuf[16];
snprintf(intbuf, sizeof(intbuf), "%d", i_in);
return std::string(intbuf);
}
//----------------------------------------------------------------------
inline std::string toString(unsigned int i_in)
{
char intbuf[16];
snprintf(intbuf, sizeof(intbuf), "%u", i_in);
return std::string(intbuf);
}
//----------------------------------------------------------------------
inline std::string toString(unsigned long i_in)
{
char longbuf[40];
snprintf(longbuf, sizeof(longbuf), "%lu", i_in);
return std::string(longbuf);
}
//----------------------------------------------------------------------
inline std::string toString(const char *i_in)
{
return std::string(i_in);
}
//----------------------------------------------------------------------
inline int atoi(const std::string &s_in)
{
return ::atoi(s_in.c_str());
}
//----------------------------------------------------------------------
inline std::string toHex(const std::string &s)
{
const char hexchars[] = "0123456789abcdef";
std::string tmp;
for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
unsigned char c = (unsigned char)*i;
tmp += hexchars[((c & 0xf0) >> 4)];
tmp += hexchars[c & 0x0f];
}
return tmp;
}
//----------------------------------------------------------------------
inline std::string fromHex(const std::string &s)
{
const char hexchars[] = "0123456789abcdef";
std::string tmp;
for (std::string::const_iterator i = s.begin();
i != s.end() && i + 1 != s.end(); i += 2) {
int n;
unsigned char c = *i;
unsigned char d = *(i + 1);
char *t;
if ((t = strchr(hexchars, c)) == 0)
return "out of range";
n = (t - hexchars) << 4;
if ((t = strchr(hexchars, d)) == 0)
return "out of range";
n += (t - hexchars);
if (n >= 0 && n <= 255)
tmp += (char) n;
else
return "out of range";
}
return tmp;
}
//----------------------------------------------------------------------
inline std::string toImapString(const std::string &s_in)
{
for (std::string::const_iterator i = s_in.begin(); i != s_in.end(); ++i) {
unsigned char c = (unsigned char)*i;
if (c <= 31 || c >= 127 || c == '\"' || c == '\\')
return "{" + toString(s_in.length()) + "}\r\n" + s_in;
}
return "\"" + s_in + "\"";
}
//----------------------------------------------------------------------
inline void uppercase(std::string &input)
{
for (std::string::iterator i = input.begin(); i != input.end(); ++i)
*i = toupper(*i);
}
//----------------------------------------------------------------------
inline void lowercase(std::string &input)
{
for (std::string::iterator i = input.begin(); i != input.end(); ++i)
*i = tolower(*i);
}
//----------------------------------------------------------------------
inline void chomp(std::string &s_in, const std::string &chars = " \t\r\n")
{
int n = s_in.length();
while (n > 1 && chars.find(s_in[n - 1]) != std::string::npos)
s_in.resize(n-- - 1);
}
//----------------------------------------------------------------------
inline void trim(std::string &s_in, const std::string &chars = " \t\r\n")
{
while (s_in != "" && chars.find(s_in[0]) != std::string::npos)
s_in = s_in.substr(1);
chomp(s_in, chars);
}
//----------------------------------------------------------------------
inline const std::string unfold(const std::string &a,
bool removecomment = true)
{
std::string tmp;
bool incomment = false;
bool inquotes = false;
for (std::string::const_iterator i = a.begin(); i != a.end(); ++i) {
unsigned char c = (unsigned char)*i;
if (!inquotes && removecomment) {
if (c == '(') {
incomment = true;
tmp += " ";
} else if (c == ')') {
incomment = false;
} else if (c != 0x0a && c != 0x0d) {
tmp += *i;
}
} else if (c != 0x0a && c != 0x0d) {
tmp += *i;
}
if (!incomment) {
if (*i == '\"')
inquotes = !inquotes;
}
}
trim(tmp);
return tmp;
}
//----------------------------------------------------------------------
inline void split(const std::string &s_in, const std::string &delim,
std::vector<std::string> &dest, bool skipempty = true)
{
std::string token;
for (std::string::const_iterator i = s_in.begin(); i != s_in.end(); ++i) {
if (delim.find(*i) != std::string::npos) {
if (!skipempty || token != "")
dest.push_back(token);
token = "";
} else
token += *i;
}
if (token != "")
dest.push_back(token);
}
//----------------------------------------------------------------------
inline void splitAddr(const std::string &s_in,
std::vector<std::string> &dest, bool skipempty = true)
{
static const std::string delim = ",";
std::string token;
bool inquote = false;
for (std::string::const_iterator i = s_in.begin(); i != s_in.end(); ++i) {
if (inquote && *i == '\"') inquote = false;
else if (!inquote && *i == '\"') inquote = true;
if (!inquote && delim.find(*i) != std::string::npos) {
if (!skipempty || token != "")
dest.push_back(token);
token = "";
} else
token += *i;
}
if (token != "")
dest.push_back(token);
}
//----------------------------------------------------------------------
inline std::string toCanonMailbox(const std::string &s_in)
{
if (s_in.find("..") != std::string::npos) return "";
if (s_in.length() >= 5) {
std::string a = s_in.substr(0, 5);
uppercase(a);
return a == "INBOX" ?
a + (s_in.length() > 5 ? s_in.substr(5) : "") : s_in;
}
return s_in;
}
//------------------------------------------------------------------------
inline std::string toRegex(const std::string &s_in, char delimiter)
{
std::string regex = "^";
for (std::string::const_iterator i = s_in.begin(); i != s_in.end(); ++i) {
if (*i == '.' || *i == '[' || *i == ']' || *i == '{' || *i == '}' ||
*i == '(' || *i == ')' || *i == '^' || *i == '$' || *i == '?' ||
*i == '+' || *i == '\\') {
regex += "\\";
regex += *i;
} else if (*i == '*')
regex += ".*?";
else if (*i == '%') {
regex += "[^\\";
regex += delimiter;
regex += "]*?";
} else regex += *i;
}
if (regex[regex.length() - 1] == '?')
regex[regex.length() - 1] = '$';
else
regex += "$";
return regex;
}
//------------------------------------------------------------------------
class BincStream {
private:
std::string nstr;
public:
//--
BincStream &operator << (std::ostream&(*)(std::ostream&));
BincStream &operator << (const std::string &t);
BincStream &operator << (unsigned int t);
BincStream &operator << (int t);
BincStream &operator << (char t);
//--
std::string popString(unsigned int size);
//--
char popChar(void);
void unpopChar(char c);
void unpopStr(const std::string &s);
//--
const std::string &str(void) const;
//--
unsigned int getSize(void) const;
//--
void clear(void);
//--
BincStream(void);
~BincStream(void);
};
}
#endif

0
src/bincimapmime/depot.h Normal file
View File

View File

@ -0,0 +1,317 @@
/*-*-mode:c++-*-*/
/* --------------------------------------------------------------------
* Filename:
* src/iodevice.cc
*
* Description:
* Implementation of the IODevice class.
* --------------------------------------------------------------------
* Copyright 2002, 2003 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.
* --------------------------------------------------------------------
*/
#include "iodevice.h"
#include "convert.h" // BincStream
#include "session.h" // getEnv/hasEnv
#include <stdlib.h>
#include <unistd.h>
using namespace ::std;
using namespace ::Binc;
//------------------------------------------------------------------------
IODevice::IODevice(int f) : flags(f | IsEnabled),
maxInputBufferSize(0),
maxOutputBufferSize(0),
timeout(0),
readCount(0), writeCount(0),
outputLevel(0), outputLevelLimit(0),
error(Unknown), errorString("Unknown error"),
dumpfd(0)
{
}
//------------------------------------------------------------------------
IODevice::~IODevice(void)
{
}
//------------------------------------------------------------------------
IODevice &IODevice::operator <<(ostream &(*source)(ostream &))
{
if (!(flags & IsEnabled) || outputLevel > outputLevelLimit)
return *this;
static std::ostream &(*endl_funcptr)(ostream &) = endl;
if (source != endl_funcptr)
return *this;
outputBuffer << "\r\n";
if (dumpfd)
::write(dumpfd, "\r\n", 2);
if (flags & FlushesOnEndl)
flush();
else if (flags & HasOutputLimit)
if (outputBuffer.getSize() > maxOutputBufferSize)
flush();
return *this;
}
//------------------------------------------------------------------------
bool IODevice::canRead(void) const
{
return false;
}
//------------------------------------------------------------------------
void IODevice::clear()
{
if (!(flags & IsEnabled))
return;
inputBuffer.clear();
outputBuffer.clear();
}
//------------------------------------------------------------------------
bool IODevice::flush()
{
if (!(flags & IsEnabled))
return true;
WriteResult writeResult = WriteWait;
do {
unsigned int s = outputBuffer.getSize();
if (s == 0)
break;
if (!waitForWrite())
return false;
writeResult = write();
if (writeResult == WriteError)
return false;
writeCount += s - outputBuffer.getSize();
} while (outputBuffer.getSize() > 0 && writeResult == WriteWait);
outputBuffer.clear();
return true;
}
//------------------------------------------------------------------------
void IODevice::setFlags(unsigned int f)
{
flags |= f;
}
//------------------------------------------------------------------------
void IODevice::clearFlags(unsigned int f)
{
flags &= ~f;
}
//------------------------------------------------------------------------
void IODevice::setMaxInputBufferSize(unsigned int max)
{
maxInputBufferSize = max;
}
//------------------------------------------------------------------------
void IODevice::setMaxOutputBufferSize(unsigned int max)
{
maxOutputBufferSize = max;
}
//------------------------------------------------------------------------
void IODevice::setTimeout(unsigned int t)
{
timeout = t;
if (t)
flags |= HasTimeout;
else
flags &= ~HasTimeout;
}
//------------------------------------------------------------------------
unsigned int IODevice::getTimeout(void) const
{
return timeout;
}
//------------------------------------------------------------------------
void IODevice::setOutputLevel(unsigned int level)
{
outputLevel = level;
}
//------------------------------------------------------------------------
unsigned int IODevice::getOutputLevel(void) const
{
return outputLevel;
}
//------------------------------------------------------------------------
void IODevice::setOutputLevelLimit(unsigned int level)
{
outputLevelLimit = level;
}
//------------------------------------------------------------------------
unsigned int IODevice::getOutputLevelLimit(void) const
{
return outputLevelLimit;
}
//------------------------------------------------------------------------
bool IODevice::readStr(string *dest, unsigned int max)
{
// If max is 0, fill the input buffer once only if it's empty.
if (!max && inputBuffer.getSize() == 0 && !fillInputBuffer())
return false;
// If max is != 0, wait until we have max.
while (max && inputBuffer.getSize() < max) {
if (!fillInputBuffer())
return false;
}
unsigned int bytesToRead = max ? max : inputBuffer.getSize();
*dest += inputBuffer.str().substr(0, bytesToRead);
if (dumpfd) {
::write(dumpfd, inputBuffer.str().substr(0, bytesToRead).c_str(),
bytesToRead);
}
inputBuffer.popString(bytesToRead);
readCount += bytesToRead;
return true;
}
//------------------------------------------------------------------------
bool IODevice::readChar(char *dest)
{
if (inputBuffer.getSize() == 0 && !fillInputBuffer())
return false;
char c = inputBuffer.popChar();
if (dest)
*dest = c;
if (dumpfd)
::write(dumpfd, &c, 1);
++readCount;
return true;
}
//------------------------------------------------------------------------
void IODevice::unreadChar(char c)
{
inputBuffer.unpopChar(c);
}
//------------------------------------------------------------------------
void IODevice::unreadStr(const string &s)
{
inputBuffer.unpopStr(s);
}
//------------------------------------------------------------------------
bool IODevice::skipTo(char c)
{
char dest = '\0';
do {
if (!readChar(&dest))
return false;
if (dumpfd)
::write(dumpfd, &dest, 1);
} while (c != dest);
return true;
}
//------------------------------------------------------------------------
string IODevice::service(void) const
{
return "nul";
}
//------------------------------------------------------------------------
bool IODevice::waitForWrite(void) const
{
return false;
}
//------------------------------------------------------------------------
bool IODevice::waitForRead(void) const
{
return false;
}
//------------------------------------------------------------------------
IODevice::WriteResult IODevice::write(void)
{
return WriteError;
}
//------------------------------------------------------------------------
bool IODevice::fillInputBuffer(void)
{
return false;
}
//------------------------------------------------------------------------
IODevice::Error IODevice::getLastError(void) const
{
return error;
}
//------------------------------------------------------------------------
string IODevice::getLastErrorString(void) const
{
return errorString;
}
//------------------------------------------------------------------------
unsigned int IODevice::getReadCount(void) const
{
return readCount;
}
//------------------------------------------------------------------------
unsigned int IODevice::getWriteCount(void) const
{
return writeCount;
}
//------------------------------------------------------------------------
void IODevice::enableProtocolDumping(void)
{
BincStream ss;
ss << "/tmp/bincimap-dump-" << (int) time(0) << "-"
<< Session::getInstance().getIP() << "-XXXXXX";
char *safename = strdup(ss.str().c_str());
dumpfd = mkstemp(safename);
if (dumpfd == -1)
dumpfd = 0;
delete safename;
}

389
src/bincimapmime/iodevice.h Normal file
View File

@ -0,0 +1,389 @@
/*-*-mode:c++-*-*/
/* --------------------------------------------------------------------
* Filename:
* src/iodevice.h
*
* Description:
* Declaration of the IODevice class.
* --------------------------------------------------------------------
* Copyright 2002, 2003 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 iodevice_h_included
#define iodevice_h_included
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "convert.h" // BincStream
#include <string>
#include <unistd.h> // ::write
namespace Binc {
/*!
\class IODevice
\brief The IODevice class provides a framework for reading and
writing to device.
Implement new devices by inheriting this class and overloading all
virtual methods.
service() returns the service that the specific device is used
for. Two values are "log" and "client".
\sa IOFactory, MultilogDevice, SyslogDevice, StdIODevice, SSLDevice
*/
class IODevice {
public:
/*!
Standard options for an IODevice.
*/
enum Flags {
None = 0,
FlushesOnEndl = 1 << 0,
HasInputLimit = 1 << 1,
HasOutputLimit = 1 << 2,
IsEnabled = 1 << 3,
HasTimeout = 1 << 4
};
/*!
Errors from when an operation returned false.
*/
enum Error {
Unknown,
Timeout
};
/*!
Constructs an invalid IODevice.
Instances of IODevice perform no operations, and all boolean
functions always return false. This constructor is only useful
if called from a subclass that reimplements all virtual methods.
*/
IODevice(int f = 0);
/*!
Destructs an IODevice; does nothing.
*/
virtual ~IODevice(void);
/*!
Clears all data in the input and output buffers.
*/
void clear(void);
/*!
Sets one or more flags.
\param f A bitwise OR of flags from the Flags enum.
*/
void setFlags(unsigned int f);
/*!
Clears one or more flags.
\param f A bitwise OR of flags from the Flags enum.
*/
void clearFlags(unsigned int f);
/*!
Sets the maximum allowed input buffer size. If this size is
non-zero and exceeded, reading from the device will fail. This
functionality is used to prevent clients from forcing this class
to consume so much memory that the program crashes.
Setting the max input buffer size to 0 disables the input size
limit.
\param max The maximum input buffer size in bytes.
*/
void setMaxInputBufferSize(unsigned int max);
/*!
Sets the maximum allowed output buffer size. If this size is
non-zero and exceeded, flush() is called implicitly.
Setting the max output buffer size to 0 disables the output size
limit. This is generally discouraged.
As a contrast to setMaxInputBufferSize(), this function is used
to bundle up consequent write calls, allowing more efficient use
of the underlying device as larger blocks of data are written at
a time.
\param max The maximum output buffer size in bytes.
*/
void setMaxOutputBufferSize(unsigned int max);
/*!
Sets the device's internal timeout in seconds. This timeout is
used both when waiting for data to read and for waiting for the
ability to write.
If this timeout is exceeded, the read or write function that
triggered the timeout will fail.
Setting the timeout to 0 disables the timeout.
\param t The timeout in seconds.
\sa getTimeout()
*/
void setTimeout(unsigned int t);
/*!
Returns the timeout in seconds, or 0 if there is no timeout.
\sa setTimeout()
*/
unsigned int getTimeout(void) const;
/*!
Sets the output level for the following write operations on this
device.
The output level is a number which gives the following write
operations a priority. You can use setOutputLevelLimit() to
filter the write operations valid for different operating modes.
This enables you to have certain write operations ignored.
For instance, if the output level is set to 0, then "Hello" is
written, and the output level is set to 1, followed by writing
"Daisy", the output level limit value will decive wether only
"Hello" is written, or if also "Daisy" is written.
A low value of the level gives higher priority, and a high level
will give low priority. The default value is 0, and write
operations that are done with output level 0 are never ignored.
\param level The output level
\sa getOutputLevel(), setOutputLevelLimit()
*/
void setOutputLevel(unsigned int level);
/*!
Returns the current output level.
\sa setOutputLevel()
*/
unsigned int getOutputLevel(void) const;
/*!
Sets the current output level limit. Write operations with a
level higher than the output level limit are ignored.
\param level The output level limit
\sa setOutputLevel()
*/
void setOutputLevelLimit(unsigned int level);
/*!
Returns the current output level limit.
\sa setOutputLevelLimit()
*/
unsigned int getOutputLevelLimit(void) const;
/*!
Returns the number of bytes that have been read from this device
since it was created.
*/
unsigned int getReadCount(void) const;
/*!
Returns the number of bytes that have been written to this
device since it was created.
*/
unsigned int getWriteCount(void) const;
void enableProtocolDumping(void);
/*!
Writes data to the device. Depending on the value of the max
output buffer size, the data may not be written immediately.
\sa setMaxOutputBufferSize()
*/
template <class T> IODevice &operator <<(const T &source);
/*!
Writes data to the device. This function specializes on standard
ostream derivates, such as std::endl.
*/
IODevice &operator <<(std::ostream &(*source)(std::ostream &));
/*!
Returns true if data can be read from the device; otherwise
returns false.
*/
virtual bool canRead(void) const;
/*!
Reads data from the device, and stores this in a string. Returns
true on success; otherwise returns false.
\param dest The incoming data is stored in this string.
\param max No more than this number of bytes is read from the
device.
*/
bool readStr(std::string *dest, unsigned int max = 0);
/*!
Reads exactly one byte from the device and stores this in a
char. Returns true on success; otherwise returns false.
\param dest The incoming byte is stored in this char.
*/
bool readChar(char *dest = 0);
/*!
FIXME: add docs
*/
void unreadChar(char c);
/*!
FIXME: add docs
*/
void unreadStr(const std::string &s);
/*!
Reads characters from the device, until and including one
certain character is found. All read characters are discarded.
This function can be used to skip to the beginning of a line,
with the terminating character being '\n'.
\param The certain character.
*/
bool skipTo(char c);
/*!
Flushes the output buffer. Writes all data in the output buffer
to the device.
*/
bool flush(void);
/*!
Returns the type of error that most recently occurred.
*/
Error getLastError(void) const;
/*!
Returns a human readable description of the error that most
recently occurred. If no known error has occurred, this method
returns "Unknown error".
*/
std::string getLastErrorString(void) const;
/*!
Returns the type of service provided by this device. Two valid
return values are "client" and "log".
*/
virtual std::string service(void) const;
protected:
/*!
Waits until data can be written to the device. If the timeout is
0, this function waits indefinitely. Otherwise, it waits until
the timeout has expired.
If this function returns true, data can be written to the
device; otherwise, getLastError() must be checked to determine
whether a timeout occurred or whether an error with the device
prevents further writing.
*/
virtual bool waitForWrite(void) const;
/*!
Waits until data can be read from the device.
\sa waitForWrite()
*/
virtual bool waitForRead(void) const;
/*!
Types of results from a write.
*/
enum WriteResult {
WriteWait = 0,
WriteDone = 1 << 0,
WriteError = 1 << 1
};
/*!
Writes as much data as possible to the device. If some but not
all data was written, returns WriteWait. If all data was
written, returns WriteDone. If an error occurred, returns
WriteError.
*/
virtual WriteResult write(void);
/*!
Reads data from the device, and stores it in the input buffer.
Returns true on success; otherwise returns false.
This method will fail if there is no more data available, if a
timeout occurred or if an error with the device prevents more
data from being read.
The number of bytes read from the device is undefined.
*/
virtual bool fillInputBuffer(void);
BincStream inputBuffer;
BincStream outputBuffer;
protected:
unsigned int flags;
unsigned int maxInputBufferSize;
unsigned int maxOutputBufferSize;
unsigned int timeout;
unsigned int readCount;
unsigned int writeCount;
unsigned int outputLevel;
unsigned int outputLevelLimit;
Error error;
std::string errorString;
int dumpfd;
};
//----------------------------------------------------------------------
template <class T> IODevice &IODevice::operator <<(const T &source)
{
if ((flags & IsEnabled) && outputLevel <= outputLevelLimit) {
outputBuffer << source;
if (dumpfd) {
BincStream ss;
ss << source;
::write(dumpfd, ss.str().c_str(), ss.getSize());
}
if (flags & HasInputLimit)
if (outputBuffer.getSize() > maxOutputBufferSize)
flush();
}
return *this;
}
}
#endif

View File

@ -0,0 +1,85 @@
/*-*-mode:c++-*-*/
/* --------------------------------------------------------------------
* Filename:
* src/iofactory.cc
*
* Description:
* Implementation of the IOFactory class.
* --------------------------------------------------------------------
* Copyright 2002, 2003 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.
* --------------------------------------------------------------------
*/
#include "iofactory.h"
#include "iodevice.h"
using namespace ::Binc;
using namespace ::std;
//------------------------------------------------------------------------
IOFactory::IOFactory(void)
{
}
//------------------------------------------------------------------------
IOFactory::~IOFactory(void)
{
}
//------------------------------------------------------------------------
IOFactory &IOFactory::getInstance(void)
{
static IOFactory ioFactory;
return ioFactory;
}
//------------------------------------------------------------------------
void IOFactory::addDevice(IODevice *dev)
{
IODevice *ioDevice = IOFactory::getInstance().devices[dev->service()];
// FIXME: Delete correct object. Now, only IODevice's destructor is
// called, and only IODevice's memory is freed.
if (ioDevice)
delete ioDevice;
IOFactory::getInstance().devices[dev->service()] = dev;
}
//------------------------------------------------------------------------
IODevice &IOFactory::getClient(void)
{
static IODevice nulDevice;
IOFactory &ioFactory = IOFactory::getInstance();
if (ioFactory.devices.find("client") != ioFactory.devices.end())
return *ioFactory.devices["client"];
return nulDevice;
}
//------------------------------------------------------------------------
IODevice &IOFactory::getLogger(void)
{
static IODevice nulDevice;
IOFactory &ioFactory = IOFactory::getInstance();
if (ioFactory.devices.find("log") != ioFactory.devices.end())
return *ioFactory.devices["log"];
return nulDevice;
}

View File

@ -0,0 +1,68 @@
/*-*-mode:c++-*-*/
/* --------------------------------------------------------------------
* Filename:
* src/iofactory.h
*
* Description:
* Declaration of the IOFactory class.
* --------------------------------------------------------------------
* Copyright 2002, 2003 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 IOFACTORY_H_INCLUDED
#define IOFACTORY_H_INCLUDED
#include <map>
#include <string>
namespace Binc {
class IODevice;
class IOFactory {
public:
~IOFactory(void);
static void addDevice(IODevice *dev);
static IOFactory &getInstance(void);
static IODevice &getClient(void);
static IODevice &getLogger(void);
private:
IOFactory(void);
std::map<std::string, IODevice *> devices;
};
}
#define bincClient \
IOFactory::getClient()
#if !defined (DEBUG)
#define bincError if (false) std::cout
#define bincWarning if (false) std::cout
#define bincDebug if (false) std::cout
#else
#define bincError \
IOFactory::getLogger().setOutputLevel(0);IOFactory::getLogger()
#define bincWarning \
IOFactory::getLogger().setOutputLevel(2);IOFactory::getLogger()
#define bincDebug \
IOFactory::getLogger().setOutputLevel(3);IOFactory::getLogger()
#endif
#define bincInfo \
IOFactory::getLogger().setOutputLevel(1);IOFactory::getLogger()
#endif

View File

@ -0,0 +1,94 @@
/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* mime-getpart.cc
*
* Description:
* Implementation of main mime parser components
* --------------------------------------------------------------------
* 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.
* --------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "mime.h"
#include "convert.h"
#include <string>
#include <vector>
#include <map>
#include <exception>
#include <iostream>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
using namespace ::std;
//------------------------------------------------------------------------
const Binc::MimePart *Binc::MimePart::getPart(const string &findpart,
string genpart, FetchType fetchType) const
{
if (findpart == genpart)
return this;
if (isMultipart()) {
if (members.size() != 0) {
vector<MimePart>::const_iterator i = members.begin();
int part = 1;
while (i != members.end()) {
BincStream ss;
ss << genpart;
if (genpart != "")
ss << ".";
ss << part;
const MimePart *m;
if ((m = (*i).getPart(findpart, ss.str())) != 0) {
if (fetchType == FetchHeader && m->isMessageRFC822())
m = &m->members[0];
return m;
}
++i;
++part;
}
}
} else if (isMessageRFC822()) {
if (members.size() == 1) {
const MimePart *m = members[0].getPart(findpart, genpart);
return m;
} else {
return 0;
}
} else {
// Singlepart
if (genpart != "")
genpart += ".";
genpart += "1";
if (findpart == genpart)
return this;
}
return 0;
}

View File

@ -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

View File

@ -0,0 +1,666 @@
/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* mime-parsefull.cc
*
* Description:
* Implementation of main mime parser components
* --------------------------------------------------------------------
* 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.
* --------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "mime.h"
#include "mime-utils.h"
#include "mime-inputsource.h"
#include "convert.h"
#include <string>
#include <vector>
#include <map>
#include <exception>
#include <iostream>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
Binc::MimeInputSource *mimeSource = 0;
using namespace ::std;
//------------------------------------------------------------------------
void Binc::MimeDocument::parseFull(int fd) const
{
if (allIsParsed)
return;
allIsParsed = true;
if (!mimeSource || mimeSource->getFileDescriptor() != fd) {
delete mimeSource;
mimeSource = new MimeInputSource(fd);
} else {
mimeSource->reset();
}
headerstartoffsetcrlf = 0;
headerlength = 0;
bodystartoffsetcrlf = 0;
bodylength = 0;
size = 0;
messagerfc822 = false;
multipart = false;
int bsize = 0;
string bound;
MimePart::parseFull(bound, bsize);
// eat any trailing junk to get the correct size
char c;
while (mimeSource->getChar(&c));
size = mimeSource->getOffset();
}
//------------------------------------------------------------------------
static bool parseOneHeaderLine(Binc::Header *header, unsigned int *nlines)
{
using namespace ::Binc;
char c;
bool eof = false;
char cqueue[4];
string name;
string content;
while (mimeSource->getChar(&c)) {
// If we encounter a \r before we got to the first ':', then
// rewind back to the start of the line and assume we're at the
// start of the body.
if (c == '\r') {
for (int i = 0; i < (int) name.length() + 1; ++i)
mimeSource->ungetChar();
return false;
}
// A colon marks the end of the header name
if (c == ':') break;
// Otherwise add to the header name
name += c;
}
cqueue[0] = '\0';
cqueue[1] = '\0';
cqueue[2] = '\0';
cqueue[3] = '\0';
// Read until the end of the header.
bool endOfHeaders = false;
while (!endOfHeaders) {
if (!mimeSource->getChar(&c)) {
eof = true;
break;
}
if (c == '\n') ++*nlines;
for (int i = 0; i < 3; ++i)
cqueue[i] = cqueue[i + 1];
cqueue[3] = c;
if (strncmp(cqueue, "\r\n\r\n", 4) == 0) {
endOfHeaders = true;
break;
}
// If the last character was a newline, and the first now is not
// whitespace, then rewind one character and store the current
// key,value pair.
if (cqueue[2] == '\n' && c != ' ' && c != '\t') {
if (content.length() > 2)
content.resize(content.length() - 2);
trim(content);
header->add(name, content);
if (c != '\r') {
mimeSource->ungetChar();
if (c == '\n') --*nlines;
return true;
}
mimeSource->getChar(&c);
return false;
}
content += c;
}
if (name != "") {
if (content.length() > 2)
content.resize(content.length() - 2);
header->add(name, content);
}
return !(eof || endOfHeaders);
}
//------------------------------------------------------------------------
static void parseHeader(Binc::Header *header, unsigned int *nlines)
{
while (parseOneHeaderLine(header, nlines))
{ }
}
//------------------------------------------------------------------------
static void analyzeHeader(Binc::Header *header, bool *multipart,
bool *messagerfc822, string *subtype,
string *boundary)
{
using namespace ::Binc;
// Do simple parsing of headers to determine the
// type of message (multipart,messagerfc822 etc)
HeaderItem ctype;
if (header->getFirstHeader("content-type", ctype)) {
vector<string> types;
split(ctype.getValue(), ";", types);
if (types.size() > 0) {
// first element should describe content type
string tmp = types[0];
trim(tmp);
vector<string> v;
split(tmp, "/", v);
string key, value;
key = (v.size() > 0) ? v[0] : "text";
value = (v.size() > 1) ? v[1] : "plain";
lowercase(key);
if (key == "multipart") {
*multipart = true;
lowercase(value);
*subtype = value;
} else if (key == "message") {
lowercase(value);
if (value == "rfc822")
*messagerfc822 = true;
}
}
for (vector<string>::const_iterator i = types.begin();
i != types.end(); ++i) {
string element = *i;
trim(element);
if (element.find("=") != string::npos) {
string::size_type pos = element.find('=');
string key = element.substr(0, pos);
string value = element.substr(pos + 1);
lowercase(key);
trim(key);
if (key == "boundary") {
trim(value, " \"");
*boundary = value;
}
}
}
}
}
static void parseMessageRFC822(vector<Binc::MimePart> *members,
bool *foundendofpart,
unsigned int *bodylength,
unsigned int *nbodylines,
const string &toboundary)
{
using namespace ::Binc;
// message rfc822 means a completely enclosed mime document. we
// call the parser recursively, and pass on the boundary string
// that we got. when parse() finds this boundary, it returns 0. if
// it finds the end boundary (boundary + "--"), it returns != 0.
MimePart m;
unsigned int bodystartoffsetcrlf = mimeSource->getOffset();
// parsefull returns the number of bytes that need to be removed
// from the body because of the terminating boundary string.
int bsize = 0;
if (m.parseFull(toboundary, bsize))
*foundendofpart = true;
// make sure bodylength doesn't overflow
*bodylength = mimeSource->getOffset();
if (*bodylength >= bodystartoffsetcrlf) {
*bodylength -= bodystartoffsetcrlf;
if (*bodylength >= (unsigned int) bsize) {
*bodylength -= (unsigned int) bsize;
} else {
*bodylength = 0;
}
} else {
*bodylength = 0;
}
*nbodylines += m.getNofLines();
members->push_back(m);
}
static bool skipUntilBoundary(const string &delimiter,
unsigned int *nlines, bool *eof)
{
int endpos = delimiter.length();
char *delimiterqueue = 0;
int delimiterpos = 0;
const char *delimiterStr = delimiter.c_str();
if (delimiter != "") {
delimiterqueue = new char[endpos];
memset(delimiterqueue, 0, endpos);
}
// first, skip to the first delimiter string. Anything between the
// header and the first delimiter string is simply ignored (it's
// usually a text message intended for non-mime clients)
char c;
bool foundBoundary = false;
for (;;) {
if (!mimeSource->getChar(&c)) {
*eof = true;
break;
}
if (c == '\n')
++*nlines;
// if there is no delimiter, we just read until the end of the
// file.
if (!delimiterqueue)
continue;
delimiterqueue[delimiterpos++ % endpos] = c;
if (compareStringToQueue(delimiterStr, delimiterqueue,
delimiterpos, endpos)) {
foundBoundary = true;
break;
}
}
delete [] delimiterqueue;
delimiterqueue = 0;
return foundBoundary;
}
static void parseMultipart(const string &boundary,
const string &toboundary,
bool *eof,
unsigned int *nlines,
int *boundarysize,
bool *foundendofpart,
unsigned int *bodylength,
vector<Binc::MimePart> *members)
{
using namespace ::Binc;
unsigned int bodystartoffsetcrlf = mimeSource->getOffset();
// multipart parsing starts with skipping to the first
// boundary. then we call parse() for all parts. the last parse()
// command will return a code indicating that it found the last
// boundary of this multipart. Note that the first boundary does
// not have to start with CRLF.
string delimiter = "--" + boundary;
skipUntilBoundary(delimiter, nlines, eof);
if (!eof)
*boundarysize = delimiter.size();
// Read two more characters. This may be CRLF, it may be "--" and
// it may be any other two characters.
char a;
if (!mimeSource->getChar(&a))
*eof = true;
if (a == '\n')
++*nlines;
char b;
if (!mimeSource->getChar(&b))
*eof = true;
if (b == '\n')
++*nlines;
// If we find two dashes after the boundary, then this is the end
// of boundary marker.
if (!*eof) {
if (a == '-' && b == '-') {
*foundendofpart = true;
*boundarysize += 2;
if (!mimeSource->getChar(&a))
*eof = true;
if (a == '\n')
++*nlines;
if (!mimeSource->getChar(&b))
*eof = true;
if (b == '\n')
++*nlines;
}
if (a == '\r' && b == '\n') {
// This exception is to handle a special case where the
// delimiter of one part is not followed by CRLF, but
// immediately followed by a CRLF prefixed delimiter.
if (!mimeSource->getChar(&a) || !mimeSource->getChar(&b))
*eof = true;
else if (a == '-' && b == '-') {
mimeSource->ungetChar();
mimeSource->ungetChar();
mimeSource->ungetChar();
mimeSource->ungetChar();
} else {
mimeSource->ungetChar();
mimeSource->ungetChar();
}
*boundarysize += 2;
} else {
mimeSource->ungetChar();
mimeSource->ungetChar();
}
}
// read all mime parts.
if (!*foundendofpart && !*eof) {
bool quit = false;
do {
MimePart m;
// If parseFull returns != 0, then it encountered the multipart's
// final boundary.
int bsize = 0;
if (m.parseFull(boundary, bsize)) {
quit = true;
*boundarysize = bsize;
}
members->push_back(m);
} while (!quit);
}
if (!*foundendofpart && !*eof) {
// multipart parsing starts with skipping to the first
// boundary. then we call parse() for all parts. the last parse()
// command will return a code indicating that it found the last
// boundary of this multipart. Note that the first boundary does
// not have to start with CRLF.
string delimiter = "\r\n--" + toboundary;
skipUntilBoundary(delimiter, nlines, eof);
if (!*eof)
*boundarysize = delimiter.size();
// Read two more characters. This may be CRLF, it may be "--" and
// it may be any other two characters.
char a = '\0';
if (!mimeSource->getChar(&a))
*eof = true;
if (a == '\n')
++*nlines;
char b = '\0';
if (!mimeSource->getChar(&b))
*eof = true;
if (b == '\n')
++*nlines;
// If we find two dashes after the boundary, then this is the end
// of boundary marker.
if (!*eof) {
if (a == '-' && b == '-') {
*foundendofpart = true;
*boundarysize += 2;
if (!mimeSource->getChar(&a))
*eof = true;
if (a == '\n')
++*nlines;
if (!mimeSource->getChar(&b))
*eof = true;
if (b == '\n')
++*nlines;
}
if (a == '\r' && b == '\n') {
// This exception is to handle a special case where the
// delimiter of one part is not followed by CRLF, but
// immediately followed by a CRLF prefixed delimiter.
if (!mimeSource->getChar(&a) || !mimeSource->getChar(&b))
*eof = true;
else if (a == '-' && b == '-') {
mimeSource->ungetChar();
mimeSource->ungetChar();
mimeSource->ungetChar();
mimeSource->ungetChar();
} else {
mimeSource->ungetChar();
mimeSource->ungetChar();
}
*boundarysize += 2;
} else {
mimeSource->ungetChar();
mimeSource->ungetChar();
}
}
}
// make sure bodylength doesn't overflow
*bodylength = mimeSource->getOffset();
if (*bodylength >= bodystartoffsetcrlf) {
*bodylength -= bodystartoffsetcrlf;
if (*bodylength >= (unsigned int) *boundarysize) {
*bodylength -= (unsigned int) *boundarysize;
} else {
*bodylength = 0;
}
} else {
*bodylength = 0;
}
}
static void parseSinglePart(const string &toboundary,
int *boundarysize,
unsigned int *nbodylines,
unsigned int *nlines,
bool *eof, bool *foundendofpart,
unsigned int *bodylength)
{
using namespace ::Binc;
unsigned int bodystartoffsetcrlf = mimeSource->getOffset();
// If toboundary is empty, then we read until the end of the
// file. Otherwise we will read until we encounter toboundary.
string _toboundary;
if (toboundary != "") {
_toboundary = "\r\n--";
_toboundary += toboundary;
}
// if (skipUntilBoundary(_toboundary, nlines, eof))
// *boundarysize = _toboundary.length();
char *boundaryqueue = 0;
int endpos = _toboundary.length();
if (toboundary != "") {
boundaryqueue = new char[endpos];
memset(boundaryqueue, 0, endpos);
}
int boundarypos = 0;
*boundarysize = 0;
const char *_toboundaryStr = _toboundary.c_str();
string line;
bool toboundaryIsEmpty = (toboundary == "");
char c;
while (mimeSource->getChar(&c)) {
if (c == '\n') { ++*nbodylines; ++*nlines; }
if (toboundaryIsEmpty)
continue;
// find boundary
boundaryqueue[boundarypos++ % endpos] = c;
if (compareStringToQueue(_toboundaryStr, boundaryqueue,
boundarypos, endpos)) {
*boundarysize = _toboundary.length();
break;
}
}
delete [] boundaryqueue;
if (toboundary != "") {
char a;
if (!mimeSource->getChar(&a))
*eof = true;
if (a == '\n')
++*nlines;
char b;
if (!mimeSource->getChar(&b))
*eof = true;
if (b == '\n')
++*nlines;
if (a == '-' && b == '-') {
*boundarysize += 2;
*foundendofpart = true;
if (!mimeSource->getChar(&a))
*eof = true;
if (a == '\n')
++*nlines;
if (!mimeSource->getChar(&b))
*eof = true;
if (b == '\n')
++*nlines;
}
if (a == '\r' && b == '\n') {
// This exception is to handle a special case where the
// delimiter of one part is not followed by CRLF, but
// immediately followed by a CRLF prefixed delimiter.
if (!mimeSource->getChar(&a) || !mimeSource->getChar(&b))
*eof = true;
else if (a == '-' && b == '-') {
mimeSource->ungetChar();
mimeSource->ungetChar();
mimeSource->ungetChar();
mimeSource->ungetChar();
} else {
mimeSource->ungetChar();
mimeSource->ungetChar();
}
*boundarysize += 2;
} else {
mimeSource->ungetChar();
mimeSource->ungetChar();
}
}
// make sure bodylength doesn't overflow
*bodylength = mimeSource->getOffset();
if (*bodylength >= bodystartoffsetcrlf) {
*bodylength -= bodystartoffsetcrlf;
if (*bodylength >= (unsigned int) *boundarysize) {
*bodylength -= (unsigned int) *boundarysize;
} else {
*bodylength = 0;
}
} else {
*bodylength = 0;
}
}
//------------------------------------------------------------------------
int Binc::MimePart::parseFull(const string &toboundary,
int &boundarysize) const
{
headerstartoffsetcrlf = mimeSource->getOffset();
// Parse the header of this mime part.
parseHeader(&h, &nlines);
// Headerlength includes the seperating CRLF. Body starts after the
// CRLF.
headerlength = mimeSource->getOffset() - headerstartoffsetcrlf;
bodystartoffsetcrlf = mimeSource->getOffset();
bodylength = 0;
// Determine the type of mime part by looking at fields in the
// header.
analyzeHeader(&h, &multipart, &messagerfc822, &subtype, &boundary);
bool eof = false;
bool foundendofpart = false;
if (messagerfc822) {
parseMessageRFC822(&members, &foundendofpart, &bodylength,
&nbodylines, toboundary);
} else if (multipart) {
parseMultipart(boundary, toboundary, &eof, &nlines, &boundarysize,
&foundendofpart, &bodylength,
&members);
} else {
parseSinglePart(toboundary, &boundarysize, &nbodylines, &nlines,
&eof, &foundendofpart, &bodylength);
}
return (eof || foundendofpart) ? 1 : 0;
}

View File

@ -0,0 +1,171 @@
/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* mime-parseonlyheader.cc
*
* Description:
* Implementation of main mime parser components
* --------------------------------------------------------------------
* 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.
* --------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "mime.h"
#include "mime-utils.h"
#include "mime-inputsource.h"
#include "convert.h"
#include <string>
#include <vector>
#include <map>
#include <exception>
#include <iostream>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
using namespace ::std;
//------------------------------------------------------------------------
void Binc::MimeDocument::parseOnlyHeader(int fd) const
{
if (allIsParsed || headerIsParsed)
return;
headerIsParsed = true;
if (!mimeSource || mimeSource->getFileDescriptor() != fd) {
delete mimeSource;
mimeSource = new MimeInputSource(fd);
} else {
mimeSource->reset();
}
headerstartoffsetcrlf = 0;
headerlength = 0;
bodystartoffsetcrlf = 0;
bodylength = 0;
messagerfc822 = false;
multipart = false;
nlines = 0;
nbodylines = 0;
MimePart::parseOnlyHeader("");
}
//------------------------------------------------------------------------
int Binc::MimePart::parseOnlyHeader(const string &toboundary) const
{
string name;
string content;
char cqueue[4];
memset(cqueue, 0, sizeof(cqueue));
headerstartoffsetcrlf = mimeSource->getOffset();
bool quit = false;
char c = '\0';
while (!quit) {
// read name
while (1) {
if (!mimeSource->getChar(&c)) {
quit = true;
break;
}
if (c == '\n') ++nlines;
if (c == ':') break;
if (c == '\n') {
for (int i = name.length() - 1; i >= 0; --i)
mimeSource->ungetChar();
quit = true;
name = "";
break;
}
name += c;
if (name.length() == 2 && name.substr(0, 2) == "\r\n") {
name = "";
quit = true;
break;
}
}
if (name.length() == 1 && name[0] == '\r') {
name = "";
break;
}
if (quit) break;
while (!quit) {
if (!mimeSource->getChar(&c)) {
quit = true;
break;
}
if (c == '\n') ++nlines;
for (int i = 0; i < 3; ++i)
cqueue[i] = cqueue[i + 1];
cqueue[3] = c;
if (strncmp(cqueue, "\r\n\r\n", 4) == 0) {
quit = true;
break;
}
if (cqueue[2] == '\n') {
// guess the mime rfc says what can not appear on the beginning
// of a line.
if (!isspace(cqueue[3])) {
if (content.length() > 2)
content.resize(content.length() - 2);
trim(content);
h.add(name, content);
name = c;
content = "";
break;
}
}
content += c;
}
}
if (name != "") {
if (content.length() > 2)
content.resize(content.length() - 2);
h.add(name, content);
}
headerlength = mimeSource->getOffset() - headerstartoffsetcrlf;
return 1;
}

View File

@ -0,0 +1,74 @@
/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* mime-printbody.cc
*
* Description:
* Implementation of main mime parser components
* --------------------------------------------------------------------
* 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.
* --------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "mime.h"
#include "mime-utils.h"
#include "mime-inputsource.h"
#include "convert.h"
#include "iodevice.h"
#include "iofactory.h"
#include <string>
#include <vector>
#include <map>
#include <exception>
#include <iostream>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
using namespace ::std;
//------------------------------------------------------------------------
void Binc::MimePart::printBody(int fd, IODevice &output,
unsigned int startoffset,
unsigned int length) const
{
if (!mimeSource || mimeSource->getFileDescriptor() != fd) {
delete mimeSource;
mimeSource = new MimeInputSource(fd);
}
mimeSource->reset();
mimeSource->seek(bodystartoffsetcrlf + startoffset);
if (startoffset + length > bodylength)
length = bodylength - startoffset;
char c = '\0';
for (unsigned int i = 0; i < length; ++i) {
if (!mimeSource->getChar(&c))
break;
output << (char)c;
}
}

View File

@ -0,0 +1,70 @@
/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* mime-printdoc.cc
*
* Description:
* Implementation of main mime parser components
* --------------------------------------------------------------------
* 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.
* --------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "mime.h"
#include "mime-utils.h"
#include "mime-inputsource.h"
#include "convert.h"
#include "iodevice.h"
#include "iofactory.h"
#include <string>
#include <vector>
#include <map>
#include <exception>
#include <iostream>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
using namespace ::std;
//------------------------------------------------------------------------
void Binc::MimePart::printDoc(int fd, IODevice &output,
unsigned int startoffset,
unsigned int length) const
{
if (!mimeSource || mimeSource->getFileDescriptor() != fd) {
delete mimeSource;
mimeSource = new MimeInputSource(fd);
}
mimeSource->reset();
mimeSource->seek(headerstartoffsetcrlf);
char c;
for (unsigned int i = 0; i < length; ++i) {
if (!mimeSource->getChar(&c))
break;
output << (char)c;
}
}

View File

@ -0,0 +1,198 @@
/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* mime-printheader.cc
*
* Description:
* Implementation of main mime parser components
* --------------------------------------------------------------------
* 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.
* --------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "mime.h"
#include "mime-utils.h"
#include "mime-inputsource.h"
#include "convert.h"
#include "iodevice.h"
#include "iofactory.h"
#include <string>
#include <vector>
#include <map>
#include <exception>
#include <iostream>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
using namespace ::std;
//------------------------------------------------------------------------
void Binc::MimePart::printHeader(int fd, IODevice &output,
vector<string> headers, bool includeheaders,
unsigned int startoffset,
unsigned int length, string &store) const
{
if (!mimeSource || mimeSource->getFileDescriptor() != fd) {
delete mimeSource;
mimeSource = new MimeInputSource(fd);
}
mimeSource->seek(headerstartoffsetcrlf);
string name;
string content;
char cqueue[2];
memset(cqueue, 0, sizeof(cqueue));
bool quit = false;
char c = '\0';
unsigned int wrotebytes = 0;
unsigned int processedbytes = 0;
bool hasHeaderSeparator = false;
while (!quit) {
// read name
while (1) {
// allow EOF to end the header
if (!mimeSource->getChar(&c)) {
quit = true;
break;
}
// assume this character is part of the header name.
name += c;
// break on the first colon
if (c == ':')
break;
// break if a '\n' turned up.
if (c == '\n') {
// end of headers detected
if (name == "\r\n") {
hasHeaderSeparator = true;
quit = true;
break;
}
// put all data back in the buffer to the beginning of this
// line.
for (int i = name.length(); i >= 0; --i)
mimeSource->ungetChar();
// abort printing of header. note that in this case, the
// headers will not end with a seperate \r\n.
quit = true;
name = "";
break;
}
}
if (quit) break;
// at this point, we have a name, that is - the start of a
// header. we'll read until the end of the header.
while (!quit) {
// allow EOF to end the header.
if (!mimeSource->getChar(&c)) {
quit = true;
break;
}
if (c == '\n') ++nlines;
// make a fifo queue of the last 4 characters.
cqueue[0] = cqueue[1];
cqueue[1] = c;
// print header
if (cqueue[0] == '\n' && cqueue[1] != '\t' && cqueue[1] != ' ') {
// it wasn't a space, so put it back as it is most likely
// the start of a header name. in any case it terminates the
// content part of this header.
mimeSource->ungetChar();
string lowername = name;
lowercase(lowername);
trim(lowername, ": \t");
bool foundMatch = false;
for (vector<string>::const_iterator i = headers.begin();
i != headers.end(); ++i) {
string nametmp = *i;
lowercase(nametmp);
if (nametmp == lowername) {
foundMatch = true;
break;
}
}
if (foundMatch == includeheaders || headers.size() == 0) {
string out = name + content;
for (string::const_iterator i = out.begin(); i != out.end(); ++i)
if (processedbytes >= startoffset && wrotebytes < length) {
if (processedbytes >= startoffset) {
store += *i;
++wrotebytes;
}
} else
++processedbytes;
}
// move on to the next header
content = "";
name = "";
break;
}
content += c;
}
}
if (name != "") {
string lowername = name;
lowercase(lowername);
trim(lowername, ": \t");
bool foundMatch = false;
for (vector<string>::const_iterator i = headers.begin();
i != headers.end(); ++i) {
string nametmp = *i;
lowercase(nametmp);
if (nametmp == lowername) {
foundMatch = true;
break;
}
}
if (hasHeaderSeparator || foundMatch == includeheaders || headers.size() == 0) {
string out = name + content;
for (string::const_iterator i = out.begin(); i != out.end(); ++i)
if (processedbytes >= startoffset && wrotebytes < length) {
store += *i;
++wrotebytes;
} else
++processedbytes;
}
}
}

View File

@ -0,0 +1,50 @@
/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* mime.cc
*
* Description:
* Implementation of main mime parser components
* --------------------------------------------------------------------
* 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_utils_h_included
#define mime_utils_h_included
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
using namespace ::std;
inline bool compareStringToQueue(const char *s_in, char *bqueue,
int pos, int size)
{
for (int i = 0; i < size; ++i)
if (s_in[i] != bqueue[(pos + i) % size])
return false;
return true;
}
#endif

157
src/bincimapmime/mime.cc Normal file
View File

@ -0,0 +1,157 @@
/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* mime.cc
*
* Description:
* Implementation of main mime parser components
* --------------------------------------------------------------------
* 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.
* --------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "mime.h"
#include "convert.h"
#include <string>
#include <vector>
#include <map>
#include <exception>
#include <iostream>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
using namespace ::std;
//------------------------------------------------------------------------
Binc::MimeDocument::MimeDocument(void) : MimePart()
{
allIsParsed = false;
headerIsParsed = false;
}
//------------------------------------------------------------------------
Binc::MimeDocument::~MimeDocument(void)
{
}
//------------------------------------------------------------------------
void Binc::MimeDocument::clear(void) const
{
members.clear();
h.clear();
headerIsParsed = false;
allIsParsed = false;
}
//------------------------------------------------------------------------
void Binc::MimePart::clear(void) const
{
members.clear();
h.clear();
}
//------------------------------------------------------------------------
Binc::MimePart::MimePart(void)
{
size = 0;
messagerfc822 = false;
multipart = false;
nlines = 0;
nbodylines = 0;
}
//------------------------------------------------------------------------
Binc::MimePart::~MimePart(void)
{
}
//------------------------------------------------------------------------
Binc::HeaderItem::HeaderItem(void)
{
}
//------------------------------------------------------------------------
Binc::HeaderItem::HeaderItem(const string &key, const string &value)
{
this->key = key;
this->value = value;
}
//------------------------------------------------------------------------
Binc::Header::Header(void)
{
}
//------------------------------------------------------------------------
Binc::Header::~Header(void)
{
}
//------------------------------------------------------------------------
bool Binc::Header::getFirstHeader(const string &key, HeaderItem &dest) const
{
string k = key;
lowercase(k);
for (vector<HeaderItem>::const_iterator i = content.begin();
i != content.end(); ++i) {
string tmp = (*i).getKey();
lowercase(tmp);
if (tmp == k) {
dest = *i;
return true;
}
}
return false;
}
//------------------------------------------------------------------------
bool Binc::Header::getAllHeaders(const string &key, vector<HeaderItem> &dest) const
{
string k = key;
lowercase(k);
for (vector<HeaderItem>::const_iterator i = content.begin();
i != content.end(); ++i) {
string tmp = (*i).getKey();
lowercase(tmp);
if (tmp == k)
dest.push_back(*i);
}
return (dest.size() != 0);
}
//------------------------------------------------------------------------
void Binc::Header::clear(void) const
{
content.clear();
}
//------------------------------------------------------------------------
void Binc::Header::add(const string &key, const string &value)
{
content.push_back(HeaderItem(key, value));
}

143
src/bincimapmime/mime.h Normal file
View File

@ -0,0 +1,143 @@
/* -*- Mode: c++; -*- */
/* --------------------------------------------------------------------
* Filename:
* src/parsers/mime/mime.h
*
* Description:
* Declaration of main mime parser components
* --------------------------------------------------------------------
* 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.
* --------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef mime_h_included
#define mime_h_included
#include <string>
#include <vector>
#include <map>
#include <stdio.h>
namespace Binc {
//----------------------------------------------------------------------
class HeaderItem {
private:
mutable std::string key;
mutable std::string value;
public:
inline const std::string &getKey(void) const { return key; }
inline const std::string &getValue(void) const { return value; }
//--
HeaderItem(void);
HeaderItem(const std::string &key, const std::string &value);
};
//----------------------------------------------------------------------
class Header {
private:
mutable std::vector<HeaderItem> content;
public:
bool getFirstHeader(const std::string &key, HeaderItem &dest) const;
bool getAllHeaders(const std::string &key, std::vector<HeaderItem> &dest) const;
void add(const std::string &name, const std::string &content);
void clear(void) const;
//--
Header(void);
~Header(void);
};
//----------------------------------------------------------------------
class IODevice;
class MimeDocument;
class MimePart {
protected:
public:
mutable bool multipart;
mutable bool messagerfc822;
mutable std::string subtype;
mutable std::string boundary;
mutable unsigned int headerstartoffsetcrlf;
mutable unsigned int headerlength;
mutable unsigned int bodystartoffsetcrlf;
mutable unsigned int bodylength;
mutable unsigned int nlines;
mutable unsigned int nbodylines;
mutable unsigned int size;
public:
enum FetchType {
FetchBody,
FetchHeader,
FetchMime
};
mutable Header h;
mutable std::vector<MimePart> members;
inline const std::string &getSubType(void) const { return subtype; }
inline bool isMultipart(void) const { return multipart; }
inline bool isMessageRFC822(void) const { return messagerfc822; }
inline unsigned int getSize(void) const { return bodylength; }
inline unsigned int getNofLines(void) const { return nlines; }
inline unsigned int getNofBodyLines(void) const { return nbodylines; }
inline unsigned int getBodyLength(void) const { return bodylength; }
inline unsigned int getBodyStartOffset(void) const { return bodystartoffsetcrlf; }
void printBody(int fd, Binc::IODevice &output, unsigned int startoffset, unsigned int length) const;
void printHeader(int fd, Binc::IODevice &output, std::vector<std::string> headers, bool includeheaders, unsigned int startoffset, unsigned int length, std::string &storage) const;
void printDoc(int fd, Binc::IODevice &output, unsigned int startoffset, unsigned int length) const;
virtual void clear(void) const;
const MimePart *getPart(const std::string &findpart, std::string genpart, FetchType fetchType = FetchBody) const;
virtual int parseOnlyHeader(const std::string &toboundary) const;
virtual int parseFull(const std::string &toboundary, int &boundarysize) const;
MimePart(void);
virtual ~MimePart(void);
};
//----------------------------------------------------------------------
class MimeDocument : public MimePart {
private:
mutable bool headerIsParsed;
mutable bool allIsParsed;
public:
void parseOnlyHeader(int fd) const;
void parseFull(int fd) const;
void clear(void) const;
inline bool isHeaderParsed(void) { return headerIsParsed; }
inline bool isAllParsed(void) { return allIsParsed; }
//--
MimeDocument(void);
~MimeDocument(void);
};
};
#endif

View File