/*
Basic History plugin
Copyright (C) 2011-2012 Krzysztof Kral
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 version 2
of the License.
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, see .
*/
#include "StdAfx.h"
#include "DatExport.h"
#include "EventList.h"
#define EXP_FILE (*((std::ofstream*)IExport::stream))
#define IMP_FILE (*((std::ifstream*)IImport::stream))
std::wstring GetProtocolName(HANDLE hContact);
std::wstring GetContactId(HANDLE hContact);
#pragma pack(push, 1)
struct MCHeader
{
unsigned char signature[2];
unsigned int version;
unsigned int dataSize;
};
#pragma pack(pop)
typedef struct {
int cbSize; //size of the structure in bytes
DWORD szModule; //pointer to name of the module that 'owns' this
//event, ie the one that is in control of the data format
DWORD timestamp; //seconds since 00:00, 01/01/1970. Gives us times until
//2106 unless you use the standard C library which is
//signed and can only do until 2038. In GMT.
DWORD flags; //the omnipresent flags
WORD eventType; //module-defined event type field
DWORD cbBlob; //size of pBlob in bytes
DWORD pBlob; //pointer to buffer containing module-defined event data
} DBEVENTINFO86;
DatExport::~DatExport()
{
}
int DatExport::WriteString(const std::wstring &str)
{
int conv = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), (int)str.length() + 1, NULL, 0, NULL, NULL);
if(conv > (int)memBuf.size())
{
memBuf.resize(conv);
}
conv = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), (int)str.length() + 1, (char*)memBuf.c_str(), conv, NULL, NULL);
return conv;
}
void DatExport::WriteHeader(const std::wstring &fileName, const std::wstring &filterName, const std::wstring &myName, const std::wstring &myId, const std::wstring &name1, const std::wstring &proto1, const std::wstring &id1, const std::string& baseProto1, const std::wstring& encoding)
{
MCHeader header;
memset(&header, 0, sizeof(MCHeader));
memcpy(header.signature, "HB", 2);
header.version = -1;
header.dataSize = 0;
dataSize = 0;
EXP_FILE.write((char*)&header, sizeof(MCHeader));
}
void DatExport::WriteFooter()
{
size_t pos = EXP_FILE.tellp();
EXP_FILE.seekp(offsetof(MCHeader, dataSize), std::ios_base::beg);
EXP_FILE.write((char*)&dataSize, sizeof(dataSize));
EXP_FILE.seekp(pos, std::ios_base::beg);
memBuf.resize(0);
memBuf.shrink_to_fit();
}
void DatExport::WriteGroup(bool isMe, const std::wstring &time, const std::wstring &user, const std::wstring &eventText)
{
}
void DatExport::WriteMessage(bool isMe, const std::wstring &longDate, const std::wstring &shortDate, const std::wstring &user, const std::wstring &message, const DBEVENTINFO& dbei)
{
DBEVENTINFO86 header;
header.cbSize = sizeof(DBEVENTINFO86);
header.eventType = dbei.eventType;
header.flags = dbei.flags & (~(0x800));
header.timestamp = dbei.timestamp;
header.szModule = 0;
header.pBlob = 0;
if(dbei.flags & 0x800)
{
//Imported
header.flags |= DBEF_UTF;
header.cbBlob = WriteString(message);
EXP_FILE.write((char*)&header, header.cbSize);
EXP_FILE.write(memBuf.c_str(), header.cbBlob);
}
else
{
//Internal
header.cbBlob = dbei.cbBlob;
EXP_FILE.write((char*)&header, header.cbSize);
EXP_FILE.write((char*)dbei.pBlob, header.cbBlob);
}
dataSize += header.cbSize + header.cbBlob;
}
bool ReadHeader(MCHeader& header, std::istream* stream)
{
stream->read((char*)&header, sizeof(MCHeader));
if(!stream->good())
return false;
if(memcmp(header.signature, "HB", 2) != 0)
return false;
return true;
}
int DatExport::IsContactInFile(const std::vector& contacts)
{
MCHeader header;
if(!ReadHeader(header, IImport::stream))
return -2;
if(contacts.size() == 1)
{
hContact = contacts[0];
}
IMP_FILE.seekg(0, std::ios_base::beg);
return -3;
}
bool DatExport::GetEventList(std::vector& eventList)
{
MCHeader header;
if(!ReadHeader(header, IImport::stream))
return false;
dataSize = header.dataSize;
DBEVENTINFO86 messageHeader;
DBEVENTINFO info = {0};
info.cbSize = sizeof(DBEVENTINFO);
info.szModule = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
TCHAR _str[MAXSELECTSTR + 8]; // for safety reason
std::multimap sortedEvents;
while(dataSize > 0)
{
messageHeader.cbSize = 0;
IMP_FILE.read((char*)&messageHeader, sizeof(DBEVENTINFO86));
if(!IMP_FILE.good())
return false;
if(messageHeader.cbSize < sizeof(DBEVENTINFO86))
return false;
if(messageHeader.cbSize > sizeof(DBEVENTINFO86))
{
IMP_FILE.seekg(messageHeader.cbSize - sizeof(DBEVENTINFO86), std::ios_base::cur);
}
IImport::ExternalMessage exMsg;
exMsg.eventType = messageHeader.eventType;
exMsg.flags = messageHeader.flags;
exMsg.timestamp = messageHeader.timestamp;
if(messageHeader.cbBlob > memBuf.size())
{
memBuf.resize(messageHeader.cbBlob);
}
IMP_FILE.read((char*)memBuf.c_str(), messageHeader.cbBlob);
if(!IMP_FILE.good())
return false;
info.eventType = messageHeader.eventType;
info.flags = messageHeader.flags;
info.timestamp = messageHeader.timestamp;
info.cbBlob = messageHeader.cbBlob;
info.pBlob = (PBYTE)memBuf.c_str();
EventList::GetObjectDescription(&info, _str, MAXSELECTSTR);
exMsg.message = _str;
sortedEvents.insert(std::pair(messageHeader.timestamp, exMsg));
dataSize -= messageHeader.cbSize + messageHeader.cbBlob;
}
memBuf.resize(0);
memBuf.shrink_to_fit();
for(std::multimap::iterator it = sortedEvents.begin(); it != sortedEvents.end(); ++it)
{
eventList.push_back(it->second);
}
return true;
}