r_servicebook.cc

Go to the documentation of this file.
00001 ///
00002 /// \file       r_servicebook.cc
00003 ///             Blackberry database record parser class for
00004 ///             Service Book records.
00005 ///
00006 
00007 /*
00008     Copyright (C) 2005-2008, Net Direct Inc. (http://www.netdirect.ca/)
00009 
00010     This program is free software; you can redistribute it and/or modify
00011     it under the terms of the GNU General Public License as published by
00012     the Free Software Foundation; either version 2 of the License, or
00013     (at your option) any later version.
00014 
00015     This program is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00018 
00019     See the GNU General Public License in the COPYING file at the
00020     root directory of this project for more details.
00021 */
00022 
00023 #include "r_servicebook.h"
00024 #include "record-internal.h"
00025 #include "protocol.h"
00026 #include "protostructs.h"
00027 #include "data.h"
00028 #include "time.h"
00029 #include "error.h"
00030 #include "endian.h"
00031 #include <ostream>
00032 #include <iomanip>
00033 #include <time.h>
00034 #include <stdexcept>
00035 
00036 #define __DEBUG_MODE__
00037 #include "debug.h"
00038 
00039 using namespace std;
00040 using namespace Barry::Protocol;
00041 
00042 namespace Barry {
00043 
00044 
00045 ///////////////////////////////////////////////////////////////////////////////
00046 // ServiceBookConfig class
00047 
00048 // service book packed field codes
00049 #define SBFCC_END                       0xffff
00050 
00051 FieldLink<ServiceBookConfig> ServiceBookConfigFieldLinks[] = {
00052 //   { SBFC_DSID,        "DSID",       0, 0,    &ServiceBook::DSID, 0, 0 },
00053    { SBFCC_END,         "End of List",0, 0,    0, 0, 0 }
00054 };
00055 
00056 ServiceBookConfig::ServiceBookConfig()
00057         : Format(0)
00058 {
00059         Clear();
00060 }
00061 
00062 ServiceBookConfig::~ServiceBookConfig()
00063 {
00064 }
00065 
00066 const unsigned char* ServiceBookConfig::ParseField(const unsigned char *begin,
00067                                                    const unsigned char *end)
00068 {
00069         const void *raw;
00070         uint16_t size, type;
00071 
00072         switch( Format )
00073         {
00074         case 0x02:
00075                 {
00076                         const PackedField_02 *field = (const PackedField_02 *) begin;
00077                         raw = field->raw;
00078                         size = field->size;
00079                         type = field->type;
00080                         begin += PACKED_FIELD_02_HEADER_SIZE + size;
00081                 }
00082                 break;
00083 
00084         case 0x10:
00085                 {
00086                         const PackedField_10 *field = (const PackedField_10 *) begin;
00087                         raw = field->raw;
00088                         size = field->size;
00089                         type = field->type;
00090                         begin += PACKED_FIELD_10_HEADER_SIZE + size;
00091                 }
00092                 break;
00093 
00094         default:
00095                 eout("Unknown packed field format" << Format);
00096                 return begin + 1;
00097         }
00098 
00099 
00100         // check size
00101         if( begin > end )               // if begin==end, we are ok
00102                 return begin;
00103 
00104         if( !size )             // if field has no size, something's up
00105                 return begin;
00106 
00107         // cycle through the type table
00108         for(    FieldLink<ServiceBookConfig> *b = ServiceBookConfigFieldLinks;
00109                 b->type != SBFCC_END;
00110                 b++ )
00111         {
00112                 if( b->type == type ) {
00113                         if( b->strMember ) {
00114                                 std::string &s = this->*(b->strMember);
00115                                 s = ParseFieldString(raw, size-1);
00116                                 return begin;   // done!
00117                         }
00118                 }
00119         }
00120 
00121 /*
00122         // handle special cases
00123         switch( type )
00124         {
00125         }
00126 */
00127 
00128         // if still not handled, add to the Unknowns list
00129         UnknownField uf;
00130         uf.type = type;
00131         uf.data.assign((const char*)raw, size);
00132         Unknowns.push_back(uf);
00133 
00134         // return new pointer for next field
00135         return begin;
00136 }
00137 
00138 void ServiceBookConfig::ParseHeader(const Data &data, size_t &offset)
00139 {
00140         MAKE_RECORD(const Barry::Protocol::ServiceBookConfigField, sbc, data, offset);
00141         offset += SERVICE_BOOK_CONFIG_FIELD_HEADER_SIZE;
00142         if( data.GetSize() >= offset ) {        // size check!
00143                 Format = sbc->format;
00144         }
00145 }
00146 
00147 void ServiceBookConfig::ParseFields(const Data &data, size_t &offset)
00148 {
00149         const unsigned char *finish = ParseCommonFields(*this,
00150                 data.GetData() + offset, data.GetData() + data.GetSize());
00151         offset += finish - (data.GetData() + offset);
00152 }
00153 
00154 void ServiceBookConfig::BuildHeader(Data &data, size_t &offset) const
00155 {
00156         // make sure there is enough space
00157         data.GetBuffer(offset + SERVICE_BOOK_CONFIG_FIELD_HEADER_SIZE);
00158 
00159         MAKE_RECORD(Barry::Protocol::ServiceBookConfigField, sbc, data, offset);
00160         sbc->format = Format;
00161 
00162         offset += SERVICE_BOOK_CONFIG_FIELD_HEADER_SIZE;
00163 }
00164 
00165 //
00166 // BuildFields
00167 //
00168 /// Build fields part of record
00169 ///
00170 void ServiceBookConfig::BuildFields(Data &data, size_t &offset) const
00171 {
00172         throw std::logic_error("ServiceBookConfig::Build not yet implemented");
00173 }
00174 
00175 void ServiceBookConfig::Clear()
00176 {
00177         Unknowns.clear();
00178 }
00179 
00180 void ServiceBookConfig::Dump(std::ostream &os) const
00181 {
00182         os << "   ServiceBookConfig Format: " << setbase(16) << (uint16_t)Format << "\n";
00183 
00184         // cycle through the type table
00185         for(    const FieldLink<ServiceBookConfig> *b = ServiceBookConfigFieldLinks;
00186                 b->type != SBFCC_END;
00187                 b++ )
00188         {
00189                 if( b->strMember ) {
00190                         const std::string &s = this->*(b->strMember);
00191                         if( s.size() )
00192                                 os << "      " << b->name << ": " << s << "\n";
00193                 }
00194                 else if( b->timeMember ) {
00195                         time_t t = this->*(b->timeMember);
00196                         if( t > 0 )
00197                                 os << "      " << b->name << ": " << ctime(&t);
00198                 }
00199         }
00200 
00201         // print any unknowns
00202         os << Unknowns;
00203         os << "   ------------------- End of Config Field\n";
00204 }
00205 
00206 
00207 ///////////////////////////////////////////////////////////////////////////////
00208 // ServiceBook class
00209 
00210 // service book field codes
00211 #define SBFC_OLD_NAME                   0x01
00212 #define SBFC_HIDDEN_NAME                0x02
00213 #define SBFC_NAME                       0x03
00214 #define SBFC_OLD_UNIQUE_ID              0x06
00215 #define SBFC_UNIQUE_ID                  0x07
00216 #define SBFC_CONTENT_ID                 0x08
00217 #define SBFC_CONFIG                     0x09
00218 #define SBFC_OLD_DESC                   0x32
00219 #define SBFC_DESCRIPTION                0x0f
00220 #define SBFC_DSID                       0xa1
00221 #define SBFC_BES_DOMAIN                 0xa2
00222 #define SBFC_USER_ID                    0xa3
00223 #define SBFC_END                        0xffff
00224 
00225 FieldLink<ServiceBook> ServiceBookFieldLinks[] = {
00226    { SBFC_HIDDEN_NAME, "Hidden Name",0, 0,    &ServiceBook::HiddenName, 0, 0 },
00227    { SBFC_DSID,        "DSID",       0, 0,    &ServiceBook::DSID, 0, 0 },
00228    { SBFC_END,         "End of List",0, 0,    0, 0, 0 }
00229 };
00230 
00231 ServiceBook::ServiceBook()
00232         : NameType(SBFC_OLD_NAME),
00233         DescType(SBFC_OLD_DESC),
00234         UniqueIdType(SBFC_OLD_UNIQUE_ID),
00235         RecordId(0)
00236 {
00237         Clear();
00238 }
00239 
00240 ServiceBook::~ServiceBook()
00241 {
00242 }
00243 
00244 const unsigned char* ServiceBook::ParseField(const unsigned char *begin,
00245                                           const unsigned char *end)
00246 {
00247         const CommonField *field = (const CommonField *) begin;
00248 
00249         // advance and check size
00250         begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
00251         if( begin > end )               // if begin==end, we are ok
00252                 return begin;
00253 
00254         if( !btohs(field->size) )       // if field has no size, something's up
00255                 return begin;
00256 
00257         // cycle through the type table
00258         for(    FieldLink<ServiceBook> *b = ServiceBookFieldLinks;
00259                 b->type != SBFC_END;
00260                 b++ )
00261         {
00262                 if( b->type == field->type ) {
00263                         if( b->strMember ) {
00264                                 std::string &s = this->*(b->strMember);
00265                                 s = ParseFieldString(field);
00266                                 return begin;   // done!
00267                         }
00268                         else if( b->timeMember && btohs(field->size) == 4 ) {
00269                                 time_t &t = this->*(b->timeMember);
00270                                 t = min2time(field->u.min1900);
00271                                 return begin;
00272                         }
00273                 }
00274         }
00275 
00276         // handle special cases
00277         switch( field->type )
00278         {
00279         case SBFC_OLD_NAME:             // strings with old/new type codes
00280         case SBFC_NAME:
00281                 Name = ParseFieldString(field);
00282                 NameType = field->type;
00283                 return begin;
00284 
00285         case SBFC_OLD_DESC:
00286         case SBFC_DESCRIPTION:
00287                 Description = ParseFieldString(field);
00288                 DescType = field->type;
00289                 return begin;
00290 
00291         case SBFC_OLD_UNIQUE_ID:
00292         case SBFC_UNIQUE_ID:
00293                 UniqueId = ParseFieldString(field);
00294                 UniqueIdType = field->type;
00295                 return begin;
00296 
00297         case SBFC_CONTENT_ID:
00298                 ContentId = ParseFieldString(field);
00299                 return begin;
00300 
00301         case SBFC_BES_DOMAIN:
00302                 BesDomain = ParseFieldString(field);
00303                 return begin;
00304 
00305         case SBFC_CONFIG:
00306                 {
00307                         Data config((const void *)field->u.raw, btohs(field->size));
00308                         size_t offset = 0;
00309                         Config.ParseHeader(config, offset);
00310                         Config.ParseFields(config, offset);
00311                 }
00312                 break;  // break here so raw packet is still visible in dump
00313 //              return begin;
00314         }
00315 
00316         // if still not handled, add to the Unknowns list
00317         UnknownField uf;
00318         uf.type = field->type;
00319         uf.data.assign((const char*)field->u.raw, btohs(field->size));
00320         Unknowns.push_back(uf);
00321 
00322         // return new pointer for next field
00323         return begin;
00324 }
00325 
00326 void ServiceBook::ParseHeader(const Data &data, size_t &offset)
00327 {
00328         // no header in this record (?)
00329 }
00330 
00331 void ServiceBook::ParseFields(const Data &data, size_t &offset)
00332 {
00333         const unsigned char *finish = ParseCommonFields(*this,
00334                 data.GetData() + offset, data.GetData() + data.GetSize());
00335         offset += finish - (data.GetData() + offset);
00336 }
00337 
00338 void ServiceBook::BuildHeader(Data &data, size_t &offset) const
00339 {
00340         // no header in this record (?)
00341 }
00342 
00343 //
00344 // BuildFields
00345 //
00346 /// Build fields part of record
00347 ///
00348 void ServiceBook::BuildFields(Data &data, size_t &offset) const
00349 {
00350         throw std::logic_error("ServiceBook::BuildFields not yet implemented");
00351 }
00352 
00353 void ServiceBook::Clear()
00354 {
00355         Unknowns.clear();
00356         Config.Clear();
00357 }
00358 
00359 void ServiceBook::Dump(std::ostream &os) const
00360 {
00361         os << "ServiceBook entry: 0x" << setbase(16) << RecordId
00362                 << " (" << (unsigned int)RecType << ")\n";
00363 
00364         // cycle through the type table
00365         for(    const FieldLink<ServiceBook> *b = ServiceBookFieldLinks;
00366                 b->type != SBFC_END;
00367                 b++ )
00368         {
00369                 if( b->strMember ) {
00370                         const std::string &s = this->*(b->strMember);
00371                         if( s.size() )
00372                                 os << "   " << b->name << ": " << s << "\n";
00373                 }
00374                 else if( b->timeMember ) {
00375                         time_t t = this->*(b->timeMember);
00376                         if( t > 0 )
00377                                 os << "   " << b->name << ": " << ctime(&t);
00378                 }
00379         }
00380 
00381         // special cases
00382         if( UniqueId.size() )
00383                 os << "   Unique ID: " << UniqueId << "\n";
00384         if( ContentId.size() )
00385                 os << "   Content ID: " << ContentId << "\n";
00386         if( BesDomain.size() )
00387                 os << "   (BES) Domain: " << BesDomain << "\n";
00388 
00389         os << Config;
00390 
00391         // print any unknowns
00392         os << Unknowns;
00393 }
00394 
00395 } // namespace Barry
00396 

Generated on Wed Sep 24 21:27:32 2008 for Barry by  doxygen 1.5.1