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_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 "iconv.h"
00032 #include <ostream>
00033 #include <iomanip>
00034 #include <time.h>
00035 #include <stdexcept>
00036
00037 #define __DEBUG_MODE__
00038 #include "debug.h"
00039
00040 using namespace std;
00041 using namespace Barry::Protocol;
00042
00043 namespace Barry {
00044
00045
00046
00047
00048
00049 #define SBFCC_END 0xffff
00050
00051 static FieldLink<ServiceBookConfig> ServiceBookConfigFieldLinks[] = {
00052
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 const IConverter *ic)
00069 {
00070 const void *raw;
00071 uint16_t size, type;
00072
00073 switch( Format )
00074 {
00075 case 0x01:
00076 case 0x02:
00077 {
00078 const PackedField_02 *field = (const PackedField_02 *) begin;
00079 raw = field->raw;
00080 size = field->size;
00081 type = field->type;
00082 begin += PACKED_FIELD_02_HEADER_SIZE + size;
00083 }
00084 break;
00085
00086 case 0x10:
00087 {
00088 const PackedField_10 *field = (const PackedField_10 *) begin;
00089 raw = field->raw;
00090 size = field->size;
00091 type = field->type;
00092 begin += PACKED_FIELD_10_HEADER_SIZE + size;
00093 }
00094 break;
00095
00096 default:
00097 eout("------> Unknown packed field format: 0x" << std::hex <<
00098 (unsigned int) Format);
00099 throw BadPackedFormat(Format);
00100 return begin + 1;
00101 }
00102
00103
00104
00105 if( begin > end )
00106 return begin;
00107
00108 if( !size )
00109 return begin;
00110
00111
00112 for( FieldLink<ServiceBookConfig> *b = ServiceBookConfigFieldLinks;
00113 b->type != SBFCC_END;
00114 b++ )
00115 {
00116 if( b->type == type ) {
00117 if( b->strMember ) {
00118 std::string &s = this->*(b->strMember);
00119 s = ParseFieldString(raw, size-1);
00120 return begin;
00121 }
00122 }
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 UnknownField uf;
00134 uf.type = type;
00135 uf.data.assign((const char*)raw, size);
00136 Unknowns.push_back(uf);
00137
00138
00139 return begin;
00140 }
00141
00142 void ServiceBookConfig::ParseHeader(const Data &data, size_t &offset)
00143 {
00144 MAKE_RECORD(const Barry::Protocol::ServiceBookConfigField, sbc, data, offset);
00145 offset += SERVICE_BOOK_CONFIG_FIELD_HEADER_SIZE;
00146 if( data.GetSize() >= offset ) {
00147 Format = sbc->format;
00148 }
00149 }
00150
00151 void ServiceBookConfig::ParseFields(const Data &data, size_t &offset, const IConverter *ic)
00152 {
00153 const unsigned char *finish = ParseCommonFields(*this,
00154 data.GetData() + offset, data.GetData() + data.GetSize(), ic);
00155 offset += finish - (data.GetData() + offset);
00156 }
00157
00158 void ServiceBookConfig::BuildHeader(Data &data, size_t &offset) const
00159 {
00160
00161 data.GetBuffer(offset + SERVICE_BOOK_CONFIG_FIELD_HEADER_SIZE);
00162
00163 MAKE_RECORD(Barry::Protocol::ServiceBookConfigField, sbc, data, offset);
00164 sbc->format = Format;
00165
00166 offset += SERVICE_BOOK_CONFIG_FIELD_HEADER_SIZE;
00167 }
00168
00169
00170
00171
00172
00173
00174 void ServiceBookConfig::BuildFields(Data &data, size_t &offset, const IConverter *ic) const
00175 {
00176 throw std::logic_error("ServiceBookConfig::Build not yet implemented");
00177 }
00178
00179 void ServiceBookConfig::Clear()
00180 {
00181 Unknowns.clear();
00182 }
00183
00184 void ServiceBookConfig::Dump(std::ostream &os) const
00185 {
00186 os << " ServiceBookConfig Format: " << setbase(16) << (uint16_t)Format << "\n";
00187
00188
00189 for( const FieldLink<ServiceBookConfig> *b = ServiceBookConfigFieldLinks;
00190 b->type != SBFCC_END;
00191 b++ )
00192 {
00193 if( b->strMember ) {
00194 const std::string &s = this->*(b->strMember);
00195 if( s.size() )
00196 os << " " << b->name << ": " << s << "\n";
00197 }
00198 else if( b->timeMember ) {
00199 time_t t = this->*(b->timeMember);
00200 if( t > 0 )
00201 os << " " << b->name << ": " << ctime(&t);
00202 }
00203 }
00204
00205
00206 os << Unknowns;
00207 os << " ------------------- End of Config Field\n";
00208 }
00209
00210
00211
00212
00213
00214
00215 #define SBFC_OLD_NAME 0x01
00216 #define SBFC_HIDDEN_NAME 0x02
00217 #define SBFC_NAME 0x03
00218 #define SBFC_OLD_UNIQUE_ID 0x06
00219 #define SBFC_UNIQUE_ID 0x07
00220 #define SBFC_CONTENT_ID 0x08
00221 #define SBFC_CONFIG 0x09
00222 #define SBFC_OLD_DESC 0x32
00223 #define SBFC_DESCRIPTION 0x0f
00224 #define SBFC_DSID 0xa1
00225 #define SBFC_BES_DOMAIN 0xa2
00226 #define SBFC_USER_ID 0xa3
00227 #define SBFC_END 0xffff
00228
00229
00230 class ServiceBookData
00231 {
00232 public:
00233 FieldLink<ServiceBook> *m_typeSet;
00234 ServiceBookData(FieldLink<ServiceBook> *typeSet) : m_typeSet(typeSet) {}
00235 };
00236
00237
00238
00239
00240
00241 static FieldLink<ServiceBook> ServiceBookOldFieldLinks[] = {
00242 { SBFC_OLD_NAME, "Old Name", 0, 0, &ServiceBook::Name, 0, 0, 0, 0, true },
00243 { SBFC_OLD_DESC, "Old Desc", 0, 0, &ServiceBook::Description, 0, 0, 0, 0, true },
00244 { SBFC_OLD_UNIQUE_ID, "Old UniqueId", 0, 0, &ServiceBook::UniqueId, 0, 0, 0, 0, false },
00245 { SBFC_END, "End of List", 0, 0, 0, 0, 0, 0, 0, false }
00246 };
00247
00248 static FieldLink<ServiceBook> ServiceBookNewFieldLinks[] = {
00249 { SBFC_NAME, "Name", 0, 0, &ServiceBook::Name, 0, 0, 0, 0, true },
00250 { SBFC_DESCRIPTION, "Description", 0, 0, &ServiceBook::Description, 0, 0, 0, 0, true },
00251 { SBFC_UNIQUE_ID, "UniqueId", 0, 0, &ServiceBook::UniqueId, 0, 0, 0, 0, false },
00252 { SBFC_END, "End of List", 0, 0, 0, 0, 0, 0, 0, false }
00253 };
00254
00255
00256 static FieldLink<ServiceBook> ServiceBookFieldLinks[] = {
00257 { SBFC_HIDDEN_NAME, "Hidden Name",0, 0, &ServiceBook::HiddenName, 0, 0, 0, 0, true },
00258 { SBFC_DSID, "DSID", 0, 0, &ServiceBook::DSID, 0, 0, 0, 0, false },
00259 { SBFC_CONTENT_ID, "ContentId", 0, 0, &ServiceBook::ContentId, 0, 0, 0, 0, false },
00260 { SBFC_BES_DOMAIN, "BES Domain", 0, 0, &ServiceBook::BesDomain, 0, 0, 0, 0, false },
00261 { SBFC_END, "End of List",0, 0, 0, 0, 0, 0, 0, false }
00262 };
00263
00264
00265 static FieldLink<ServiceBook> *ServiceBookLinkTable[] = {
00266 ServiceBookOldFieldLinks,
00267 ServiceBookNewFieldLinks,
00268 0
00269 };
00270
00271 #define FIELDLINK_END 0xffff
00272
00273 template <class RecordT>
00274 FieldLink<RecordT>* ParseFieldByTable(RecordT *rec,
00275 const CommonField *field,
00276 const IConverter *ic,
00277 FieldLink<RecordT> *links)
00278 {
00279
00280 for( FieldLink<RecordT> *b = links; b->type != FIELDLINK_END; b++ ) {
00281 if( b->type == field->type ) {
00282 if( b->strMember ) {
00283 std::string &s = rec->*(b->strMember);
00284 if( s.size() ) {
00285 dout(RecordT::GetDBName() << ": field '" << b->name << "' already has data (" << s << "). Overwriting.");
00286 }
00287 s = ParseFieldString(field);
00288 if( b->iconvNeeded && ic )
00289 s = ic->FromBB(s);
00290 return links;
00291 }
00292 else if( b->timeMember && btohs(field->size) == 4 ) {
00293 time_t &t = rec->*(b->timeMember);
00294 t = min2time(field->u.min1900);
00295 return links;
00296 }
00297 }
00298 }
00299 return 0;
00300 }
00301
00302 template <class RecordT>
00303 FieldLink<RecordT>* ParseFieldByTable(RecordT *rec,
00304 const CommonField *field,
00305 const IConverter *ic,
00306 FieldLink<RecordT> **b)
00307 {
00308 for( ; *b; b++ ) {
00309 FieldLink<RecordT> *link =
00310 ParseFieldByTable<RecordT>(rec, field, ic, *b);
00311 if( link )
00312 return link;
00313 }
00314 return 0;
00315 }
00316
00317 ServiceBook::ServiceBook()
00318 : m_data( new ServiceBookData(ServiceBookOldFieldLinks) )
00319 , RecordId(0)
00320 {
00321 Clear();
00322 }
00323
00324 ServiceBook::~ServiceBook()
00325 {
00326 }
00327
00328 const unsigned char* ServiceBook::ParseField(const unsigned char *begin,
00329 const unsigned char *end,
00330 const IConverter *ic)
00331 {
00332 const CommonField *field = (const CommonField *) begin;
00333
00334
00335 begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size);
00336 if( begin > end )
00337 return begin;
00338
00339 if( !btohs(field->size) )
00340 return begin;
00341
00342
00343 FieldLink<ServiceBook> *typeSet =
00344 ParseFieldByTable(this, field, ic, ServiceBookLinkTable);
00345 if( typeSet ) {
00346 if( m_data->m_typeSet && m_data->m_typeSet != typeSet ) {
00347 dout("ServiceBook record has a mix of old and new field types.");
00348 }
00349 m_data->m_typeSet = typeSet;
00350 return begin;
00351 }
00352 else {
00353 if( ParseFieldByTable(this, field, ic, ServiceBookFieldLinks) )
00354 return begin;
00355 }
00356
00357
00358 switch( field->type )
00359 {
00360 case SBFC_CONFIG:
00361 try {
00362 Data config((const void *)field->u.raw, btohs(field->size));
00363 size_t offset = 0;
00364 Config.ParseHeader(config, offset);
00365 Config.ParseFields(config, offset);
00366 return begin;
00367 }
00368 catch( BadPackedFormat & ) {
00369
00370
00371 break;
00372 }
00373 }
00374
00375
00376 UnknownField uf;
00377 uf.type = field->type;
00378 uf.data.assign((const char*)field->u.raw, btohs(field->size));
00379 Unknowns.push_back(uf);
00380
00381
00382 return begin;
00383 }
00384
00385 void ServiceBook::ParseHeader(const Data &data, size_t &offset)
00386 {
00387
00388 }
00389
00390 void ServiceBook::ParseFields(const Data &data, size_t &offset, const IConverter *ic)
00391 {
00392 const unsigned char *finish = ParseCommonFields(*this,
00393 data.GetData() + offset, data.GetData() + data.GetSize(), ic);
00394 offset += finish - (data.GetData() + offset);
00395 }
00396
00397 void ServiceBook::BuildHeader(Data &data, size_t &offset) const
00398 {
00399
00400 }
00401
00402
00403
00404
00405
00406
00407 void ServiceBook::BuildFields(Data &data, size_t &offset, const IConverter *ic) const
00408 {
00409 throw std::logic_error("ServiceBook::BuildFields not yet implemented");
00410 }
00411
00412 void ServiceBook::Clear()
00413 {
00414 m_data->m_typeSet = ServiceBookOldFieldLinks;
00415 Unknowns.clear();
00416 Config.Clear();
00417 }
00418
00419 inline void FormatStr(std::ostream &os, const char *name, const std::string &str)
00420 {
00421 if( str.size() ) {
00422 os << " " << setw(20) << name;
00423 os << ": " << str << "\n";
00424 }
00425 }
00426
00427 void ServiceBook::Dump(std::ostream &os) const
00428 {
00429 ios::fmtflags oldflags = os.setf(ios::left);
00430 char fill = os.fill(' ');
00431
00432 os << "ServiceBook entry: 0x" << setbase(16) << RecordId
00433 << " (" << (unsigned int)RecType << ")\n";
00434
00435 FormatStr(os, "Name", Name);
00436 FormatStr(os, "Hidden Name", HiddenName);
00437 FormatStr(os, "Description", Description);
00438 FormatStr(os, "DSID", DSID);
00439 FormatStr(os, "Unique ID", UniqueId);
00440 FormatStr(os, "Content ID", ContentId);
00441 FormatStr(os, "(BES) Domain", BesDomain);
00442
00443 os << Config;
00444
00445
00446 os << Unknowns;
00447
00448
00449 os.flags(oldflags);
00450 os.fill(fill);
00451 }
00452
00453 }
00454