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 "protocol.h"
00027 #include "protostructs.h"
00028 #include "data.h"
00029 #include "time.h"
00030 #include "error.h"
00031 #include "endian.h"
00032 #include <sstream>
00033 #include <iomanip>
00034 #include <time.h>
00035 #include <string.h>
00036 #include <stdio.h>
00037 #include <stdexcept>
00038
00039 #define __DEBUG_MODE__
00040 #include "debug.h"
00041
00042 using namespace std;
00043 using namespace Barry::Protocol;
00044
00045 namespace Barry {
00046
00047 BXEXPORT std::ostream& operator<< (std::ostream &os, const Cr2LfWrapper &str)
00048 {
00049 for( std::string::const_iterator i = str.m_str.begin();
00050 i != str.m_str.end() && *i;
00051 i++)
00052 {
00053 if( *i == '\r' )
00054 os << '\n';
00055 else
00056 os << *i;
00057 }
00058 return os;
00059 }
00060
00061
00062
00063
00064 void BuildField1900(Data &data, size_t &size, uint8_t type, time_t t)
00065 {
00066 size_t timesize = COMMON_FIELD_MIN1900_SIZE;
00067 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + timesize;
00068 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00069 CommonField *field = (CommonField *) pd;
00070
00071 field->size = htobs(timesize);
00072 field->type = type;
00073 field->u.min1900 = time2min(t);
00074
00075 size += fieldsize;
00076 }
00077
00078 void BuildField(Data &data, size_t &size, uint8_t type, char c)
00079 {
00080 BuildField(data, size, type, (uint8_t)c);
00081 }
00082
00083 void BuildField(Data &data, size_t &size, uint8_t type, uint8_t c)
00084 {
00085 size_t strsize = 1;
00086 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + strsize;
00087 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00088 CommonField *field = (CommonField *) pd;
00089
00090 field->size = htobs(strsize);
00091 field->type = type;
00092 memcpy(field->u.raw, &c, strsize);
00093
00094 size += fieldsize;
00095 }
00096
00097 void BuildField(Data &data, size_t &size, uint8_t type, uint16_t value)
00098 {
00099 size_t strsize = 2;
00100 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + strsize;
00101 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00102 CommonField *field = (CommonField *) pd;
00103
00104 field->size = htobs(strsize);
00105 field->type = type;
00106
00107 uint16_t store = htobs(value);
00108 memcpy(field->u.raw, &store, strsize);
00109
00110 size += fieldsize;
00111 }
00112
00113 void BuildField(Data &data, size_t &size, uint8_t type, uint32_t value)
00114 {
00115 size_t strsize = 4;
00116 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + strsize;
00117 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00118 CommonField *field = (CommonField *) pd;
00119
00120 field->size = htobl(strsize);
00121 field->type = type;
00122
00123 uint32_t store = htobl(value);
00124 memcpy(field->u.raw, &store, strsize);
00125
00126 size += fieldsize;
00127 }
00128
00129 void BuildField(Data &data, size_t &size, uint8_t type, uint64_t value)
00130 {
00131 size_t strsize = 8;
00132 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + strsize;
00133 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00134 CommonField *field = (CommonField *) pd;
00135
00136 field->size = htobl(strsize);
00137 field->type = type;
00138
00139 uint64_t store = htobll(value);
00140 memcpy(field->u.raw, &store, strsize);
00141
00142 size += fieldsize;
00143 }
00144
00145 void BuildField(Data &data, size_t &size, uint8_t type, const std::string &str)
00146 {
00147
00148 BuildField(data, size, type, str.c_str(), str.size() + 1);
00149 }
00150
00151 void BuildField(Data &data, size_t &size, uint8_t type,
00152 const void *buf, size_t bufsize)
00153 {
00154
00155 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + bufsize;
00156 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00157 CommonField *field = (CommonField *) pd;
00158
00159 field->size = htobs(bufsize);
00160 field->type = type;
00161 memcpy(field->u.raw, buf, bufsize);
00162
00163 size += fieldsize;
00164 }
00165
00166 void BuildField(Data &data, size_t &size, const Barry::UnknownField &field)
00167 {
00168 BuildField(data, size, field.type,
00169 field.data.raw_data.data(), field.data.raw_data.size());
00170 }
00171
00172 void BuildField(Data &data, size_t &size, uint8_t type, const Barry::Protocol::GroupLink &link)
00173 {
00174 size_t linksize = sizeof(Barry::Protocol::GroupLink);
00175 size_t fieldsize = COMMON_FIELD_HEADER_SIZE + linksize;
00176 unsigned char *pd = data.GetBuffer(size + fieldsize) + size;
00177 CommonField *field = (CommonField *) pd;
00178
00179 field->size = htobs(linksize);
00180 field->type = type;
00181 field->u.link = link;
00182
00183 size += fieldsize;
00184 }
00185
00186 std::string ParseFieldString(const Barry::Protocol::CommonField *field)
00187 {
00188
00189
00190
00191 return ParseFieldString(field->u.raw, btohs(field->size));
00192 }
00193
00194 std::string ParseFieldString(const void *data, uint16_t maxlen)
00195 {
00196 const char *str = (const char *)data;
00197
00198
00199
00200 while( maxlen && str[maxlen-1] == 0 )
00201 maxlen--;
00202
00203 return std::string(str, maxlen);
00204 }
00205
00206
00207
00208
00209
00210 std::ostream& operator<< (std::ostream &os, const std::vector<UnknownField> &unknowns)
00211 {
00212 std::vector<UnknownField>::const_iterator
00213 ub = unknowns.begin(), ue = unknowns.end();
00214 if( ub != ue )
00215 os << " Unknowns:\n";
00216 for( ; ub != ue; ub++ ) {
00217 os << " Type: 0x" << setbase(16)
00218 << (unsigned int) ub->type
00219 << " Data:\n" << Data(ub->data.data(), ub->data.size());
00220 }
00221 return os;
00222 }
00223
00224
00225
00226
00227
00228 std::ostream& operator<<(std::ostream &os, const EmailAddress &msga) {
00229 os << msga.Name << " <" << msga.Email << ">";
00230 return os;
00231 }
00232
00233 std::ostream& operator<<(std::ostream &os, const EmailAddressList &elist) {
00234 for( EmailAddressList::const_iterator i = elist.begin(); i != elist.end(); ++i ) {
00235 if( i != elist.begin() )
00236 os << ", ";
00237 os << *i;
00238 }
00239 return os;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 std::string PostalAddress::GetLabel() const
00252 {
00253 std::string address = Address1;
00254 if( Address2.size() ) {
00255 if( address.size() )
00256 address += "\n";
00257 address += Address2;
00258 }
00259 if( Address3.size() ) {
00260 if( address.size() )
00261 address += "\n";
00262 address += Address3;
00263 }
00264 if( address.size() )
00265 address += "\n";
00266 if( City.size() )
00267 address += City + " ";
00268 if( Province.size() )
00269 address += Province + " ";
00270 if( Country.size() )
00271 address += Country;
00272 if( address.size() )
00273 address += "\n";
00274 if( PostalCode.size() )
00275 address += PostalCode;
00276
00277 return address;
00278 }
00279
00280 void PostalAddress::Clear()
00281 {
00282 Address1.clear();
00283 Address2.clear();
00284 Address3.clear();
00285 City.clear();
00286 Province.clear();
00287 PostalCode.clear();
00288 Country.clear();
00289 }
00290
00291 std::ostream& operator<<(std::ostream &os, const PostalAddress &post) {
00292 os << post.GetLabel();
00293 return os;
00294 }
00295
00296
00297
00298
00299
00300
00301 Date::Date(const struct tm *timep)
00302 {
00303 FromTm(timep);
00304 }
00305
00306 void Date::Clear()
00307 {
00308 Month = Day = Year = 0;
00309 }
00310
00311 void Date::ToTm(struct tm *timep) const
00312 {
00313 memset(timep, 0, sizeof(tm));
00314 timep->tm_year = Year - 1900;
00315 timep->tm_mon = Month;
00316 timep->tm_mday = Day;
00317 }
00318
00319 std::string Date::ToYYYYMMDD() const
00320 {
00321 std::ostringstream oss;
00322
00323 oss << setw(4) << setfill('0') << Year
00324 << setw(2) << setfill('0') << (Month + 1)
00325 << setw(2) << setfill('0') << Day;
00326 return oss.str();
00327 }
00328
00329
00330
00331
00332
00333
00334
00335 std::string Date::ToBBString() const
00336 {
00337 std::ostringstream oss;
00338
00339 oss << setw(2) << setfill('0') << Day << '/'
00340 << setw(2) << setfill('0') << (Month + 1) << '/'
00341 << setw(2) << setfill('0') << Year;
00342 return oss.str();
00343 }
00344
00345 bool Date::FromTm(const struct tm *timep)
00346 {
00347 if( !timep )
00348 throw std::logic_error("NULL time pointer passed to Date::FromTm");
00349
00350 Year = timep->tm_year + 1900;
00351 Month = timep->tm_mon;
00352 Day = timep->tm_mday;
00353 return true;
00354 }
00355
00356 bool Date::FromBBString(const std::string &str)
00357 {
00358 int m, d, y;
00359 if( 3 == sscanf(str.c_str(), "%d/%d/%d", &d, &m, &y) ) {
00360 Year = y;
00361 Month = m - 1;
00362 Day = d;
00363 return true;
00364 }
00365 return false;
00366 }
00367
00368 bool Date::FromYYYYMMDD(const std::string &str)
00369 {
00370 int m, d, y;
00371 if( 3 == sscanf(str.c_str(), "%4d%2d%2d", &y, &m, &d) ) {
00372 Year = y;
00373 Month = m - 1;
00374 Day = d;
00375 return true;
00376 }
00377 return false;
00378 }
00379
00380 std::ostream& operator<<(std::ostream &os, const Date &date)
00381 {
00382 os << setw(4) << dec << date.Year << '/'
00383 << setw(2) << dec << (date.Month + 1) << '/'
00384 << setw(2) << dec << date.Day;
00385 return os;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395 void CategoryList::CategoryStr2List(const std::string &str)
00396 {
00397
00398 clear();
00399
00400 if( !str.size() )
00401 return;
00402
00403
00404
00405 string::size_type start = 0, end = 0, delim = str.find(',', start);
00406 while( start != string::npos ) {
00407 if( delim == string::npos )
00408 end = str.size() - 1;
00409 else
00410 end = delim - 1;
00411
00412
00413 while( str[start] == ' ' )
00414 start++;
00415 while( end && str[end] == ' ' )
00416 end--;
00417
00418 if( start <= end ) {
00419 string token = str.substr(start, end-start+1);
00420 push_back(token);
00421 }
00422
00423
00424 start = delim;
00425 if( start != string::npos )
00426 start++;
00427 delim = str.find(',', start);
00428 }
00429 }
00430
00431
00432
00433 void CategoryList::CategoryList2Str(std::string &str) const
00434 {
00435 str.clear();
00436
00437 Barry::CategoryList::const_iterator i = begin();
00438 for( ; i != end(); ++i ) {
00439 if( str.size() )
00440 str += ", ";
00441 str += *i;
00442 }
00443 }
00444
00445
00446 }
00447
00448
00449 #ifdef __TEST_MODE__
00450
00451 #include <iostream>
00452
00453 int main(int argc, char *argv[])
00454 {
00455 if( argc < 2 ) {
00456 cerr << "Usage: test <datafile>" << endl;
00457 return 1;
00458 }
00459
00460 std::vector<Data> array;
00461 if( !LoadDataArray(argv[1], array) ) {
00462 cerr << "Unable to load file: " << argv[1] << endl;
00463 return 1;
00464 }
00465
00466 cout << "Loaded " << array.size() << " items" << endl;
00467
00468 for( std::vector<Data>::iterator b = array.begin(), e = array.end();
00469 b != e; b++ )
00470 {
00471 Data &d = *b;
00472
00473 if( d.GetSize() > 13 && d.GetData()[6] == 0x4f ) {
00474 Barry::Contact contact;
00475 size_t size = 13;
00476 contact.ParseFields(d, size);
00477 cout << contact << endl;
00478 contact.DumpLdif(cout, "ou=People,dc=example,dc=com");
00479 }
00480 else if( d.GetSize() > 13 && d.GetData()[6] == 0x44 ) {
00481 Barry::Calendar cal;
00482 size_t size = 13;
00483 cal.ParseFields(d, size);
00484 cout << cal << endl;
00485 }
00486 }
00487 }
00488
00489 #endif
00490