debian: first review version for intrigeri: 0.18.5-1~rc1
[barry.git] / src / r_calllog.cc
blobd8fddfaf8d20d69759a1f25fbefb13ce8f0201fe
1 ///
2 /// \file r_calllog.cc
3 /// Record parsing class for the phone call logs database.
4 ///
6 /*
7 Copyright (C) 2008-2009, Nicolas VIVIEN
8 Copyright (C) 2005-2013, Net Direct Inc. (http://www.netdirect.ca/)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License in the COPYING file at the
20 root directory of this project for more details.
23 #include "i18n.h"
24 #include "r_calllog.h"
25 #include "record-internal.h"
26 #include "protostructs.h"
27 #include "data.h"
28 #include "time.h"
29 #include "iconv.h"
30 #include <ostream>
31 #include <iomanip>
32 #include "ios_state.h"
34 using namespace std;
35 using namespace Barry::Protocol;
37 namespace Barry {
39 #define MILLISECONDS_IN_A_SECOND 1000
41 time_t CallLog::GetTime() const
43 return (time_t)(Timestamp / MILLISECONDS_IN_A_SECOND);
46 CallLog::DirectionFlagType CallLog::DirectionProto2Rec(uint8_t s)
48 return (DirectionFlagType)s;
51 uint8_t CallLog::DirectionRec2Proto(DirectionFlagType s)
53 return s;
56 CallLog::PhoneTypeFlagType CallLog::PhoneTypeProto2Rec(uint8_t s)
58 return (PhoneTypeFlagType)s;
61 uint8_t CallLog::PhoneTypeRec2Proto(PhoneTypeFlagType s)
63 return s;
67 ///////////////////////////////////////////////////////////////////////////////
68 // CallLog Class
70 // CallLog Field Codes
71 #define CLLFC_CALLLOG_TYPE 0x01
72 #define CLLFC_DIRECTION 0x02
73 #define CLLFC_DURATION 0x03
74 #define CLLFC_TIMESTAMP 0x04
75 #define CLLFC_STATUS 0x06
76 #define CLLFC_UNIQUEID 0x07
77 #define CLLFC_PHONE_TYPE 0x0b
78 #define CLLFC_PHONE_NUMBER 0x0c
79 #define CLLFC_PHONE_INFO 0x0d
80 #define CLLFC_CONTACT_NAME 0x1f
81 #define CLLFC_END 0xffff
83 static FieldLink<CallLog> CallLogFieldLinks[] = {
84 { CLLFC_PHONE_NUMBER, N_("Phone number"), 0, 0, &CallLog::PhoneNumber, 0, 0, 0, 0, true },
85 { CLLFC_CONTACT_NAME, N_("Contact name"), 0, 0, &CallLog::ContactName, 0, 0, 0, 0, true },
86 { CLLFC_END, N_("End of List"), 0, 0, 0, 0, 0, 0, 0, false }
89 CallLog::CallLog()
91 Clear();
94 CallLog::~CallLog()
98 const unsigned char* CallLog::ParseField(const unsigned char *begin,
99 const unsigned char *end,
100 const IConverter *ic)
102 const CommonField *field = (const CommonField *) begin;
104 // advance and check size
105 begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
106 if( begin > end ) // if begin==end, we are ok
107 return begin;
109 if( !btohs(field->size) ) // if field has no size, something's up
110 return begin;
112 if( field->type == CLLFC_CALLLOG_TYPE ) {
113 if( field->u.raw[0] != 'p' ) {
114 throw Error( _("CallLog::ParseField: CallLogType is not 'p'") );
116 return begin;
119 // this is always the same as the RecordID from the lower level
120 // protocol, so we throw this away for now
121 if( field->type == CLLFC_UNIQUEID)
122 return begin;
124 // cycle through the type table
125 for( FieldLink<CallLog> *b = CallLogFieldLinks;
126 b->type != CLLFC_END;
127 b++ )
129 if( b->type == field->type ) {
130 if( b->strMember ) {
131 std::string &s = this->*(b->strMember);
132 s = ParseFieldString(field);
133 if( b->iconvNeeded && ic )
134 s = ic->FromBB(s);
135 return begin; // done!
137 else if( b->timeMember && btohs(field->size) == 4 ) {
138 TimeT &t = this->*(b->timeMember);
139 t.Time = min2time(field->u.min1900);
140 return begin;
145 // handle special cases
146 switch( field->type )
148 case CLLFC_STATUS:
149 // single byte... size check above checks for non-zero already
150 switch (field->u.raw[0]) {
151 case 0x00:
152 StatusFlag = Barry::CallLog::OK;
153 break;
154 case 0x01:
155 StatusFlag = Barry::CallLog::Busy;
156 break;
157 case 0x09:
158 StatusFlag = Barry::CallLog::NetError;
159 break;
160 default:
161 StatusFlag = Barry::CallLog::Unknown;
163 return begin;
165 case CLLFC_DIRECTION:
166 if( field->u.raw[0] > CLL_DIRECTION_RANGE_HIGH ) {
167 throw Error( _("CallLog::ParseField: direction field out of bounds") );
169 else {
170 DirectionFlag = DirectionProto2Rec(field->u.raw[0]);
172 return begin;
174 case CLLFC_PHONE_TYPE:
175 if( field->u.raw[0] > CLL_PHONETYPE_RANGE_HIGH ) {
176 PhoneTypeFlag = Barry::CallLog::TypeUnknown;
178 else {
179 PhoneTypeFlag = PhoneTypeProto2Rec(field->u.raw[0]);
181 return begin;
183 case CLLFC_PHONE_INFO:
184 switch (field->u.raw[0]) {
185 case 0x03:
186 PhoneInfoFlag = Barry::CallLog::InfoKnown;
187 break;
188 case 0x80:
189 PhoneInfoFlag = Barry::CallLog::InfoUnknown;
190 break;
191 case 0x40:
192 PhoneInfoFlag = Barry::CallLog::InfoPrivate;
193 break;
194 default:
195 PhoneInfoFlag = Barry::CallLog::InfoUndefined;
197 return begin;
199 case CLLFC_DURATION:
200 if( btohs(field->size) >= sizeof(field->u.uint32) ) {
201 Duration = btohl(field->u.uint32);
202 return begin;
204 break;
206 case CLLFC_TIMESTAMP:
207 if( btohs(field->size) >= sizeof(field->u.timestamp) ) {
208 Timestamp = btohll(field->u.timestamp);
209 return begin;
211 break;
214 // if still not handled, add to the Unknowns list
215 UnknownField uf;
216 uf.type = field->type;
217 uf.data.assign((const char*)field->u.raw, btohs(field->size));
218 Unknowns.push_back(uf);
220 // return new pointer for next field
221 return begin;
224 void CallLog::ParseHeader(const Data &data, size_t &offset)
226 // no header in CallLog records
229 void CallLog::ParseFields(const Data &data, size_t &offset, const IConverter *ic)
231 const unsigned char *finish = ParseCommonFields(*this,
232 data.GetData() + offset, data.GetData() + data.GetSize(), ic);
233 offset += finish - (data.GetData() + offset);
236 void CallLog::Validate() const
240 void CallLog::BuildHeader(Data &data, size_t &offset) const
242 // not yet implemented
245 void CallLog::BuildFields(Data &data, size_t &offset, const IConverter *ic) const
247 // not yet implemented
250 void CallLog::Dump(std::ostream &os) const
252 ios_format_state state(os);
254 uint32_t timestamp = Duration;
255 int32_t days, hours, minutes, secondes;
257 static const char *DirectionName[] = {
258 N_("Received"),
259 N_("Sent"),
260 N_("Call Missing (Messagerie)"),
261 N_("Call Missing")
263 static const char *StatusName[] = {
264 N_("OK"),
265 N_("Busy"),
266 N_("Error"),
267 N_("Not supported by Barry")
269 static const char *PhoneInfoName[] = {
270 N_("Undefined"),
271 N_("Known phone number"),
272 N_("Unknown phone number"),
273 N_("Private phone number")
275 static const char *PhoneTypeName[] = {
276 N_("Unknown"),
277 N_("Office"),
278 N_("Home"),
279 N_("Mobile"),
280 N_("Not supported by Barry")
283 os << _("CallLog entry: ") << "0x" << setbase(16) << RecordId
284 << " (" << (unsigned int)RecType << ")\n";
286 time_t t = GetTime();
287 os << _(" Timestamp: ") << ctime(&t);
288 os << _(" Direction: ")
289 << gettext( DirectionName[DirectionFlag] ) << "\n";
290 os << _(" Status: ")
291 << gettext( StatusName[StatusFlag] ) << "\n";
292 os << _(" Phone info: ")
293 << gettext( PhoneInfoName[PhoneInfoFlag] ) << "\n";
294 os << _(" Phone type: ")
295 << gettext( PhoneTypeName[PhoneTypeFlag] ) << "\n";
297 os << _(" Duration: ");
299 // Days :
300 days = (int) (timestamp / (60 * 60 * 24));
301 timestamp = timestamp - (days * (60 * 60 * 24));
302 // Hours :
303 hours = (int) (timestamp / (60 * 60));
304 timestamp = timestamp - (hours * (60 * 60));
305 // Minutes :
306 minutes = (int) (timestamp / 60);
307 timestamp = timestamp - (minutes * 60);
308 // Secondes :
309 secondes = timestamp;
311 if (days > 1)
312 os << setbase(10) << days << _(" days ");
313 else if (days > 0)
314 os << setbase(10) << days << _(" day ");
316 os << setfill ('0') << setw(2) << setbase(10) << hours;
317 os << ":";
318 os << setfill ('0') << setw(2) << setbase(10) << minutes;
319 os << ":";
320 os << setfill ('0') << setw(2) << setbase(10) << secondes;
321 os << "\n";
323 // cycle through the type table
324 for( const FieldLink<CallLog> *b = CallLogFieldLinks;
325 b->type != CLLFC_END;
326 b++ )
328 if( b->strMember ) {
329 const std::string &s = this->*(b->strMember);
330 if( s.size() )
331 os << " " << gettext(b->name) << ": " << s << "\n";
333 else if( b->timeMember ) {
334 TimeT t = this->*(b->timeMember);
335 if( t.Time > 0 )
336 os << " " << gettext(b->name) << ": " << t << "\n";
337 else
338 os << " " << gettext(b->name) << ": " << _("unknown") << "\n";
343 os << Unknowns;
344 os << "\n\n";
347 void CallLog::Clear()
349 RecType = GetDefaultRecType();
350 RecordId = 0;
352 Duration = 0;
353 Timestamp = 0;
355 ContactName.clear();
356 PhoneNumber.clear();
358 DirectionFlag = Barry::CallLog::Receiver;
359 StatusFlag = Barry::CallLog::Unknown;
360 PhoneTypeFlag = Barry::CallLog::TypeUnknown;
361 PhoneInfoFlag = Barry::CallLog::InfoUndefined;
363 Unknowns.clear();
366 const FieldHandle<CallLog>::ListT& CallLog::GetFieldHandles()
368 static FieldHandle<CallLog>::ListT fhv;
370 if( fhv.size() )
371 return fhv;
373 #undef CONTAINER_OBJECT_NAME
374 #define CONTAINER_OBJECT_NAME fhv
376 #undef RECORD_CLASS_NAME
377 #define RECORD_CLASS_NAME CallLog
379 FHP(RecType, _("Record Type Code"));
380 FHP(RecordId, _("Unique Record ID"));
382 FHD(Duration, _("Duration of Call in Seconds"), CLLFC_DURATION, false);
383 FHD(Timestamp, _("Timestamp of Call in Milliseconds"), CLLFC_TIMESTAMP, false);
384 FHD(ContactName, _("Contact Name"), CLLFC_CONTACT_NAME, true);
385 FHD(PhoneNumber, _("Phone Number"), CLLFC_PHONE_NUMBER, true);
387 FHE(dft, DirectionFlagType, DirectionFlag, _("Direction of Call"));
388 FHE_CONST(dft, Receiver, _("Received Call"));
389 FHE_CONST(dft, Emitter, _("Placed the Call"));
390 FHE_CONST(dft, Failed, _("Failed Call"));
391 FHE_CONST(dft, Missing, _("Missed Call"));
393 FHE(sft, StatusFlagType, StatusFlag, _("Status of Call"));
394 FHE_CONST(sft, OK, _("OK"));
395 FHE_CONST(sft, Busy, _("Busy"));
396 FHE_CONST(sft, NetError, _("Network Error"));
397 FHE_CONST(sft, Unknown, _("Unsupported Status"));
399 FHE(ptf, PhoneTypeFlagType, PhoneTypeFlag, _("Phone Type"));
400 FHE_CONST(ptf, TypeUndefined, _("Undefined"));
401 FHE_CONST(ptf, TypeOffice, _("Office"));
402 FHE_CONST(ptf, TypeHome, _("Home"));
403 FHE_CONST(ptf, TypeMobile, _("Mobile"));
404 FHE_CONST(ptf, TypeUnknown, _("Unknown"));
406 FHE(pif, PhoneInfoFlagType, PhoneInfoFlag, _("Phone Info"));
407 FHE_CONST(pif, InfoUndefined, _("Undefined"));
408 FHE_CONST(pif, InfoKnown, _("Phone Number is Set"));
409 FHE_CONST(pif, InfoUnknown, _("Phone Number Not Set"));
410 FHE_CONST(pif, InfoPrivate, _("Phone Number is Private"));
412 FHP(Unknowns, _("Unknown Fields"));
414 return fhv;
417 std::string CallLog::GetDescription() const
419 return ContactName;
422 } // namespace Barry