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