- added website docs to doc/www... these are out of date at the
[barry.git] / src / r_servicebook.cc
blobc08f699a7b7c1ac549300afeaa1af562926da864
1 ///
2 /// \file r_servicebook.cc
3 /// Blackberry database record parser class for
4 /// Service Book records.
5 ///
7 /*
8 Copyright (C) 2005-2007, 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"
25 #include "protocol.h"
26 #include "protostructs.h"
27 #include "data.h"
28 #include "time.h"
29 #include "error.h"
30 #include "endian.h"
31 #include <ostream>
32 #include <iomanip>
33 #include <time.h>
34 #include <stdexcept>
36 #define __DEBUG_MODE__
37 #include "debug.h"
39 using namespace std;
40 using namespace Barry::Protocol;
42 namespace Barry {
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()
57 : Format(0)
59 Clear();
62 ServiceBookConfig::~ServiceBookConfig()
66 const unsigned char* ServiceBookConfig::ParseField(const unsigned char *begin,
67 const unsigned char *end)
69 const void *raw;
70 uint16_t size, type;
72 switch( Format )
74 case 0x02:
76 const PackedField_02 *field = (const PackedField_02 *) begin;
77 raw = field->raw;
78 size = field->size;
79 type = field->type;
80 begin += PACKED_FIELD_02_HEADER_SIZE + size;
82 break;
84 case 0x10:
86 const PackedField_10 *field = (const PackedField_10 *) begin;
87 raw = field->raw;
88 size = field->size;
89 type = field->type;
90 begin += PACKED_FIELD_10_HEADER_SIZE + size;
92 break;
94 default:
95 eout("Unknown packed field format" << Format);
96 return begin + 1;
100 // check size
101 if( begin > end ) // if begin==end, we are ok
102 return begin;
104 if( !size ) // if field has no size, something's up
105 return begin;
107 // cycle through the type table
108 for( FieldLink<ServiceBookConfig> *b = ServiceBookConfigFieldLinks;
109 b->type != SBFCC_END;
110 b++ )
112 if( b->type == type ) {
113 if( b->strMember ) {
114 std::string &s = this->*(b->strMember);
115 s = ParseFieldString(raw, size-1);
116 return begin; // done!
122 // handle special cases
123 switch( type )
128 // if still not handled, add to the Unknowns list
129 UnknownField uf;
130 uf.type = type;
131 uf.data.assign((const char*)raw, size);
132 Unknowns.push_back(uf);
134 // return new pointer for next field
135 return begin;
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;
166 // BuildFields
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()
177 Unknowns.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;
187 b++ )
189 if( b->strMember ) {
190 const std::string &s = this->*(b->strMember);
191 if( s.size() )
192 os << " " << b->name << ": " << s << "\n";
194 else if( b->timeMember ) {
195 time_t t = this->*(b->timeMember);
196 if( t > 0 )
197 os << " " << b->name << ": " << ctime(&t);
201 // print any unknowns
202 os << Unknowns;
203 os << " ------------------- End of Config Field\n";
207 ///////////////////////////////////////////////////////////////////////////////
208 // ServiceBook class
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),
235 RecordId(0)
237 Clear();
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
252 return begin;
254 if( !btohs(field->size) ) // if field has no size, something's up
255 return begin;
257 // cycle through the type table
258 for( FieldLink<ServiceBook> *b = ServiceBookFieldLinks;
259 b->type != SBFC_END;
260 b++ )
262 if( b->type == field->type ) {
263 if( b->strMember ) {
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);
271 return begin;
276 // handle special cases
277 switch( field->type )
279 case SBFC_OLD_NAME: // strings with old/new type codes
280 case SBFC_NAME:
281 Name = ParseFieldString(field);
282 NameType = field->type;
283 return begin;
285 case SBFC_OLD_DESC:
286 case SBFC_DESCRIPTION:
287 Description = ParseFieldString(field);
288 DescType = field->type;
289 return begin;
291 case SBFC_OLD_UNIQUE_ID:
292 case SBFC_UNIQUE_ID:
293 UniqueId = ParseFieldString(field);
294 UniqueIdType = field->type;
295 return begin;
297 case SBFC_CONTENT_ID:
298 ContentId = ParseFieldString(field);
299 return begin;
301 case SBFC_BES_DOMAIN:
302 BesDomain = ParseFieldString(field);
303 return begin;
305 case SBFC_CONFIG:
307 Data config((const void *)field->u.raw, btohs(field->size));
308 size_t offset = 0;
309 Config.ParseHeader(config, offset);
310 Config.ParseFields(config, offset);
312 break; // break here so raw packet is still visible in dump
313 // return begin;
316 // if still not handled, add to the Unknowns list
317 UnknownField uf;
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
323 return begin;
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 (?)
344 // BuildFields
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()
355 Unknowns.clear();
356 Config.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;
366 b->type != SBFC_END;
367 b++ )
369 if( b->strMember ) {
370 const std::string &s = this->*(b->strMember);
371 if( s.size() )
372 os << " " << b->name << ": " << s << "\n";
374 else if( b->timeMember ) {
375 time_t t = this->*(b->timeMember);
376 if( t > 0 )
377 os << " " << b->name << ": " << ctime(&t);
381 // special cases
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";
389 os << Config;
391 // print any unknowns
392 os << Unknowns;
395 } // namespace Barry