00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "record.h"
00025 #include "record-internal.h"
00026 #include "protostructs.h"
00027 #include "data.h"
00028 #include "time.h"
00029 #include "error.h"
00030 #include "endian.h"
00031 #include "trim.h"
00032 #include "ios_state.h"
00033 #include "parser.h"
00034 #include <sstream>
00035 #include <iomanip>
00036 #include <time.h>
00037 #include <string.h>
00038 #include <stdio.h>
00039 #include <stdexcept>
00040
00041
00042 #include "recordtmpl.h"
00043 #include "r_calendar.h"
00044 #include "r_calllog.h"
00045 #include "r_bookmark.h"
00046 #include "r_contact.h"
00047 #include "r_cstore.h"
00048 #include "r_memo.h"
00049 #include "r_message.h"
00050 #include "r_servicebook.h"
00051 #include "r_task.h"
00052 #include "r_pin_message.h"
00053 #include "r_saved_message.h"
00054 #include "r_sms.h"
00055 #include "r_folder.h"
00056 #include "r_timezone.h"
00057 #include "r_hhagent.h"
00058
00059 #define __DEBUG_MODE__
00060 #include "debug.h"
00061
00062 using namespace std;
00063 using namespace Barry::Protocol;
00064
00065 namespace Barry {
00066
00067 std::ostream& operator<< (std::ostream &os, const Cr2LfWrapper &str)
00068 {
00069 for( std::string::const_iterator i = str.m_str.begin();
00070 i != str.m_str.end() && *i;
00071 i++)
00072 {
00073 if( *i == '\r' )
00074 os << '\n';
00075 else
00076 os << *i;
00077 }
00078 return os;
00079 }
00080
00081 std::ostream& operator<< (std::ostream &os, const TimeT &t)
00082 {
00083
00084 string output = ctime(&t.Time);
00085 while( output.size() &&
00086 (output[output.size()-1] == '\n' ||
00087 output[output.size()-1] == '\r') )
00088 {
00089 output.resize(output.size() - 1);
00090 }
00091
00092 os << output;
00093 return os;
00094 }
00095
00096
00097
00098
00099 void BuildField1900(Data &data, size_t &size, uint8_t type, time_t t)
00100 {
00101 size_t timesize = COMMON_FIELD_MIN1900_SIZE;
00102 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + timesize;
00103 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00104 CommonField *field = (CommonField *) pd;
00105
00106 field->size = htobs(timesize);
00107 field->type = type;
00108 field->u.min1900 = time2min(t);
00109
00110 size += fieldsize;
00111 }
00112
00113 void BuildField(Data &data, size_t &size, uint8_t type, char c)
00114 {
00115 BuildField(data, size, type, (uint8_t)c);
00116 }
00117
00118 void BuildField(Data &data, size_t &size, uint8_t type, uint8_t c)
00119 {
00120 size_t strsize = 1;
00121 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + strsize;
00122 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00123 CommonField *field = (CommonField *) pd;
00124
00125 field->size = htobs(strsize);
00126 field->type = type;
00127 memcpy(field->u.raw, &c, strsize);
00128
00129 size += fieldsize;
00130 }
00131
00132 void BuildField(Data &data, size_t &size, uint8_t type, uint16_t value)
00133 {
00134 size_t strsize = 2;
00135 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + strsize;
00136 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00137 CommonField *field = (CommonField *) pd;
00138
00139 field->size = htobs(strsize);
00140 field->type = type;
00141
00142 uint16_t store = htobs(value);
00143 memcpy(field->u.raw, &store, strsize);
00144
00145 size += fieldsize;
00146 }
00147
00148 void BuildField(Data &data, size_t &size, uint8_t type, uint32_t value)
00149 {
00150 size_t strsize = 4;
00151 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + strsize;
00152 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00153 CommonField *field = (CommonField *) pd;
00154
00155 field->size = htobl(strsize);
00156 field->type = type;
00157
00158 uint32_t store = htobl(value);
00159 memcpy(field->u.raw, &store, strsize);
00160
00161 size += fieldsize;
00162 }
00163
00164 void BuildField(Data &data, size_t &size, uint8_t type, uint64_t value)
00165 {
00166 size_t strsize = 8;
00167 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + strsize;
00168 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00169 CommonField *field = (CommonField *) pd;
00170
00171 field->size = htobl(strsize);
00172 field->type = type;
00173
00174 uint64_t store = htobll(value);
00175 memcpy(field->u.raw, &store, strsize);
00176
00177 size += fieldsize;
00178 }
00179
00180 void BuildField(Data &data, size_t &size, uint8_t type, const std::string &str)
00181 {
00182
00183 BuildField(data, size, type, str.c_str(), str.size() + 1);
00184 }
00185
00186 void BuildField(Data &data, size_t &size, uint8_t type,
00187 const void *buf, size_t bufsize)
00188 {
00189
00190 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + bufsize;
00191 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00192 CommonField *field = (CommonField *) pd;
00193
00194 field->size = htobs(bufsize);
00195 field->type = type;
00196 memcpy(field->u.raw, buf, bufsize);
00197
00198 size += fieldsize;
00199 }
00200
00201 void BuildField(Data &data, size_t &size, const Barry::UnknownField &field)
00202 {
00203 BuildField(data, size, field.type,
00204 field.data.raw_data.data(), field.data.raw_data.size());
00205 }
00206
00207 void BuildField(Data &data, size_t &size, uint8_t type, const Barry::Protocol::GroupLink &link)
00208 {
00209 size_t linksize = sizeof(Barry::Protocol::GroupLink);
00210 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + linksize;
00211 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00212 CommonField *field = (CommonField *) pd;
00213
00214 field->size = htobs(linksize);
00215 field->type = type;
00216 field->u.link = link;
00217
00218 size += fieldsize;
00219 }
00220
00221 std::string ParseFieldString(const Barry::Protocol::CommonField *field)
00222 {
00223
00224
00225
00226 return ParseFieldString(field->u.raw, btohs(field->size));
00227 }
00228
00229 std::string ParseFieldString(const void *data, uint16_t maxlen)
00230 {
00231 const char *str = (const char *)data;
00232
00233
00234
00235 while( maxlen && str[maxlen-1] == 0 )
00236 maxlen--;
00237
00238 return std::string(str, maxlen);
00239 }
00240
00241
00242
00243
00244
00245 std::ostream& operator<< (std::ostream &os, const std::vector<UnknownField> &unknowns)
00246 {
00247 ios_format_state state(os);
00248
00249 std::vector<UnknownField>::const_iterator
00250 ub = unknowns.begin(), ue = unknowns.end();
00251 if( ub != ue )
00252 os << " Unknowns:\n";
00253 for( ; ub != ue; ub++ ) {
00254 os << " Type: 0x" << setbase(16)
00255 << (unsigned int) ub->type
00256 << " Data:\n" << Data(ub->data.data(), ub->data.size());
00257 }
00258 return os;
00259 }
00260
00261
00262
00263
00264
00265 std::ostream& operator<< (std::ostream &os, const EmailList &list)
00266 {
00267 for( EmailList::const_iterator b = list.begin(), e = list.end();
00268 b != e;
00269 ++b )
00270 {
00271 if( b != list.begin() )
00272 os << ", ";
00273 os << *b;
00274 }
00275 return os;
00276 }
00277
00278
00279
00280
00281 EmailAddress::EmailAddress(const std::string &complex_address)
00282 {
00283 size_t end = complex_address.rfind('>');
00284 size_t start = complex_address.rfind('<');
00285 if( start == string::npos || end == string::npos || start > end ) {
00286
00287 Email = complex_address;
00288 Inplace::trim(Email);
00289 }
00290 else {
00291 Name = complex_address.substr(0, start);
00292 Inplace::trim(Name);
00293
00294 Email = complex_address.substr(start+1, end - start - 1);
00295 Inplace::trim(Email);
00296 }
00297 }
00298
00299 std::ostream& operator<<(std::ostream &os, const EmailAddress &msga)
00300 {
00301 if( msga.Name.size() )
00302 os << msga.Name << " <";
00303 os << msga.Email;
00304 if( msga.Name.size() )
00305 os << ">";
00306 return os;
00307 }
00308
00309
00310
00311
00312
00313 std::string EmailAddressList::ToCommaSeparated() const
00314 {
00315 std::ostringstream oss;
00316 oss << *this;
00317 return oss.str();
00318 }
00319
00320
00321
00322 void EmailAddressList::AddCommaSeparated(const std::string &list)
00323 {
00324 istringstream iss(list);
00325 string address;
00326 iss >> ws;
00327
00328 while( getline(iss, address, ',') ) {
00329
00330 size_t len = address.size();
00331 while( len && ::isspace(address[len-1]) )
00332 address.resize(len-1);
00333
00334
00335 if( address.size() ) {
00336 EmailAddress ea(address);
00337 push_back(ea);
00338 }
00339 }
00340 }
00341
00342 std::ostream& operator<<(std::ostream &os, const EmailAddressList &elist)
00343 {
00344 for( EmailAddressList::const_iterator i = elist.begin(); i != elist.end(); ++i ) {
00345 if( i != elist.begin() )
00346 os << ", ";
00347 os << *i;
00348 }
00349 return os;
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361 std::string PostalAddress::GetLabel() const
00362 {
00363 std::string address = Address1;
00364 if( Address2.size() ) {
00365 if( address.size() )
00366 address += "\n";
00367 address += Address2;
00368 }
00369 if( Address3.size() ) {
00370 if( address.size() )
00371 address += "\n";
00372 address += Address3;
00373 }
00374 if( address.size() )
00375 address += "\n";
00376 if( City.size() )
00377 address += City + " ";
00378 if( Province.size() )
00379 address += Province + " ";
00380 if( Country.size() )
00381 address += Country;
00382 if( address.size() )
00383 address += "\n";
00384 if( PostalCode.size() )
00385 address += PostalCode;
00386
00387 return address;
00388 }
00389
00390 void PostalAddress::Clear()
00391 {
00392 Address1.clear();
00393 Address2.clear();
00394 Address3.clear();
00395 City.clear();
00396 Province.clear();
00397 PostalCode.clear();
00398 Country.clear();
00399 }
00400
00401 std::ostream& operator<<(std::ostream &os, const PostalAddress &post) {
00402 os << post.GetLabel();
00403 return os;
00404 }
00405
00406
00407
00408
00409
00410
00411 Date::Date(const struct tm *timep)
00412 {
00413 FromTm(timep);
00414 }
00415
00416 void Date::Clear()
00417 {
00418 Month = Day = Year = 0;
00419 }
00420
00421 void Date::ToTm(struct tm *timep) const
00422 {
00423 memset(timep, 0, sizeof(tm));
00424 timep->tm_year = Year - 1900;
00425 timep->tm_mon = Month;
00426 timep->tm_mday = Day;
00427 }
00428
00429 std::string Date::ToYYYYMMDD() const
00430 {
00431 std::ostringstream oss;
00432
00433 oss << setw(4) << setfill('0') << dec << Year
00434 << setw(2) << setfill('0') << dec << (Month + 1)
00435 << setw(2) << setfill('0') << dec << Day;
00436 return oss.str();
00437 }
00438
00439
00440
00441
00442
00443
00444
00445 std::string Date::ToBBString() const
00446 {
00447 std::ostringstream oss;
00448
00449 oss << setw(2) << setfill('0') << dec << Day << '/'
00450 << setw(2) << setfill('0') << dec << (Month + 1) << '/'
00451 << setw(2) << setfill('0') << dec << Year;
00452 return oss.str();
00453 }
00454
00455 bool Date::FromTm(const struct tm *timep)
00456 {
00457 if( !timep )
00458 throw std::logic_error("NULL time pointer passed to Date::FromTm");
00459
00460 Year = timep->tm_year + 1900;
00461 Month = timep->tm_mon;
00462 Day = timep->tm_mday;
00463 return true;
00464 }
00465
00466 bool Date::FromBBString(const std::string &str)
00467 {
00468 int m, d, y;
00469 if( 3 == sscanf(str.c_str(), "%d/%d/%d", &d, &m, &y) ) {
00470 Year = y;
00471 Month = m - 1;
00472 Day = d;
00473 return true;
00474 }
00475 return false;
00476 }
00477
00478 bool Date::FromYYYYMMDD(const std::string &str)
00479 {
00480 int m, d, y;
00481 if( 3 == sscanf(str.c_str(), "%4d%2d%2d", &y, &m, &d) ) {
00482 Year = y;
00483 Month = m - 1;
00484 Day = d;
00485 return true;
00486 }
00487 return false;
00488 }
00489
00490 std::ostream& operator<<(std::ostream &os, const Date &date)
00491 {
00492 ios_format_state state(os);
00493
00494 os.setf(ios::right);
00495 os.fill('0');
00496
00497 os << setw(4) << dec << date.Year << '/'
00498 << setw(2) << dec << (date.Month + 1) << '/'
00499 << setw(2) << dec << date.Day;
00500
00501 return os;
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511 void CategoryList::CategoryStr2List(const std::string &str)
00512 {
00513
00514 clear();
00515
00516 if( !str.size() )
00517 return;
00518
00519
00520
00521 string::size_type start = 0, end = 0, delim = str.find(',', start);
00522 while( start != string::npos ) {
00523 if( delim == string::npos )
00524 end = str.size() - 1;
00525 else
00526 end = delim - 1;
00527
00528
00529 while( str[start] == ' ' )
00530 start++;
00531 while( end && str[end] == ' ' )
00532 end--;
00533
00534 if( start <= end ) {
00535 string token = str.substr(start, end-start+1);
00536 push_back(token);
00537 }
00538
00539
00540 start = delim;
00541 if( start != string::npos )
00542 start++;
00543 delim = str.find(',', start);
00544 }
00545 }
00546
00547
00548
00549 void CategoryList::CategoryList2Str(std::string &str) const
00550 {
00551 str.clear();
00552
00553 Barry::CategoryList::const_iterator i = begin();
00554 for( ; i != end(); ++i ) {
00555 if( str.size() )
00556 str += ", ";
00557 str += *i;
00558 }
00559 }
00560
00561 std::ostream& operator<<(std::ostream &os, const CategoryList &cl)
00562 {
00563 string buf;
00564 cl.CategoryList2Str(buf);
00565 os << buf;
00566 return os;
00567 }
00568
00569
00570
00571
00572 void EnumConstants::AddConstant(const char *name,
00573 const std::string &display,
00574 int val)
00575 {
00576 m_constants.push_back(EnumConstant(name, display, val));
00577 }
00578
00579 const EnumConstants::EnumConstant& EnumConstants::GetConstant(int value) const
00580 {
00581 for( EnumConstantList::const_iterator b = m_constants.begin(), e = m_constants.end();
00582 b != e;
00583 ++b )
00584 {
00585 if( b->Value == value )
00586 return *b;
00587 }
00588
00589
00590 throw std::logic_error("Enum value not found in constant list");
00591 }
00592
00593 const char* EnumConstants::GetName(int value) const
00594 {
00595 return GetConstant(value).Name;
00596 }
00597
00598 const std::string& EnumConstants::GetDisplayName(int value) const
00599 {
00600 return GetConstant(value).DisplayName;
00601 }
00602
00603 bool EnumConstants::IsConstantValid(int value) const
00604 {
00605 for( EnumConstantList::const_iterator b = m_constants.begin(), e = m_constants.end();
00606 b != e;
00607 ++b )
00608 {
00609 if( b->Value == value )
00610 return true;
00611 }
00612
00613
00614 return false;
00615 }
00616
00617
00618
00619
00620
00621 DBNamedFieldCmp::DBNamedFieldCmp(const std::string &field_name,
00622 const Barry::IConverter *ic)
00623 : m_name(field_name)
00624 , m_ic(ic)
00625 {
00626 }
00627
00628 bool DBNamedFieldCmp::operator() (const Barry::DBData &a,
00629 const Barry::DBData &b) const
00630 {
00631 #undef HANDLE_PARSER
00632 #define HANDLE_PARSER(tname) \
00633 else if( tname::GetDBName() == a.GetDBName() ) { \
00634 tname rec1, rec2; \
00635 ParseDBData(a, rec1, m_ic); \
00636 ParseDBData(b, rec2, m_ic); \
00637 return NamedFieldCmp<tname>(m_name).operator()(rec1, rec2); \
00638 }
00639
00640 if( a.GetDBName() != b.GetDBName() ) {
00641 throw logic_error("Different database types in DBNamedFieldCmp");
00642 }
00643
00644 ALL_KNOWN_PARSER_TYPES
00645
00646 throw logic_error("Unknown database in DBNamedFieldCmp::operator()");
00647 }
00648
00649 }
00650
00651
00652 #ifdef __TEST_MODE__
00653
00654 #include <iostream>
00655
00656 int main(int argc, char *argv[])
00657 {
00658 if( argc < 2 ) {
00659 cerr << "Usage: test <datafile>" << endl;
00660 return 1;
00661 }
00662
00663 std::vector<Data> array;
00664 if( !LoadDataArray(argv[1], array) ) {
00665 cerr << "Unable to load file: " << argv[1] << endl;
00666 return 1;
00667 }
00668
00669 cout << "Loaded " << array.size() << " items" << endl;
00670
00671 for( std::vector<Data>::iterator b = array.begin(), e = array.end();
00672 b != e; b++ )
00673 {
00674 Data &d = *b;
00675
00676 if( d.GetSize() > 13 && d.GetData()[6] == 0x4f ) {
00677 Barry::Contact contact;
00678 size_t size = 13;
00679 contact.ParseFields(d, size);
00680 cout << contact << endl;
00681 contact.DumpLdif(cout, "ou=People,dc=example,dc=com");
00682 }
00683 else if( d.GetSize() > 13 && d.GetData()[6] == 0x44 ) {
00684 Barry::Calendar cal;
00685 size_t size = 13;
00686 cal.ParseFields(d, size);
00687 cout << cal << endl;
00688 }
00689 }
00690 }
00691
00692 #endif
00693