p≡p MIME library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

302 lines
8.2 KiB

#include "pEpMIME.hh"
#include "base64.hh"
#ifdef WIN32
#include <libpEpAdapter/slurp.hh>
#else
#include <pEp/slurp.hh>
#endif
#include <iostream>
#include <gtest/gtest.h>
namespace std
{
ostream& operator<<(ostream&, struct tm const&);
ostream& operator<<(ostream& o, struct tm const* t)
{
if(t)
{
return o << *t;
}
return o << "(NULL)";
}
}
using namespace std::string_literals;
namespace {
static const char* mail1_eml =
"Return-Path: <alice@pep-project.org>\r\n"
"X-Original-To: alice@pep-project.org\r\n"
"Delivered-To: alice@pep-project.org\r\n"
"Received: from localhost (localhost [127.0.0.1])\r\n"
"\tby dragon.pibit.ch (Postfix) with ESMTP id B84AF171C06F\r\n"
"\tfor <alice@pep-project.org>; Wed, 16 Jan 2019 16:29:39 +0100 (CET)\r\n"
"Received: from dragon.pibit.ch ([127.0.0.1])\r\n"
"\tby localhost (dragon.pibit.ch [127.0.0.1]) (amavisd-new, port 10024)\r\n"
"\twith ESMTP id q0wZqHMoT1gS for <alice@pep-project.org>;\r\n"
"\tWed, 16 Jan 2019 16:29:37 +0100 (CET)\r\n"
"Received: from Alice-PC.local (unknown [192.168.128.20])\r\n"
"\tby dragon.pibit.ch (Postfix) with ESMTPSA id 563DD171C06A\r\n"
"\tfor <alice@pep-project.org>; Wed, 16 Jan 2019 16:29:37 +0100 (CET)\r\n"
"To: Bob <bob@pep-project.org>\r\n"
"From: Alice <alice@pep-project.org>\r\n"
"Cc: Carol Couscous <carol.couscous+private@pep.lol>, Dave Doe (III) \r\n"
" Dexter <dave-dexter@pep.ooo>, dodo@pep.lol, \"Eve @ Evil\" <eve@evil.lol>\r\n"
"Subject: =?UTF-8?B?UsO4ZGdyw7hkIG1lZCBmbMO4ZGU=?=\r\n"
"Openpgp: preference=signencrypt\r\n"
"Organization: =?UTF-8?B?8J+Ukg==?=\r\n"
"Message-ID: <65a2df2c-ddc8-0875-a142-21acf62ed467@pep-project.org>\r\n"
"References: <msg-alfa@pep.id> <msg-bravo@pep.aq> <lol-123456789@intern.sc.ful-lol.example>\r\n"
" <msg-charlie@pep.aq>\r\n"
"In-Reply-To: <msg-reply-0815@pep.aq>\r\n"
"Date: Wed, 16 Jan 2019 16:29:30 +0100\r\n"
"User-Agent: B\r\n"
"MIME-Version: 1.0\r\n"
"Content-Type: multipart/signed; micalg=pgp-sha256;\r\n"
" protocol=\"application/pgp-signature\";\r\n"
" boundary=\"==pEp_01==\"\r\n"
"\r\n"
"This is an OpenPGP/MIME signed message (RFC 4880 and 3156)\r\n"
"--==pEp_01==\r\n"
"Content-Type: multipart/mixed; boundary=\"==pEp_02==\";\r\n"
" protected-headers=\"v1\"\r\n"
"From: Alice <alice@pep-project.org>\r\n"
"To: Bob <bob@pep-project.org>\r\n"
"Message-ID: <65a2df2c-ddc8-0875-a142-21acf62ed467@pep-project.org>\r\n"
"Subject: =?UTF-8?B?UsO4ZGdyw7hkIG1lZCBmbMO4ZGU=?=\r\n"
"\r\n"
"--==pEp_02==\r\n"
"Content-Type: text/plain; charset=utf-8\r\n"
"Content-Language: en-US\r\n"
"Content-Transfer-Encoding: quoted-printable\r\n"
"\r\n"
"R=C3=B8dgr=C3=B8d med fl=C3=B8de?\r\n"
"\r\n"
"\r\n"
"--==pEp_02==\r\n"
"Content-Type: application/octet-stream; name=\"This is a long\r\n"
" file name so it is split to multiple\r\n"
" physical lines.bin\"\r\n"
"Content-Language: en-US\r\n"
"Content-Transfer-Encoding: base64\r\n"
"Content-Disposition: attachment;\r\n"
" filename*0=\"This is a long file name so it is split to\";\r\n"
" filename*1=\" multiple physical lines.bin\";\r\n"
"\r\n"
"w5xiZXJncsO2w59lbsOkbmRlcnVuZyEK\r\n"
"\r\n"
"--==pEp_02==\r\n"
"Content-Type: application/octet-stream; name=\"=?UTF-8?B?8J+SqSDwn5iAIPCf?="
" =?UTF-8?B?kqkg8J+YgCDwn5KpIPCfmIAg8J+SqSDwn5iAIPCfkqkg8J+YgCDwn5KpIPCfm?="
" =?UTF-8?B?IAg8J+SqSDwn5iAIPCfkqkg8J+YgC5wbmc=?=\r\n"
"Content-Language: en-US\r\n"
"Content-Transfer-Encoding: base64\r\n"
"Content-Disposition: attachment;\r\n"
" filename*0*=utf-8''%F0%9F%92%A9%20%F0%9F%98%80%20%F0%9F%92%A9%20%F0;\r\n"
" filename*1*=%9F%98%80%20%F0%9F%92%A9%20%F0%9F%98%80%20%F0%9F%92%A9;\r\n"
" filename*2*=%20%F0%9F%98%80%20%F0%9F%92%A9%20%F0%9F%98%80%20%F0%9F;\r\n"
" filename*3*=%92%A9%20%F0%9F%98%80%20%F0%9F%92%A9%20%F0%9F%98%80%20;\r\n"
" filename*4*=%F0%9F%92%A9%20%F0%9F%98%80.png\r\n"
"\r\n"
"w5xiZXJncsO2w59lbsOkbmRlcnVuZyEK\r\n"
"\r\n"
"--==pEp_02==--\r\n"
"\r\n"
"--==pEp_01==\r\n"
"Content-Type: application/pgp-signature; name=\"signature.asc\"\r\n"
"Content-Description: OpenPGP digital signature\r\n"
"Content-Disposition: attachment; filename=\"signature.asc\"\r\n"
"\r\n"
"-----BEGIN PGP SIGNATURE-----\r\n"
"Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/\r\n"
"\r\n"
"iQIzBAEBCAAdFiEEwoKp24M4J8EyIWOoerk/iYg5bHgFAlw/Td8ACgkQerk/iYg5\r\n"
"bHhtWA/+MNRX5bzS7B3vwiKkxQ+CrO1eNi+vqR+aW8nSULI7q3mHKrMUf5n1QczY\r\n"
"R2oZzriAIo9wdY6xIN1IMwzxJi3Z59EyDLlAGN2lUtSI/G9s6wghV819pFTV0dKr\r\n"
"DZ2C+pqQuXmIB5Zu96zefj45JlwO9csMUrMQgCjafIdKE7wgoISw2bqL5f9a+lqZ\r\n"
"Ud3t3jNCPyAK8msq/TOwNXNfO4hE1xpvz5RDhF7a4/zhai3VHlqw0MKf1oWE/VG6\r\n"
"KnnOlrahRegPVCfeFrz8j5ukjWWZ8wqhnBDWBDqywcZ897gYrWLsNELV5umwi/74\r\n"
"PQ7/zZZG9ICZ4UxsjULfW0TqzvpEEGoH7zPl1eP5qpNuIa6jBnfMDX1p6UTHss7K\r\n"
"YY4IRbOzW81508y5XHkMpPx6Tx6C51mLNBJA6+vycpwyQ6VL4sc8d+WRRIsNd2b5\r\n"
"/3N7UFiiIMs9bXSbiGoyh3qrQTXbJ081MxMaObs+SbgndfHT/mVZd7zhhKI7elRi\r\n"
"MErnNucpggTu0MdSLhK85Qlk/BzCZxuAfl5jAwYu//MvayaJEhY4RMVwT99ep0Ac\r\n"
"npvgwv0BcZTzNECc/tKKHklNB2UW51qm9VL3TJlyx/jlZ3p9s6HE9JY6DyQcbjO/\r\n"
"F9zYJQSDTUeHbajW55j+SjlOHZqI2468R7nV7HHdvDFxpj9qeCs=\r\n"
"=qfLv\r\n"
"-----END PGP SIGNATURE-----\r\n"
"\r\n"
"--==pEp_01==--\r\n"
"\r\n";
}
template<class T>
T out(const T& t) { return t; }
std::string out(char* s)
{
if(s==nullptr)
{
return "(NULL)";
}
return '"' + std::string(s) + '"';
}
std::string out(pEp_identity* id)
{
if(id==nullptr)
{
return "ID{0} ";
}else{
return "ID{ addr=" + out(id->address) + ", fpr=" + out(id->fpr) + ", name=" + out(id->username) + "} ";
}
}
std::string out(identity_list* idl)
{
if(idl==nullptr)
{
return "IDL[] ";
}else{
std::string ret = "IDL[";
pEp_identity* id = idl->ident;
ret += out(id);
while(idl->next)
{
idl = idl->next;
ret += ", ";
ret += out(idl->ident);
}
return ret + ']';
}
}
std::string out(stringlist_t* sl)
{
if(sl==nullptr)
{
return "NULL ";
}else{
std::string ret = "SL[";
char* s = sl->value;
ret += out(s);
while(sl->next)
{
sl = sl->next;
ret += ", ";
ret += out(sl->value);
}
return ret + ']';
}
}
std::string out(stringpair_list_t* spl)
{
if(spl==nullptr)
{
return "NULL ";
}else{
std::string ret = "SPL[";
auto sp = spl->value;
ret += ""s + sp->key + "”:“"s + sp->value + "";
while(spl->next)
{
spl = spl->next;
auto sp = spl->value;
ret += ", “"s + sp->key + "”:“"s + sp->value + "";
}
return ret + ']';
}
}
#define PRINT(member) std::cerr << "\t" #member ": " << out(m->member) << "\n"
void print_message(message* m)
{
if(!m)
{
std::cerr << "NULL message!\n";
return;
}
PRINT(dir);
PRINT(id);
PRINT(shortmsg);
PRINT(longmsg);
PRINT(longmsg_formatted);
PRINT(attachments);
PRINT(rawmsg_ref);
PRINT(rawmsg_size);
PRINT(sent);
PRINT(recv);
PRINT(from);
PRINT(to);
PRINT(recv_by);
PRINT(cc);
PRINT(bcc);
PRINT(reply_to);
PRINT(in_reply_to);
PRINT(refering_msg_ref);
PRINT(references);
PRINT(refered_by);
PRINT(keywords);
PRINT(comments);
PRINT(opt_fields);
PRINT(enc_format);
}
void bench_base64()
{
const int STR_SIZE = 100000000;
const int TRIES = 10;
std::string str(STR_SIZE, 'p');
for (int i = 0; i < STR_SIZE; i++) { str[i] = random(); }
int s = 0;
clock_t t = clock();
std::string e;
for (int i = 0; i < TRIES; i++) {
e = pEpMIME::base64::encode( str );
s += e.size();;
}
double duration = (double)(clock() - t)/CLOCKS_PER_SEC;
printf("encode: %d bytes in %.2f seconds. %f MiB/second.\n", s, duration, (s/(1024.0*1024.0))/duration);
e = pEpMIME::base64::encode(str);
s = 0;
t = clock();
for (int i = 0; i < TRIES; i++) {
const std::string d = pEpMIME::base64::decode(e);
s += d.size();
}
duration = (double)(clock() - t)/CLOCKS_PER_SEC;
printf("decode: %d bytes in %.2f seconds. %f MiB/second.\n", s, duration, (s/(1024.0*1024.0))/duration);
}
TEST(PepMimeTest, NFC)
{
const std::string f = mail1_eml;
message* m = pEpMIME::parse_message(f.data(), f.size());
ASSERT_NE( m, nullptr );
print_message(m);
free_message(m);
}