/* 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 "BinaryExport.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 BinaryFileHeader { unsigned char signature[4]; unsigned char version; unsigned char extraFlags; unsigned short int reserved; unsigned int codepage; unsigned short int dataStart; }; struct BinaryFileMessageHeader { DWORD timestamp; WORD eventType; WORD flags; }; #pragma pack(pop) BinaryExport::~BinaryExport() { } void BinaryExport::WriteString(const std::wstring &str) { int conv = WideCharToMultiByte(codepage, 0, str.c_str(), (int)str.length() + 1, NULL, 0, NULL, NULL); char* buf = new char[conv]; conv = WideCharToMultiByte(codepage, 0, str.c_str(), (int)str.length() + 1, buf, conv, NULL, NULL); EXP_FILE.write(buf, conv); delete[] buf; } bool BinaryExport::ReadString(std::wstring &str) { std::string buf; int size = 1024; int pos = 0; int totalSize = 0; while(true) { buf.resize(size); if (IMP_FILE.peek() == 0) { IMP_FILE.get(); break; } IMP_FILE.get(((char*)buf.c_str()) + pos, size - pos, 0); if (!IMP_FILE.good()) return false; int readed = IMP_FILE.gcount(); totalSize += readed; char end; IMP_FILE.get(end); if (!IMP_FILE.good()) return false; if (end == 0) break; if (size - pos - 1 != readed) return false; buf[size - 1] = end; ++totalSize; size += 1024; pos += 1024; } if (totalSize == 0) return true; int sizeW = MultiByteToWideChar(codepage, 0, (char*)buf.c_str(), totalSize, NULL, 0); str.resize(sizeW); MultiByteToWideChar(codepage, 0, (char*)buf.c_str(), totalSize, (wchar_t*)str.c_str(), sizeW); return true; } void BinaryExport::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) { BinaryFileHeader header; memset(&header, 0, sizeof(BinaryFileHeader)); memcpy(header.signature, "BHBF", 4); header.codepage = codepage = CP_UTF8; EXP_FILE.write((char*)&header, sizeof(BinaryFileHeader)); WriteString(filterName); WriteString(myName); WriteString(myId); WriteString(name1); WriteString(proto1); WriteString(id1); size_t pos = EXP_FILE.tellp(); header.dataStart = (unsigned short)pos; EXP_FILE.seekp(offsetof(BinaryFileHeader, dataStart), std::ios_base::beg); EXP_FILE.write((char*)&(header.dataStart), sizeof(header.dataStart)); EXP_FILE.seekp(pos, std::ios_base::beg); lTime = 0; } void BinaryExport::WriteFooter() { } void BinaryExport::WriteGroup(bool isMe, const std::wstring &time, const std::wstring &user, const std::wstring &eventText) { } void BinaryExport::WriteMessage(bool isMe, const std::wstring &longDate, const std::wstring &shortDate, const std::wstring &user, const std::wstring &message, const DBEVENTINFO& dbei) { if (dbei.timestamp >= lTime) { BinaryFileMessageHeader header; header.eventType = dbei.eventType; header.flags = dbei.flags & (~(0x800)); header.timestamp = dbei.timestamp; EXP_FILE.write((char*)&header, sizeof(BinaryFileMessageHeader)); WriteString(message); lTime = dbei.timestamp; } } bool ReadHeader(BinaryFileHeader& header, std::istream* stream) { stream->read((char*)&header, sizeof(BinaryFileHeader)); if (!stream->good()) return false; if (memcmp(header.signature, "BHBF", 4) != 0) return false; if (header.version != 0 || header.codepage == 12000 || header.codepage == 12001) return false; return true; } int BinaryExport::IsContactInFile(const std::vector& contacts) { BinaryFileHeader header; if (!ReadHeader(header, IImport::stream)) return -2; codepage = header.codepage; std::wstring filterName; std::wstring myName; std::wstring myId; std::wstring name1; std::wstring proto1; std::wstring id1; if (!ReadString(filterName)) return -2; if (!ReadString(myName)) return -2; if (!ReadString(myId)) return -2; if (!ReadString(name1)) return -2; if (!ReadString(proto1)) return -2; if (!ReadString(id1)) return -2; size_t pos = IMP_FILE.tellg(); if (header.dataStart < pos) return -2; IMP_FILE.seekg(0, std::ios_base::beg); for (int i = 0; i < (int)contacts.size(); ++i) { std::wstring pn = GetProtocolName(contacts[i]); std::wstring id = GetContactId(contacts[i]); if (pn == proto1 && id == id1) return i; } return -1; } bool BinaryExport::GetEventList(std::vector& eventList) { BinaryFileHeader header; if (!ReadHeader(header, IImport::stream)) return false; codepage = header.codepage; IMP_FILE.seekg(header.dataStart, std::ios_base::beg); BinaryFileMessageHeader messageHeader; while(true) { IMP_FILE.read((char*)&messageHeader, sizeof(BinaryFileMessageHeader)); if (IMP_FILE.eof()) break; if (!IMP_FILE.good()) return false; IImport::ExternalMessage exMsg; exMsg.eventType = messageHeader.eventType; exMsg.flags = messageHeader.flags; exMsg.timestamp = messageHeader.timestamp; if (!ReadString(exMsg.message)) return false; eventList.push_back(exMsg); } return true; }