00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "r_calllog.h"
00024 #include "record-internal.h"
00025 #include "protostructs.h"
00026 #include "data.h"
00027 #include "time.h"
00028 #include "iconv.h"
00029 #include <ostream>
00030 #include <iomanip>
00031
00032 using namespace std;
00033 using namespace Barry::Protocol;
00034
00035 namespace Barry {
00036
00037 #define MILLISECONDS_IN_A_SECOND 1000
00038
00039 time_t CallLog::GetTime() const
00040 {
00041 return (time_t)(Timestamp / MILLISECONDS_IN_A_SECOND);
00042 }
00043
00044 CallLog::DirectionFlagType CallLog::DirectionProto2Rec(uint8_t s)
00045 {
00046 return (DirectionFlagType)s;
00047 }
00048
00049 uint8_t CallLog::DirectionRec2Proto(DirectionFlagType s)
00050 {
00051 return s;
00052 }
00053
00054 CallLog::PhoneTypeFlagType CallLog::PhoneTypeProto2Rec(uint8_t s)
00055 {
00056 return (PhoneTypeFlagType)s;
00057 }
00058
00059 uint8_t CallLog::PhoneTypeRec2Proto(PhoneTypeFlagType s)
00060 {
00061 return s;
00062 }
00063
00064
00065
00066
00067
00068
00069 #define CLLFC_CALLLOG_TYPE 0x01
00070 #define CLLFC_DIRECTION 0x02
00071 #define CLLFC_DURATION 0x03
00072 #define CLLFC_TIMESTAMP 0x04
00073 #define CLLFC_STATUS 0x06
00074 #define CLLFC_UNIQUEID 0x07
00075 #define CLLFC_PHONE_TYPE 0x0b
00076 #define CLLFC_PHONE_NUMBER 0x0c
00077 #define CLLFC_PHONE_INFO 0x0d
00078 #define CLLFC_CONTACT_NAME 0x1f
00079 #define CLLFC_END 0xffff
00080
00081 static FieldLink<CallLog> CallLogFieldLinks[] = {
00082 { CLLFC_PHONE_NUMBER, "Phone number", 0, 0, &CallLog::PhoneNumber, 0, 0, 0, 0, true },
00083 { CLLFC_CONTACT_NAME, "Contact name", 0, 0, &CallLog::ContactName, 0, 0, 0, 0, true },
00084 { CLLFC_END, "End of List", 0, 0, 0, 0, 0, 0, 0, false }
00085 };
00086
00087 CallLog::CallLog()
00088 {
00089 Clear();
00090 }
00091
00092 CallLog::~CallLog()
00093 {
00094 }
00095
00096 const unsigned char* CallLog::ParseField(const unsigned char *begin,
00097 const unsigned char *end,
00098 const IConverter *ic)
00099 {
00100 const CommonField *field = (const CommonField *) begin;
00101
00102
00103 begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
00104 if( begin > end )
00105 return begin;
00106
00107 if( !btohs(field->size) )
00108 return begin;
00109
00110 if( field->type == CLLFC_CALLLOG_TYPE ) {
00111 if( field->u.raw[0] != 'p' ) {
00112 throw Error( "CallLog::ParseField: CallLogType is not 'p'" );
00113 }
00114 return begin;
00115 }
00116
00117
00118
00119 if( field->type == CLLFC_UNIQUEID)
00120 return begin;
00121
00122
00123 for( FieldLink<CallLog> *b = CallLogFieldLinks;
00124 b->type != CLLFC_END;
00125 b++ )
00126 {
00127 if( b->type == field->type ) {
00128 if( b->strMember ) {
00129 std::string &s = this->*(b->strMember);
00130 s = ParseFieldString(field);
00131 if( b->iconvNeeded && ic )
00132 s = ic->FromBB(s);
00133 return begin;
00134 }
00135 else if( b->timeMember && btohs(field->size) == 4 ) {
00136 time_t &t = this->*(b->timeMember);
00137 t = min2time(field->u.min1900);
00138 return begin;
00139 }
00140 }
00141 }
00142
00143
00144 switch( field->type )
00145 {
00146 case CLLFC_STATUS:
00147
00148 switch (field->u.raw[0]) {
00149 case 0x00:
00150 StatusFlag = Barry::CallLog::OK;
00151 break;
00152 case 0x01:
00153 StatusFlag = Barry::CallLog::Busy;
00154 break;
00155 case 0x09:
00156 StatusFlag = Barry::CallLog::NetError;
00157 break;
00158 default:
00159 StatusFlag = Barry::CallLog::Unknown;
00160 }
00161 return begin;
00162
00163 case CLLFC_DIRECTION:
00164 if( field->u.raw[0] > CLL_DIRECTION_RANGE_HIGH ) {
00165 throw Error( "CallLog::ParseField: direction field out of bounds" );
00166 }
00167 else {
00168 DirectionFlag = DirectionProto2Rec(field->u.raw[0]);
00169 }
00170 return begin;
00171
00172 case CLLFC_PHONE_TYPE:
00173 if( field->u.raw[0] > CLL_PHONETYPE_RANGE_HIGH ) {
00174 PhoneTypeFlag = Barry::CallLog::TypeUnknown;
00175 }
00176 else {
00177 PhoneTypeFlag = PhoneTypeProto2Rec(field->u.raw[0]);
00178 }
00179 return begin;
00180
00181 case CLLFC_PHONE_INFO:
00182 switch (field->u.raw[0]) {
00183 case 0x03:
00184 PhoneInfoFlag = Barry::CallLog::InfoKnown;
00185 break;
00186 case 0x80:
00187 PhoneInfoFlag = Barry::CallLog::InfoUnknown;
00188 break;
00189 case 0x40:
00190 PhoneInfoFlag = Barry::CallLog::InfoPrivate;
00191 break;
00192 default:
00193 PhoneInfoFlag = Barry::CallLog::InfoUndefined;
00194 }
00195 return begin;
00196
00197 case CLLFC_DURATION:
00198 if( btohs(field->size) >= sizeof(field->u.uint32) ) {
00199 Duration = btohl(field->u.uint32);
00200 return begin;
00201 }
00202 break;
00203
00204 case CLLFC_TIMESTAMP:
00205 if( btohs(field->size) >= sizeof(field->u.timestamp) ) {
00206 Timestamp = btohll(field->u.timestamp);
00207 return begin;
00208 }
00209 break;
00210 }
00211
00212
00213 UnknownField uf;
00214 uf.type = field->type;
00215 uf.data.assign((const char*)field->u.raw, btohs(field->size));
00216 Unknowns.push_back(uf);
00217
00218
00219 return begin;
00220 }
00221
00222 void CallLog::ParseHeader(const Data &data, size_t &offset)
00223 {
00224
00225 }
00226
00227 void CallLog::ParseFields(const Data &data, size_t &offset, const IConverter *ic)
00228 {
00229 const unsigned char *finish = ParseCommonFields(*this,
00230 data.GetData() + offset, data.GetData() + data.GetSize(), ic);
00231 offset += finish - (data.GetData() + offset);
00232 }
00233
00234 void CallLog::BuildHeader(Data &data, size_t &offset) const
00235 {
00236
00237 }
00238
00239 void CallLog::BuildFields(Data &data, size_t &offset, const IConverter *ic) const
00240 {
00241
00242 }
00243
00244 void CallLog::Dump(std::ostream &os) const
00245 {
00246 uint32_t timestamp = Duration;
00247 int32_t days, hours, minutes, secondes;
00248
00249 static const char *DirectionName[] = { "Received", "Sent", "Call Missing (Messagerie)", "Call Missing" };
00250 static const char *StatusName[] = { "OK", "Busy", "Error", "Not supported by Barry" };
00251 static const char *PhoneInfoName[] = { "Undefined", "Known phone number", "Unknown phone number", "Private phone number" };
00252 static const char *PhoneTypeName[] = { "Unknown", "Office", "Home", "Mobile", "Not supported by Barry" };
00253
00254 os << "CallLog entry: 0x" << setbase(16) << RecordId
00255 << " (" << (unsigned int)RecType << ")\n";
00256
00257 time_t t = GetTime();
00258 os << " Timestamp: " << ctime(&t);
00259 os << " Direction: " << DirectionName[DirectionFlag] << "\n";
00260 os << " Status: " << StatusName[StatusFlag] << "\n";
00261 os << " Phone info: " << PhoneInfoName[PhoneInfoFlag] << "\n";
00262 os << " Phone type: " << PhoneTypeName[PhoneTypeFlag] << "\n";
00263
00264 os << " Duration: ";
00265
00266
00267 days = (int) (timestamp / (60 * 60 * 24));
00268 timestamp = timestamp - (days * (60 * 60 * 24));
00269
00270 hours = (int) (timestamp / (60 * 60));
00271 timestamp = timestamp - (hours * (60 * 60));
00272
00273 minutes = (int) (timestamp / 60);
00274 timestamp = timestamp - (minutes * 60);
00275
00276 secondes = timestamp;
00277
00278 if (days > 1)
00279 os << setbase(10) << days << " days ";
00280 else if (days > 0)
00281 os << setbase(10) << days << " day ";
00282
00283 os << setfill ('0') << setw(2) << setbase(10) << hours;
00284 os << ":";
00285 os << setfill ('0') << setw(2) << setbase(10) << minutes;
00286 os << ":";
00287 os << setfill ('0') << setw(2) << setbase(10) << secondes;
00288 os << "\n";
00289
00290
00291 for( const FieldLink<CallLog> *b = CallLogFieldLinks;
00292 b->type != CLLFC_END;
00293 b++ )
00294 {
00295 if( b->strMember ) {
00296 const std::string &s = this->*(b->strMember);
00297 if( s.size() )
00298 os << " " << b->name << ": " << s << "\n";
00299 }
00300 else if( b->timeMember ) {
00301 time_t t = this->*(b->timeMember);
00302 if( t > 0 )
00303 os << " " << b->name << ": " << ctime(&t);
00304 else
00305 os << " " << b->name << ": unknown\n";
00306 }
00307 }
00308
00309
00310 os << Unknowns;
00311 os << "\n\n";
00312 }
00313
00314 void CallLog::Clear()
00315 {
00316 RecType = GetDefaultRecType();
00317 RecordId = 0;
00318
00319 Duration = 0;
00320 Timestamp = 0;
00321
00322 ContactName.clear();
00323 PhoneNumber.clear();
00324
00325 DirectionFlag = Barry::CallLog::Receiver;
00326 StatusFlag = Barry::CallLog::Unknown;
00327 PhoneTypeFlag = Barry::CallLog::TypeUnknown;
00328 PhoneInfoFlag = Barry::CallLog::InfoUndefined;
00329
00330 Unknowns.clear();
00331 }
00332
00333 std::string CallLog::GetDescription() const
00334 {
00335 return ContactName;
00336 }
00337
00338 }
00339