2 /// \file r_servicebook.cc
3 /// Blackberry database record parser class for
4 /// Service Book records.
8 Copyright (C) 2005-2008, 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 "r_servicebook.h"
24 #include "record-internal.h"
26 #include "protostructs.h"
36 #define __DEBUG_MODE__
40 using namespace Barry::Protocol
;
45 ///////////////////////////////////////////////////////////////////////////////
46 // ServiceBookConfig class
48 // service book packed field codes
49 #define SBFCC_END 0xffff
51 FieldLink
<ServiceBookConfig
> ServiceBookConfigFieldLinks
[] = {
52 // { SBFC_DSID, "DSID", 0, 0, &ServiceBook::DSID, 0, 0 },
53 { SBFCC_END
, "End of List",0, 0, 0, 0, 0 }
56 ServiceBookConfig::ServiceBookConfig()
62 ServiceBookConfig::~ServiceBookConfig()
66 const unsigned char* ServiceBookConfig::ParseField(const unsigned char *begin
,
67 const unsigned char *end
)
76 const PackedField_02
*field
= (const PackedField_02
*) begin
;
80 begin
+= PACKED_FIELD_02_HEADER_SIZE
+ size
;
86 const PackedField_10
*field
= (const PackedField_10
*) begin
;
90 begin
+= PACKED_FIELD_10_HEADER_SIZE
+ size
;
95 eout("Unknown packed field format" << Format
);
101 if( begin
> end
) // if begin==end, we are ok
104 if( !size
) // if field has no size, something's up
107 // cycle through the type table
108 for( FieldLink
<ServiceBookConfig
> *b
= ServiceBookConfigFieldLinks
;
109 b
->type
!= SBFCC_END
;
112 if( b
->type
== type
) {
114 std::string
&s
= this->*(b
->strMember
);
115 s
= ParseFieldString(raw
, size
-1);
116 return begin
; // done!
122 // handle special cases
128 // if still not handled, add to the Unknowns list
131 uf
.data
.assign((const char*)raw
, size
);
132 Unknowns
.push_back(uf
);
134 // return new pointer for next field
138 void ServiceBookConfig::ParseHeader(const Data
&data
, size_t &offset
)
140 MAKE_RECORD(const Barry::Protocol::ServiceBookConfigField
, sbc
, data
, offset
);
141 offset
+= SERVICE_BOOK_CONFIG_FIELD_HEADER_SIZE
;
142 if( data
.GetSize() >= offset
) { // size check!
143 Format
= sbc
->format
;
147 void ServiceBookConfig::ParseFields(const Data
&data
, size_t &offset
)
149 const unsigned char *finish
= ParseCommonFields(*this,
150 data
.GetData() + offset
, data
.GetData() + data
.GetSize());
151 offset
+= finish
- (data
.GetData() + offset
);
154 void ServiceBookConfig::BuildHeader(Data
&data
, size_t &offset
) const
156 // make sure there is enough space
157 data
.GetBuffer(offset
+ SERVICE_BOOK_CONFIG_FIELD_HEADER_SIZE
);
159 MAKE_RECORD(Barry::Protocol::ServiceBookConfigField
, sbc
, data
, offset
);
160 sbc
->format
= Format
;
162 offset
+= SERVICE_BOOK_CONFIG_FIELD_HEADER_SIZE
;
168 /// Build fields part of record
170 void ServiceBookConfig::BuildFields(Data
&data
, size_t &offset
) const
172 throw std::logic_error("ServiceBookConfig::Build not yet implemented");
175 void ServiceBookConfig::Clear()
180 void ServiceBookConfig::Dump(std::ostream
&os
) const
182 os
<< " ServiceBookConfig Format: " << setbase(16) << (uint16_t)Format
<< "\n";
184 // cycle through the type table
185 for( const FieldLink
<ServiceBookConfig
> *b
= ServiceBookConfigFieldLinks
;
186 b
->type
!= SBFCC_END
;
190 const std::string
&s
= this->*(b
->strMember
);
192 os
<< " " << b
->name
<< ": " << s
<< "\n";
194 else if( b
->timeMember
) {
195 time_t t
= this->*(b
->timeMember
);
197 os
<< " " << b
->name
<< ": " << ctime(&t
);
201 // print any unknowns
203 os
<< " ------------------- End of Config Field\n";
207 ///////////////////////////////////////////////////////////////////////////////
210 // service book field codes
211 #define SBFC_OLD_NAME 0x01
212 #define SBFC_HIDDEN_NAME 0x02
213 #define SBFC_NAME 0x03
214 #define SBFC_OLD_UNIQUE_ID 0x06
215 #define SBFC_UNIQUE_ID 0x07
216 #define SBFC_CONTENT_ID 0x08
217 #define SBFC_CONFIG 0x09
218 #define SBFC_OLD_DESC 0x32
219 #define SBFC_DESCRIPTION 0x0f
220 #define SBFC_DSID 0xa1
221 #define SBFC_BES_DOMAIN 0xa2
222 #define SBFC_USER_ID 0xa3
223 #define SBFC_END 0xffff
225 FieldLink
<ServiceBook
> ServiceBookFieldLinks
[] = {
226 { SBFC_HIDDEN_NAME
, "Hidden Name",0, 0, &ServiceBook::HiddenName
, 0, 0 },
227 { SBFC_DSID
, "DSID", 0, 0, &ServiceBook::DSID
, 0, 0 },
228 { SBFC_END
, "End of List",0, 0, 0, 0, 0 }
231 ServiceBook::ServiceBook()
232 : NameType(SBFC_OLD_NAME
),
233 DescType(SBFC_OLD_DESC
),
234 UniqueIdType(SBFC_OLD_UNIQUE_ID
),
240 ServiceBook::~ServiceBook()
244 const unsigned char* ServiceBook::ParseField(const unsigned char *begin
,
245 const unsigned char *end
)
247 const CommonField
*field
= (const CommonField
*) begin
;
249 // advance and check size
250 begin
+= COMMON_FIELD_HEADER_SIZE
+ btohs(field
->size
);
251 if( begin
> end
) // if begin==end, we are ok
254 if( !btohs(field
->size
) ) // if field has no size, something's up
257 // cycle through the type table
258 for( FieldLink
<ServiceBook
> *b
= ServiceBookFieldLinks
;
262 if( b
->type
== field
->type
) {
264 std::string
&s
= this->*(b
->strMember
);
265 s
= ParseFieldString(field
);
266 return begin
; // done!
268 else if( b
->timeMember
&& btohs(field
->size
) == 4 ) {
269 time_t &t
= this->*(b
->timeMember
);
270 t
= min2time(field
->u
.min1900
);
276 // handle special cases
277 switch( field
->type
)
279 case SBFC_OLD_NAME
: // strings with old/new type codes
281 Name
= ParseFieldString(field
);
282 NameType
= field
->type
;
286 case SBFC_DESCRIPTION
:
287 Description
= ParseFieldString(field
);
288 DescType
= field
->type
;
291 case SBFC_OLD_UNIQUE_ID
:
293 UniqueId
= ParseFieldString(field
);
294 UniqueIdType
= field
->type
;
297 case SBFC_CONTENT_ID
:
298 ContentId
= ParseFieldString(field
);
301 case SBFC_BES_DOMAIN
:
302 BesDomain
= ParseFieldString(field
);
307 Data
config((const void *)field
->u
.raw
, btohs(field
->size
));
309 Config
.ParseHeader(config
, offset
);
310 Config
.ParseFields(config
, offset
);
312 break; // break here so raw packet is still visible in dump
316 // if still not handled, add to the Unknowns list
318 uf
.type
= field
->type
;
319 uf
.data
.assign((const char*)field
->u
.raw
, btohs(field
->size
));
320 Unknowns
.push_back(uf
);
322 // return new pointer for next field
326 void ServiceBook::ParseHeader(const Data
&data
, size_t &offset
)
328 // no header in this record (?)
331 void ServiceBook::ParseFields(const Data
&data
, size_t &offset
)
333 const unsigned char *finish
= ParseCommonFields(*this,
334 data
.GetData() + offset
, data
.GetData() + data
.GetSize());
335 offset
+= finish
- (data
.GetData() + offset
);
338 void ServiceBook::BuildHeader(Data
&data
, size_t &offset
) const
340 // no header in this record (?)
346 /// Build fields part of record
348 void ServiceBook::BuildFields(Data
&data
, size_t &offset
) const
350 throw std::logic_error("ServiceBook::BuildFields not yet implemented");
353 void ServiceBook::Clear()
359 void ServiceBook::Dump(std::ostream
&os
) const
361 os
<< "ServiceBook entry: 0x" << setbase(16) << RecordId
362 << " (" << (unsigned int)RecType
<< ")\n";
364 // cycle through the type table
365 for( const FieldLink
<ServiceBook
> *b
= ServiceBookFieldLinks
;
370 const std::string
&s
= this->*(b
->strMember
);
372 os
<< " " << b
->name
<< ": " << s
<< "\n";
374 else if( b
->timeMember
) {
375 time_t t
= this->*(b
->timeMember
);
377 os
<< " " << b
->name
<< ": " << ctime(&t
);
382 if( UniqueId
.size() )
383 os
<< " Unique ID: " << UniqueId
<< "\n";
384 if( ContentId
.size() )
385 os
<< " Content ID: " << ContentId
<< "\n";
386 if( BesDomain
.size() )
387 os
<< " (BES) Domain: " << BesDomain
<< "\n";
391 // print any unknowns