#include <ctype.h>
#include <string.h>
#include <stringtools.h>
#include "mimeparse.h"
#include "rfc822.h"
std::string mimeheader2str(const struct mimeheadert &mimeheader)
{
std::string dest=mimeheader.value;
if(mimeheader.subvalue!="")
{
dest+="/";
dest+=mimeheader.subvalue;
}
for(unsigned i=0; i<mimeheader.attributes.size(); i++)
{
dest+="; ";
dest+=mimeheader.attributes[i].name;
dest+="=\"";
dest+=mimeheader.attributes[i].value;
dest+="\"";
}
return dest;
}
mimestructt::mimestructt()
{
headerlen=len=offset=0;
}
bool mimeheadert::findattribute(std::string &dest, const std::string &name) const
{
for(unsigned i=0; i<attributes.size(); i++)
if(stringcasecmp(attributes[i].name, name)==0)
{
dest=attributes[i].value;
return FALSE;
}
dest="";
return TRUE;
}
void mimestructt::mimeparse(rfcmessaget &rfcm)
{
std::string text;
rfcm.parse();
headerlen=rfcm.headerlen;
len=rfcm.len;
rfcm.findsingleheader(text, "Content-Type");
if(text=="")
parse_mime_header("text/plain; charset=us-ascii", content_type);
else
parse_mime_header(text, content_type);
rfcm.findsingleheader(text, "Content-Transfer-Encoding");
parse_mime_header(text, content_transfer_encoding);
rfcm.findsingleheader(text, "Content-Disposition");
parse_mime_header(text, content_disposition);
if(stringcasecmp(content_type.value, "multipart")==0)
{
std::string boundary, line, boundary1, boundary2;
content_type.findattribute(boundary, "Boundary");
boundary1="--"+boundary;
boundary2=boundary1+"--";
const char *ptr=rfcm.data+rfcm.headerlen,
*previous_line=ptr,
*subpart_start=NULL;
while(!getline(rfcm, line, ptr))
{
if(line==boundary1 || line==boundary2)
{
if(subpart_start!=NULL)
{
rfcmessaget subpartm;
subpartm.data=subpart_start;
subpartm.endofmail=subpartm.endoffile=previous_line;
if(subpartm.endofmail>subpartm.data) // ignore empty parts
{
mimestructt subpart;
subpart.offset=subpartm.data-rfcm.data+offset;
subpart.mimeparse(subpartm);
sub.push_back(subpart);
}
}
if(line==boundary2) break;
subpart_start=ptr;
}
previous_line=ptr;
}
}
}
void parse_mime_header(const std::string &text,
mimeheadert &mimeheader)
{
std::vector<rfc822symbolt> symbols;
unsigned i=0;
parserfc822symbols(text, symbols, ";=/");
if(symbols[i].type!=rfc822symbolt::ATOM &&
symbols[i].type!=rfc822symbolt::QUOTED)
return;
mimeheader.value=symbols[i++].text;
if(symbols[i].type!=rfc822symbolt::SPECIAL)
return;
if(symbols[i].text=="/") // subtype
{
i++;
mimeheader.subvalue=symbols[i++].text;
if(symbols[i].type!=rfc822symbolt::SPECIAL)
return;
}
if(symbols[i++].text!=";") return;
while(symbols[i].type==rfc822symbolt::ATOM ||
symbols[i].type==rfc822symbolt::QUOTED)
{
mimeattributet attribute;
attribute.name=symbols[i++].text;
if(symbols[i].type==rfc822symbolt::SPECIAL &&
symbols[i].text=="=" &&
(symbols[i+1].type==rfc822symbolt::ATOM ||
symbols[i+1].type==rfc822symbolt::QUOTED))
{
i++;
do
attribute.value+=symbols[i++].text;
while(symbols[i].type==rfc822symbolt::ATOM ||
symbols[i].type==rfc822symbolt::QUOTED ||
(symbols[i].type==rfc822symbolt::SPECIAL &&
symbols[i].text!=";"));
mimeheader.attributes.push_back(attribute);
}
if(symbols[i].type!=rfc822symbolt::SPECIAL ||
symbols[i].text!=";")
return;
i++;
}
}
syntax highlighted by Code2HTML, v. 0.9.1