From dc52f34d8eea756c38bb47218f28727173fb11c7 Mon Sep 17 00:00:00 2001 From: Nicolas VIVIEN Date: Wed, 6 May 2009 10:22:18 +0200 Subject: [PATCH] First version about Phone Call Logs parser --- src/Makefile.am | 2 + src/protostructs.h | 9 +++ src/r_calllog.cc | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/r_calllog.h | 97 +++++++++++++++++++++++++ src/record.h | 1 + tools/btool.cc | 6 ++ 6 files changed, 318 insertions(+) create mode 100644 src/r_calllog.cc create mode 100644 src/r_calllog.h diff --git a/src/Makefile.am b/src/Makefile.am index 16ac0f98..1cc2ed5e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -82,6 +82,7 @@ include_barry_HEADERS = barry.h \ modem.h \ r_recur_base.h \ r_calendar.h \ + r_calllog.h \ r_contact.h \ r_folder.h \ r_memo.h \ @@ -139,6 +140,7 @@ libbarry_la_SOURCES = time.cc \ record.cc \ r_recur_base.cc \ r_calendar.cc \ + r_calllog.cc \ r_contact.cc \ r_folder.cc \ r_memo.cc \ diff --git a/src/protostructs.h b/src/protostructs.h index 69e7aa1e..684141fe 100644 --- a/src/protostructs.h +++ b/src/protostructs.h @@ -294,6 +294,15 @@ struct CalendarRecurrenceDataField // as documented in the Cassis project spec #define TR_STATUS_RANGE_LOW 0 #define TR_STATUS_RANGE_HIGH 4 +// +// Phone Call Logs record: field constants +// +// +#define CLL_STATUS_CALL_RECEIVED 0 +#define CLL_STATUS_CALL_SENT 1 +#define CLL_STATUS_CALL_FAILED 2 +#define CLL_STATUS_RANGE_LOW 0 +#define CLL_STATUS_RANGE_HIGH 2 // // Folder record: field constants diff --git a/src/r_calllog.cc b/src/r_calllog.cc new file mode 100644 index 00000000..7195a26f --- /dev/null +++ b/src/r_calllog.cc @@ -0,0 +1,203 @@ +/// +/// \file r_calllog.cc +/// Record parsing class for the phone call logs database. +/// + +/* + Copyright (C) 2008-2009, Nicolas VIVIEN + Copyright (C) 2005-2009, Net Direct Inc. (http://www.netdirect.ca/) + + 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; either version 2 of the License, or + (at your option) any later version. + + 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 in the COPYING file at the + root directory of this project for more details. +*/ + +#include "r_calllog.h" +#include "record-internal.h" +#include "protostructs.h" +#include "data.h" +#include "time.h" +#include "iconv.h" +#include +#include + +using namespace std; +using namespace Barry::Protocol; + +namespace Barry { + +CallLog::StatusFlagType CallLog::StatusProto2Rec(uint8_t s) +{ + return (StatusFlagType)s; +} + +uint8_t CallLog::StatusRec2Proto(StatusFlagType s) +{ + return s; +} + + +/////////////////////////////////////////////////////////////////////////////// +// CallLog Class + +// CallLog Field Codes +#define CLLFC_CALLLOG_TYPE 0x01 +#define CLLFC_STATUS 0x02 +#define CLLFC_PHONE 0x0c +#define CLLFC_NAME 0x1f +#define CLLFC_TIME 0x05 +#define CLLFC_UNIQUEID 0x07 +#define CLLFC_END 0xffff + +static FieldLink CallLogFieldLinks[] = { + { CLLFC_PHONE, "Phone number", 0, 0, &CallLog::Phone, 0, 0, 0, 0, true }, + { CLLFC_NAME, "Contact name", 0, 0, &CallLog::Name, 0, 0, 0, 0, true }, +// { CLLFC_TIME, "Time", 0, 0, 0, 0, &CallLog::Time, 0, 0, false }, + { CLLFC_END, "End of List", 0, 0, 0, 0, 0, 0, 0, false } +}; + +CallLog::CallLog() +{ + Clear(); +} + +CallLog::~CallLog() +{ +} + +const unsigned char* CallLog::ParseField(const unsigned char *begin, + const unsigned char *end, + const IConverter *ic) +{ + const CommonField *field = (const CommonField *) begin; + + // advance and check size + begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size); + if( begin > end ) // if begin==end, we are ok + return begin; + + if( !btohs(field->size) ) // if field has no size, something's up + return begin; + + if( field->type == CLLFC_CALLLOG_TYPE ) { + if( ( CallLogType = field->u.raw[0] ) != 'p' ) { + throw Error( "CallLog::ParseField: CallLogType is not 'p'" ); + } + return begin; + } + + if( field->type == CLLFC_UNIQUEID) + return begin; + + // cycle through the type table + for( FieldLink *b = CallLogFieldLinks; + b->type != CLLFC_END; + b++ ) + { + if( b->type == field->type ) { + if( b->strMember ) { + std::string &s = this->*(b->strMember); + s = ParseFieldString(field); + if( b->iconvNeeded && ic ) + s = ic->FromBB(s); + return begin; // done! + } + else if( b->timeMember && btohs(field->size) == 4 ) { + time_t &t = this->*(b->timeMember); + t = min2time(field->u.min1900); + return begin; + } + } + } + + // handle special cases +// switch( field->type ) +// { +// case CLLFC_STATUS: +// if( field->u.raw[0] > CLL_STATUS_RANGE_HIGH ) { +// throw Error( "CallLog::ParseField: status field out of bounds" ); +// } +// else { +// StatusFlag = StatusProto2Rec(field->u.raw[0]); +// } +// return begin; +// } + + // if still not handled, add to the Unknowns list + UnknownField uf; + uf.type = field->type; + uf.data.assign((const char*)field->u.raw, btohs(field->size)); + Unknowns.push_back(uf); + + // return new pointer for next field + return begin; +} + +void CallLog::ParseHeader(const Data &data, size_t &offset) +{ + // no header in CallLog records +} + +void CallLog::ParseFields(const Data &data, size_t &offset, const IConverter *ic) +{ + const unsigned char *finish = ParseCommonFields(*this, + data.GetData() + offset, data.GetData() + data.GetSize(), ic); + offset += finish - (data.GetData() + offset); +} + + +void CallLog::Dump(std::ostream &os) const +{ + static const char *StatusName[] = { "Received", "Sent", "Failed" }; + + os << "CallLog entry: 0x" << setbase(16) << RecordId + << " (" << (unsigned int)RecType << ")\n"; + +// os << " Status: " << StatusName[StatusFlag] << "\n"; + + // cycle through the type table + for( const FieldLink *b = CallLogFieldLinks; + b->type != CLLFC_END; + b++ ) + { + if( b->strMember ) { + const std::string &s = this->*(b->strMember); + if( s.size() ) + os << " " << b->name << ": " << s << "\n"; + } + else if( b->timeMember ) { + time_t t = this->*(b->timeMember); + if( t > 0 ) + os << " " << b->name << ": " << ctime(&t); + else + os << " " << b->name << ": unknown\n"; + } + } + + + os << Unknowns; + os << "\n\n"; +} + +void CallLog::Clear() +{ + Phone.clear(); + Name.clear(); + + Time = 0; + CallLogType = 0; + StatusFlag = (StatusFlagType)0; + + Unknowns.clear(); +} + +} // namespace Barry + diff --git a/src/r_calllog.h b/src/r_calllog.h new file mode 100644 index 00000000..267b1350 --- /dev/null +++ b/src/r_calllog.h @@ -0,0 +1,97 @@ +/// +/// \file r_memo.h +/// Record parsing class for the memo database. +/// + +/* + Copyright (C) 2008-2009, Nicolas VIVIEN + Copyright (C) 2005-2009, Net Direct Inc. (http://www.netdirect.ca/) + + 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; either version 2 of the License, or + (at your option) any later version. + + 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 in the COPYING file at the + root directory of this project for more details. +*/ + +#ifndef __BARRY_RECORD_CALLLOG_H__ +#define __BARRY_RECORD_CALLLOG_H__ + +#include "dll.h" +#include "record.h" +#include +#include +#include + +namespace Barry { + +// forward declarations +class IConverter; + +class BXEXPORT CallLog +{ +public: + typedef std::vector UnknownsType; + + uint8_t RecType; + uint32_t RecordId; + + uint8_t CallLogType; + time_t Time; + std::string Name; + std::string Phone; + + enum StatusFlagType + { + Received = 0, + Sent, + Failed + }; + StatusFlagType StatusFlag; + + UnknownsType Unknowns; + +protected: + static StatusFlagType StatusProto2Rec(uint8_t s); + static uint8_t StatusRec2Proto(StatusFlagType s); + +public: + CallLog(); + ~CallLog(); + + // Parser / Builder API (see parser.h / builder.h) + const unsigned char* ParseField(const unsigned char *begin, + const unsigned char *end, const IConverter *ic = 0); + uint8_t GetRecType() const { return RecType; } + uint32_t GetUniqueId() const { return RecordId; } + void SetIds(uint8_t Type, uint32_t Id) { RecType = Type; RecordId = Id; } + void ParseHeader(const Data &data, size_t &offset); + void ParseFields(const Data &data, size_t &offset, const IConverter *ic = 0); + + void Clear(); + + void Dump(std::ostream &os) const; + + // Sorting + bool operator<(const CallLog &other) const { return Time < other.Time; } + + // database name + static const char * GetDBName() { return "Phone Call Logs"; } + static uint8_t GetDefaultRecType() { return 0; } // or 0? +}; + +BXEXPORT inline std::ostream& operator<<(std::ostream &os, const CallLog &msg) { + msg.Dump(os); + return os; +} + +} // namespace Barry + +#endif + diff --git a/src/record.h b/src/record.h index f2607c58..f4c93797 100644 --- a/src/record.h +++ b/src/record.h @@ -267,6 +267,7 @@ BXEXPORT std::ostream& operator<<(std::ostream &os, const Date &date); #ifndef __BARRY_LIBRARY_BUILD__ // Include all parser classes, to make it easy for the application to use. #include "r_calendar.h" +#include "r_calllog.h" #include "r_contact.h" #include "r_memo.h" #include "r_message.h" diff --git a/tools/btool.cc b/tools/btool.cc index 686ebef9..c96d0d8e 100644 --- a/tools/btool.cc +++ b/tools/btool.cc @@ -252,6 +252,11 @@ auto_ptr GetParser(const string &name, const string &filename, bool null new RecordParser > ( new Store(filename, false))); } + else if( name == CallLog::GetDBName() ) { + return auto_ptr( + new RecordParser > ( + new Store(filename, false))); + } else if( name == ServiceBook::GetDBName() ) { return auto_ptr( new RecordParser > ( @@ -345,6 +350,7 @@ void ShowParsers() << " Address Book\n" << " Messages\n" << " Calendar\n" + << " Phone Call Logs\n" << " Service Book\n" << " Memos\n" << " Tasks\n" -- 2.11.4.GIT