initial import from bincimap-1.3.3
This commit is contained in:
parent
7ed16bcbf8
commit
670d7c2630
29
src/bincimapmime/Makefile
Normal file
29
src/bincimapmime/Makefile
Normal 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
|
||||
|
||||
88
src/bincimapmime/address.cc
Normal file
88
src/bincimapmime/address.cc
Normal 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;
|
||||
}
|
||||
52
src/bincimapmime/address.h
Normal file
52
src/bincimapmime/address.h
Normal 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
|
||||
0
src/bincimapmime/config.h
Normal file
0
src/bincimapmime/config.h
Normal file
131
src/bincimapmime/convert.cc
Normal file
131
src/bincimapmime/convert.cc
Normal 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
318
src/bincimapmime/convert.h
Normal 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
0
src/bincimapmime/depot.h
Normal file
317
src/bincimapmime/iodevice.cc
Normal file
317
src/bincimapmime/iodevice.cc
Normal 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
389
src/bincimapmime/iodevice.h
Normal 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
|
||||
85
src/bincimapmime/iofactory.cc
Normal file
85
src/bincimapmime/iofactory.cc
Normal 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;
|
||||
}
|
||||
68
src/bincimapmime/iofactory.h
Normal file
68
src/bincimapmime/iofactory.h
Normal 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
|
||||
94
src/bincimapmime/mime-getpart.cc
Normal file
94
src/bincimapmime/mime-getpart.cc
Normal 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;
|
||||
}
|
||||
166
src/bincimapmime/mime-inputsource.h
Normal file
166
src/bincimapmime/mime-inputsource.h
Normal 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
|
||||
666
src/bincimapmime/mime-parsefull.cc
Normal file
666
src/bincimapmime/mime-parsefull.cc
Normal 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;
|
||||
}
|
||||
171
src/bincimapmime/mime-parseonlyheader.cc
Normal file
171
src/bincimapmime/mime-parseonlyheader.cc
Normal 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;
|
||||
}
|
||||
74
src/bincimapmime/mime-printbody.cc
Normal file
74
src/bincimapmime/mime-printbody.cc
Normal 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;
|
||||
}
|
||||
}
|
||||
70
src/bincimapmime/mime-printdoc.cc
Normal file
70
src/bincimapmime/mime-printdoc.cc
Normal 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;
|
||||
}
|
||||
}
|
||||
198
src/bincimapmime/mime-printheader.cc
Normal file
198
src/bincimapmime/mime-printheader.cc
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
50
src/bincimapmime/mime-utils.h
Normal file
50
src/bincimapmime/mime-utils.h
Normal 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
157
src/bincimapmime/mime.cc
Normal 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
143
src/bincimapmime/mime.h
Normal 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
|
||||
0
src/bincimapmime/session.h
Normal file
0
src/bincimapmime/session.h
Normal file
Loading…
x
Reference in New Issue
Block a user