From d9775e7c2a2f9e665b37be35863c7ab2551ee339 Mon Sep 17 00:00:00 2001 From: cdfrey Date: Sat, 1 Mar 2008 20:05:18 +0000 Subject: [PATCH] - applied Time Zone parsing patches from Brian Edginton --- ChangeLog | 4 +- src/Makefile.am | 2 + src/protostructs.h | 1 + src/r_timezone.cc | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/r_timezone.h | 87 ++++++++++++++++++++++ src/record.h | 1 + src/s11n-boost.h | 18 +++++ tools/btool.cc | 5 ++ 8 files changed, 332 insertions(+), 1 deletion(-) create mode 100644 src/r_timezone.cc create mode 100644 src/r_timezone.h diff --git a/ChangeLog b/ChangeLog index 39d0c233..1850cbe0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ -Release: version 0.12 - 2008/02/?? +Release: version 0.12 - 2008/03/?? ------------------------------------------------------------------------------ +2008/03/01 + - applied Time Zone parsing patches from Brian Edginton 2008/02/29 - changed configure.ac to use bzip2 for "make dist".. thanks to Paul Dugas for the tip diff --git a/src/Makefile.am b/src/Makefile.am index 5db40490..3761cdc0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -71,6 +71,7 @@ include_barry_HEADERS = barry.h \ r_saved_message.h \ r_servicebook.h \ r_task.h \ + r_timezone.h \ socket.h \ time.h \ usbwrap.h \ @@ -99,6 +100,7 @@ libbarry_la_SOURCES = time.cc \ r_saved_message.cc \ r_servicebook.cc \ r_task.cc \ + r_timezone.cc \ packet.cc packet.h \ controller.cc \ version.cc \ diff --git a/src/protostructs.h b/src/protostructs.h index bed92c4d..2741cefc 100644 --- a/src/protostructs.h +++ b/src/protostructs.h @@ -82,6 +82,7 @@ struct CommonField int32_t min1900; uint16_t code; uint8_t raw[1]; + int16_t int16; } __attribute__ ((packed)) u; diff --git a/src/r_timezone.cc b/src/r_timezone.cc new file mode 100644 index 00000000..8a4c377c --- /dev/null +++ b/src/r_timezone.cc @@ -0,0 +1,215 @@ +/// +/// \file r_timezone.cc +/// Record parsing class for the timezone database. +/// + +/* + Copyright (C) 2005-2008, Net Direct Inc. (http://www.netdirect.ca/) + Copyright (C) 2008, Brian Edginton + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License in the COPYING file at the + root directory of this project for more details. +*/ + +#include "r_timezone.h" +#include "record-internal.h" +#include "protostructs.h" +#include "data.h" +#include "time.h" +#include "debug.h" +#include +#include + +using namespace std; +using namespace Barry::Protocol; + +namespace Barry +{ + +/////////////////////////////////////////////////////////////////////////////// +// Timezone Class + +// Timezone Field Codes +#define TZFC_INDEX 0x01 +#define TZFC_NAME 0x02 +#define TZFC_OFFSET 0x03 +#define TZFC_DST 0x04 +#define TZFC_STARTMONTH 0x06 +#define TZFC_ENDMONTH 0x0B +#define TZFC_TZTYPE 0x64 + +#define TZFC_END 0xffff + +FieldLink TimezoneFieldLinks[] = { + { TZFC_NAME, "Name", 0, 0, &Timezone::TimeZoneName, 0, 0 }, + { TZFC_END, "End of List", 0, 0, 0, 0, 0 }, +}; + +Timezone::Timezone() +{ + Clear(); +} + +Timezone::~Timezone() +{ +} + +const unsigned char* Timezone::ParseField(const unsigned char *begin, + const unsigned char *end) +{ + const CommonField *field = (const CommonField *) begin; + + // advance and check size + begin += COMMON_FIELD_HEADER_SIZE + btohs(field->size); + if( begin > end ) // if begin==end, we are ok + return begin; + + if( !btohs(field->size) ) // if field has no size, something's up + return begin; + + if( field->type == TZFC_TZTYPE ) { + if( ( TZType = field->u.uint32 ) != 1 ) { + throw Error("Timezone::ParseField: Timezone Type is not valid"); + } + return begin; + } + + // cycle through the type table + for( FieldLink *b = TimezoneFieldLinks; + b->type != TZFC_END; + b++ ) + { + if( b->type == field->type ) { + if( b->strMember ) { + std::string &s = this->*(b->strMember); + s = ParseFieldString(field); + return begin; // done! + } + } + } + + switch( field->type ) + { + case TZFC_INDEX: + Index = btohl(field->u.uint32); + return begin; + + case TZFC_OFFSET: + Offset = btohs(field->u.int16); + if (Offset < 0) { + Offset =~ Offset; + Offset++; + OffsetFraction = Offset % 60; + Offset = Offset / 60; + Left = true; + } else { + OffsetFraction = Offset % 60; + Offset = Offset / 60; + Left = false; + } + return begin; + + case TZFC_DST: + DSTOffset = btohl(field->u.uint32); + if (DSTOffset) { + UseDST = true; + } + return begin; + + case TZFC_STARTMONTH: + StartMonth = btohl(field->u.uint32); + return begin; + + case TZFC_ENDMONTH: + EndMonth = btohl(field->u.uint32); + return begin; + } + + // if still not handled, add to the Unknowns list + UnknownField uf; + uf.type = field->type; + uf.data.assign((const char*)field->u.raw, btohs(field->size)); + Unknowns.push_back(uf); + + // return new pointer for next field + return begin; +} + +void Timezone::ParseHeader(const Data &data, size_t &offset) +{ + // no header in Task records +} + +void Timezone::ParseFields(const Data &data, size_t &offset) +{ + const unsigned char *finish = ParseCommonFields(*this, + data.GetData() + offset, data.GetData() + data.GetSize()); + offset += finish - (data.GetData() + offset); +} + +void Timezone::Clear() +{ + TimeZoneName.clear(); + + Index = 0; + Left = false; + UseDST = false; + Offset = 0; + OffsetFraction = 0; + DSTOffset = 0; + StartMonth = -1; + EndMonth = -1; + + Unknowns.clear(); +} + +void Timezone::Dump(std::ostream &os) const +{ + static const char *month[] = { + "Jan", "Feb", "Mar", "Apr", "May", + "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + + os << "Task entry: 0x" << setbase(16) << RecordId + << " (" << (unsigned int)RecType << ")\n"; + + // cycle through the type table + for( const FieldLink *b = TimezoneFieldLinks; + b->type != TZFC_END; + b++ ) + { + if( b->strMember ) { + const std::string &s = this->*(b->strMember); + if( s.size() ) + os << " " << b->name << ": " << s << "\n"; + } + } + + os << " Index: 0x" < 0) && (StartMonth < 11)) + os << "Start Month: " << month[StartMonth] << "\n"; + else + os << "Start Month: unknown (" << setbase(10) << StartMonth << ")\n"; + if ((EndMonth > 0) && (EndMonth < 11)) + os << " End Month: " << month[EndMonth] << "\n"; + else + os << " End Month: unknown (" << setbase(10) << EndMonth << ")\n"; + } + + os << Unknowns; + os << "\n\n"; +} + +} diff --git a/src/r_timezone.h b/src/r_timezone.h new file mode 100644 index 00000000..1190af79 --- /dev/null +++ b/src/r_timezone.h @@ -0,0 +1,87 @@ +/// +/// \file r_timezone.h +/// Record parsing class for the timezone database. +/// + +/* + Copyright (C) 2005-2008, Net Direct Inc. (http://www.netdirect.ca/) + Copyright (C) 2008, Brian Edginton + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License in the COPYING file at the + root directory of this project for more details. +*/ + +#ifndef __BARRY_RECORD_TIMEZONE_H__ +#define __BARRY_RECORD_TIMEZONE_H__ + +#include "record.h" +#include +#include +#include + +namespace Barry +{ + +class Timezone +{ +public: + typedef std::vector UnknownsType; + uint8_t RecType; + uint32_t RecordId; + + uint8_t TZType; + uint32_t DSTOffset; + int32_t Index; + int32_t Offset; + int32_t OffsetFraction; + uint32_t StartMonth; + uint32_t EndMonth; + bool Left; + bool UseDST; + + + std::string TimeZoneName; + UnknownsType Unknowns; + +public: + + Timezone(); + virtual ~Timezone(); + + const unsigned char* ParseField(const unsigned char *begin, + const unsigned char *end); + void ParseRecurrenceData(const void *data); + void BuildRecurrenceData(void *data); + uint8_t GetRecType() const { return RecType; } + uint32_t GetUniqueId() const { return RecordId; } + void SetIds(uint8_t Type, uint32_t Id) { RecType = Type; RecordId = Id; } + void ParseHeader(const Data &data, size_t &offset); + void ParseFields(const Data &data, size_t &offset); + void BuildHeader(Data &data, size_t &offset) const; + + void Clear(); + + void Dump(std::ostream &os) const; + bool operator<(const Timezone &other) const { return TimeZoneName < other.TimeZoneName; } + + // database name + static const char * GetDBName() { return "Time Zones"; } + static uint8_t GetDefaultRecType() { return 2; } +}; + +inline std::ostream& operator<<(std::ostream &os, const Timezone &msg) { + msg.Dump(os); + return os; +} +} // namespace Barry + +#endif /* __BARRY_RECORD_TIMEZONE_H__*/ diff --git a/src/record.h b/src/record.h index e8b0722b..cb28bb1b 100644 --- a/src/record.h +++ b/src/record.h @@ -232,6 +232,7 @@ std::ostream& operator<<(std::ostream &os, const PostalAddress &msga); #include "r_pin_message.h" #include "r_saved_message.h" #include "r_folder.h" +#include "r_timezone.h" #endif diff --git a/src/s11n-boost.h b/src/s11n-boost.h index e7e0f110..527a993c 100644 --- a/src/s11n-boost.h +++ b/src/s11n-boost.h @@ -261,6 +261,24 @@ void serialize(ArchiveT &ar, Barry::Folder &f, const unsigned int ver) } } +template +void serialize(ArchiveT &ar, Barry::Timezone &t, const unsigned int ver) +{ + ar & make_nvp("Index", t.Index); + ar & make_nvp("TimeZoneName", t.TimeZoneName); + ar & make_nvp("Offset", t.Offset); + ar & make_nvp("OffsetFraction", t.OffsetFraction); + ar & make_nvp("Left", t.Left); + ar & make_nvp("UseDST", t.UseDST); + ar & make_nvp("DSTOffset", t.DSTOffset); + ar & make_nvp("StartMonth", t.StartMonth); + ar & make_nvp("EndMonth", t.EndMonth); + + if( ver < BARRY_POD_MAP_VERSION) { + ar & make_nvp("Unknowns", t.Unknowns); + } +} + }} // namespace boost::serialization #endif diff --git a/tools/btool.cc b/tools/btool.cc index 134c8d05..dd52b14f 100644 --- a/tools/btool.cc +++ b/tools/btool.cc @@ -261,6 +261,11 @@ auto_ptr GetParser(const string &name, const string &filename) new RecordParser > ( new Store(filename, false))); } + else if( name == Timezone::GetDBName() ) { + return auto_ptr( + new RecordParser > ( + new Store(filename, false))); + } else { // unknown database, use null parser return auto_ptr( new DataDumpParser ); -- 2.11.4.GIT