#include <libdbox.h>
#include "rfc822.h"
using namespace std;
static bool is_special_char(char ch, const string &extra_specials)
{
switch(ch)
{
case '(':
case ')':
case '<':
case '>':
case '@':
case ',':
case ';':
case ':':
case '\\':
case '"':
case '.':
case '[':
case ']':
return TRUE;
}
if(extra_specials.find(ch)!=string::npos)
return TRUE;
return FALSE;
}
static void getatom(const string &text, unsigned &i,
rfc822symbolt &symbol,
const string &extra_specials)
{
symbol.type=rfc822symbolt::ATOM;
for(; i<text.size(); i++)
{
char ch=text[i];
if(is_special_char(ch, extra_specials) ||
ch==' ' || ch=='\t') return;
symbol.text+=ch;
}
}
static void getquoted(const string &text, unsigned &i,
rfc822symbolt &symbol,
const string &extra_specials)
{
i++; // skip '"'
symbol.type=rfc822symbolt::QUOTED;
while(i<text.size())
{
char ch=text[i++];
if(ch=='\\') // quoted-pair
{
if(i<text.size()) symbol.text+=text[i++];
}
else if(ch=='"')
return;
else
symbol.text+=ch;
}
}
static void getdomain(const string &text, unsigned &i,
rfc822symbolt &symbol,
const string &extra_specials)
{
i++; // skip '['
symbol.type=rfc822symbolt::DOMAIN;
while(i<text.size())
{
char ch=text[i++];
if(ch=='\\') // quoted-pair
{
if(i<text.size()) symbol.text+=text[i++];
}
else if(ch==']')
return;
else
symbol.text+=ch;
}
}
static void getcomment(const string &text, unsigned &i,
rfc822symbolt &symbol,
const string &extra_specials)
{
int nested=0;
symbol.type=rfc822symbolt::COMMENT;
i++; // skip '('
while(i<text.size())
{
char ch=text[i++];
if(ch=='\\') // quoted-pair
{
if(i<text.size()) symbol.text+=text[i++];
}
else if(ch==')' && nested==0)
return;
else
{
if(ch=='(') nested++;
symbol.text+=ch;
}
}
}
void parserfc822symbols(const string &text,
vector<rfc822symbolt> &symbols,
const string &extra_specials)
{
unsigned i=0;
while(i<text.size())
{
char ch=text[i];
if(ch==' ' || ch=='\t') // ignore spaces
i++;
else
{
rfc822symbolt symbol;
if(is_special_char(ch, extra_specials))
{
switch(ch)
{
case '"': // quoted
getquoted(text, i, symbol, extra_specials);
break;
case '(': // comment
getcomment(text, i, symbol, extra_specials);
break;
case '[': // domain-literal
getdomain(text, i, symbol, extra_specials);
break;
default:
symbol.text+=ch;
symbol.type=rfc822symbolt::SPECIAL;
i++;
}
}
else // atom
getatom(text, i, symbol, extra_specials);
symbols.push_back(symbol);
}
}
{
rfc822symbolt symbol;
symbol.type=rfc822symbolt::END_OF_LIST;
symbols.push_back(symbol);
}
}
#ifdef TESTIT
void main()
{
vector<rfc822symbolt> symbols;
// example from rfc822
#if 0
parserfc822symbols(
"\":sysmail\"@ Some-Group. Some-Org, "
"Muhammed.(I am the greatest) Ali @(the)Vegas.WBA",
symbols);
#else
//parserfc822symbols("Hans Mueller <hans@mueller.de>", symbols);
parserfc822symbols("hans@ (Ha\"ns ?Mü\\)ller) mueller. de", symbols);
//parserfc822symbols("text/plain; charset=\"us-ascii\" "
// "(Plain text)", symbols, ";/=");
#endif
cout << "Parsing done.\n";
for(unsigned i=0; i<symbols.size(); i++)
{
cout.form("%2d: %-30s ", i, symbols[i].text.c_str());
switch(symbols[i].type)
{
case rfc822symbolt::DOMAIN: cout << "domain-literal"; break;
case rfc822symbolt::ATOM: cout << "atom"; break;
case rfc822symbolt::SPECIAL: cout << "special"; break;
case rfc822symbolt::QUOTED: cout << "quoted-string"; break;
case rfc822symbolt::COMMENT: cout << "comment"; break;
case rfc822symbolt::END_OF_LIST: cout << "end-of-list"; break;
}
cout << "\n";
}
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1