# vbase.cc

    00001 //
    00002 // \file        vbase.cc
    00003 //              vformat support routines in base class
    00004 //
    00005
    00006 /*
    00007     Copyright (C) 2006-2011, Net Direct Inc. (http://www.netdirect.ca/)
    00008
    00009     This program is free software; you can redistribute it and/or modify
    00010     it under the terms of the GNU General Public License as published by
    00011     the Free Software Foundation; either version 2 of the License, or
    00012     (at your option) any later version.
    00013
    00014     This program is distributed in the hope that it will be useful,
    00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00017
    00018     See the GNU General Public License in the COPYING file at the
    00019     root directory of this project for more details.
    00020 */
    00021
    00022 #include "vbase.h"
    00023 //#include "trace.h"
    00024 #include "vformat.h"            // comes from opensync, but not a public header yet
    00025 #include "tzwrapper.h"
    00026 #include <stdio.h>
    00027 #include <stdarg.h>
    00028 #include <stdint.h>
    00029 #include <string.h>
    00030 #include <glib.h>
    00031 #include <sstream>
    00032
    00033 using namespace std;
    00034
    00035 namespace Barry { namespace Sync {
    00036
    00037 //////////////////////////////////////////////////////////////////////////////
    00038 // vTimeConverter
    00039
    00040 std::string vTimeConverter::unix2vtime(const time_t *timestamp)
    00041 {
    00042         struct tm split;
    00043         if( !gmtime_r(timestamp, &split) ) {
    00044                 ostringstream oss;
    00045                 oss << "gmtime_r() failed on time_t of ";
    00046                 if( timestamp )
    00047                         oss << *timestamp;
    00048                 else
    00049                         oss << "(null pointer)";
    00050                 throw Barry::ConvertError(oss.str());
    00051         }
    00052
    00053         return tm_to_iso(&split, true);
    00054 }
    00055
    00056 time_t vTimeConverter::vtime2unix(const char *vtime)
    00057 {
    00058         return TzWrapper::iso_mktime(vtime);
    00059 }
    00060
    00061 //
    00062 // The following implementation is taken from opensync's
    00063 // opensync_time.c implementation with the following copyright
    00064 // notices at the top as of July 2010:
    00065 //
    00066 //  * Copyright (C) 2004-2005  Armin Bauer <armin.bauer@opensync.org>
    00067 //  * Copyright (C) 2006-2008 Daniel Gollub <gollub@b1-systems.de>
    00068 //  * Copyright (C) 2007 Chris Frey <cdfrey@netdirect.ca>
    00069 //
    00070 // License: LGPL 2.1 or later
    00071 //
    00072 int vTimeConverter::alarmduration2sec(const char *alarm)
    00073 {
    00074         int i, secs, digits = 0;
    00075         int is_digit = 0;
    00076         int sign = 1;   // when ical stamp doesn't start with '-' => seconds after event
    00077         int days = 0, weeks = 0, hours = 0, minutes = 0, seconds = 0;
    00078         int len = strlen(alarm);
    00079
    00080         for (i=0; i < len; i++) {
    00081
    00082                 switch (alarm[i]) {
    00083                 case '-':
    00084                         sign = -1; // seconds before event - change the sign
    00085                 case 'P':
    00086                 case 'T':
    00087                         is_digit = 0;
    00088                         break;
    00089                 case 'W':
    00090                         is_digit = 0;
    00091                         weeks = digits;
    00092                         break;
    00093                 case 'D':
    00094                         is_digit = 0;
    00095                         days = digits;
    00096                         break;
    00097                 case 'H':
    00098                         is_digit = 0;
    00099                         hours = digits;
    00100                         break;
    00101                 case 'M':
    00102                         is_digit = 0;
    00103                         minutes = digits;
    00104                         break;
    00105                 case 'S':
    00106                         is_digit = 0;
    00107                         seconds = digits;
    00108                         break;
    00109                 case '0':
    00110                 case '1':
    00111                 case '2':
    00112                 case '3':
    00113                 case '4':
    00114                 case '5':
    00115                 case '6':
    00116                 case '7':
    00117                 case '8':
    00118                 case '9':
    00119                         if (is_digit)
    00120                                 break;
    00121
    00122                         if (sscanf((char*)(alarm+i),"%d",&digits) == EOF)
    00123                                 return -1;
    00124
    00125                         is_digit = 1;
    00126                         break;
    00127                 }
    00128         }
    00129
    00130         secs = (weeks * 7 * 24 * 3600) + (days * 24 * 3600) + (hours * 3600) + (minutes * 60) + seconds;
    00131
    00132         secs = secs * sign;     // change sign if the alarm is in seconds before event (leading '-')
    00133
    00134         return secs;
    00135
    00136 }
    00137
    00138
    00139 //////////////////////////////////////////////////////////////////////////////
    00140 // vAttr
    00141
    00142 std::string vAttr::GetName()
    00143 {
    00144         std::string ret;
    00145
    00146         if( !m_attr )
    00147                 return ret;
    00148
    00149         const char *name = b_vformat_attribute_get_name(m_attr);
    00150         if( name )
    00151                 ret = name;
    00152         return ret;
    00153 }
    00154
    00155 std::string vAttr::GetValue(int nth)
    00156 {
    00157         std::string ret;
    00158         const char *value = 0;
    00159
    00160         if( m_attr ) {
    00161                 if( b_vformat_attribute_is_single_valued(m_attr) ) {
    00162                         if( nth == 0 )
    00163                                 value = b_vformat_attribute_get_value(m_attr);
    00164                 }
    00165                 else {
    00166                         value = b_vformat_attribute_get_nth_value(m_attr, nth);
    00167                 }
    00168         }
    00169
    00170         if( value )
    00171                 ret = value;
    00172
    00173         return ret;
    00174 }
    00175
    00176 std::string vAttr::GetDecodedValue()
    00177 {
    00178         std::string ret;
    00179         GString *value = NULL;
    00180
    00181         if( m_attr ) {
    00182                 if( b_vformat_attribute_is_single_valued(m_attr) ) {
    00183                         value = b_vformat_attribute_get_value_decoded(m_attr);
    00184                 }
    00185         }
    00186
    00187         if( value )
    00188                 ret.assign(value->str, value->len);
    00189
    00190         return ret;
    00191 }
    00192
    00193 std::string vAttr::GetParam(const char *name, int nth)
    00194 {
    00195         std::string ret;
    00196
    00197         if( !m_attr )
    00198                 return ret;
    00199
    00200         b_VFormatParam *param = b_vformat_attribute_find_param(m_attr, name, 0);
    00201         if( !param )
    00202                 return ret;
    00203
    00204         const char *value = b_vformat_attribute_param_get_nth_value(param, nth);
    00205         if( value )
    00206                 ret = value;
    00207
    00208         return ret;
    00209 }
    00210
    00211 /// Does an exhaustive search through the attribute, searching for all
    00212 /// param values that exist for the given name, and returns all values
    00213 /// in a comma delimited string.
    00214 std::string vAttr::GetAllParams(const char *name)
    00215 {
    00216         std::string ret;
    00217
    00218         if( !m_attr )
    00219                 return ret;
    00220
    00221         b_VFormatParam *param = 0;
    00222         for( int level = 0;
    00223              (param = b_vformat_attribute_find_param(m_attr, name, level));
    00224              level++ )
    00225         {
    00226                 const char *value = 0;
    00227                 for( int nth = 0;
    00228                      (value = b_vformat_attribute_param_get_nth_value(param, nth));
    00229                      nth++ )
    00230                 {
    00231                         if( ret.size() )
    00232                                 ret += ",";
    00233                         ret += value;
    00234                 }
    00235         }
    00236
    00237         return ret;
    00238 }
    00239
    00240
    00241 //////////////////////////////////////////////////////////////////////////////
    00242 // vCalendar
    00243
    00244 vBase::vBase()
    00245         : m_format(b_vformat_new())
    00246 {
    00247 }
    00248
    00249 vBase::vBase(b_VFormat *format)
    00250         : m_format(format)
    00251 {
    00252         if( !format )
    00253                 throw Barry::Error("Cannot construct vBase with null format");
    00254 }
    00255
    00256 vBase::~vBase()
    00257 {
    00258         if( m_format ) {
    00259                 b_vformat_free(m_format);
    00260                 m_format = 0;
    00261         }
    00262 }
    00263
    00264 void vBase::SetFormat(b_VFormat *format)
    00265 {
    00266         if( !format )
    00267                 throw Barry::Error("Cannot set vBase with null format");
    00268
    00269         if( m_format ) {
    00270                 b_vformat_free(m_format);
    00271                 m_format = 0;
    00272         }
    00273         m_format = format;
    00274 }
    00275
    00276 void vBase::Clear()
    00277 {
    00278         if( m_format ) {
    00279                 b_vformat_free(m_format);
    00280                 m_format = b_vformat_new();
    00281         }
    00282 }
    00283
    00284 vAttrPtr vBase::NewAttr(const char *name)
    00285 {
    00286 //      Trace trace("vBase::NewAttr");
    00287
    00288 //      trace.logf("creating valueless attr: %s", name);
    00289
    00290         vAttrPtr attr(b_vformat_attribute_new(NULL, name));
    00291         if( !attr.Get() )
    00292                 throw Barry::ConvertError("resource error allocating vformat attribute");
    00293         return attr;
    00294 }
    00295
    00296 vAttrPtr vBase::NewAttr(const char *name, const char *value)
    00297 {
    00298 //      Trace trace("vBase::NewAttr");
    00299
    00300 /*
    00301 some vCard values are positional (like name), so blank should be allowed...
    00302
    00303         if( strlen(value) == 0 ) {
    00304                 trace.logf("attribute '%s' contains no data, skipping", name);
    00305                 return vAttrPtr();
    00306         }
    00307 */
    00308
    00309 //      trace.logf("creating attr: %s, %s", name, value);
    00310
    00311         vAttrPtr attr(b_vformat_attribute_new(NULL, name));
    00312         if( !attr.Get() )
    00313                 throw ConvertError("resource error allocating vformat attribute");
    00314
    00315         b_vformat_attribute_add_value(attr.Get(), value);
    00316         return attr;
    00317 }
    00318
    00319 void vBase::AddAttr(vAttrPtr attr)
    00320 {
    00321 //      Trace trace("vBase::AddAttr");
    00322
    00323         if( !attr.Get() ) {
    00324 //              trace.log("attribute contains no data, skipping");
    00325                 return;
    00326         }
    00327
    00328         b_vformat_add_attribute(m_format, attr.Extract());
    00329 }
    00330
    00331 void vBase::AddValue(vAttrPtr &attr, const char *value)
    00332 {
    00333 //      Trace trace("vBase::AddValue");
    00334         if( !attr.Get() ) {
    00335 //              trace.log("attribute pointer contains no data, skipping");
    00336                 return;
    00337         }
    00338 /*
    00339         if( strlen(value) == 0 ) {
    00340                 trace.log("attribute value is empty, skipping");
    00341                 return;
    00342         }
    00343 */
    00344         b_vformat_attribute_add_value(attr.Get(), value);
    00345 }
    00346
    00347 void vBase::AddEncodedValue(vAttrPtr &attr, b_VFormatEncoding encoding, const char *value, int len)
    00348 {
    00349 //      Trace trace("vBase::AddValue");
    00350         if( !attr.Get() ) {
    00351 //              trace.log("attribute pointer contains no data, skipping");
    00352                 return;
    00353         }
    00354
    00355         attr.Get()->encoding = encoding;
    00356         attr.Get()->encoding_set = TRUE;
    00357
    00358         b_vformat_attribute_add_value_decoded(attr.Get(), value, len);
    00359 }
    00360
    00361 void vBase::AddParam(vAttrPtr &attr, const char *name, const char *value)
    00362 {
    00363 //      Trace trace("vBase::AddParam");
    00364
    00365         if( !attr.Get() ) {
    00366 //              trace.log("attribute pointer contains no data, skipping");
    00367                 return;
    00368         }
    00369 /*
    00370         if( strlen(value) == 0 ) {
    00371                 trace.log("parameter value is empty, skipping");
    00372                 return;
    00373         }
    00374 */
    00375
    00376         b_VFormatParam *pParam = b_vformat_attribute_param_new(name);
    00377         b_vformat_attribute_param_add_value(pParam, value);
    00378         b_vformat_attribute_add_param(attr.Get(), pParam);
    00379 }
    00380
    00381 std::string vBase::GetAttr(const char *attrname, const char *block)
    00382 {
    00383 //      Trace trace("vBase::GetAttr");
    00384 //      trace.logf("getting attr: %s", attrname);
    00385
    00386         std::string ret;
    00387         const char *value = 0;
    00388
    00389         bool needs_freeing = false;
    00390
    00391         b_VFormatAttribute *attr = b_vformat_find_attribute(m_format, attrname, 0, block);
    00392         if( attr ) {
    00393                 if( b_vformat_attribute_is_single_valued(attr) ) {
    00394                         value = b_vformat_attribute_get_value(attr);
    00395                         needs_freeing = true;
    00396                 }
    00397                 else {
    00398                         // FIXME, this is hardcoded
    00399                         value = b_vformat_attribute_get_nth_value(attr, 0);
    00400                 }
    00401         }
    00402
    00403         if( value )
    00404                 ret = value;
    00405
    00406         if( needs_freeing )
    00407                 g_free((char *)value);
    00408
    00409 //      trace.logf("attr value: %s", ret.c_str());
    00410         return ret;
    00411 }
    00412
    00413 std::vector<std::string> vBase::GetValueVector(const char *attrname, const char *block)
    00414 {
    00415 //      Trace trace("vBase::GetValueVector");
    00416 //      trace.logf("getting value vector for: %s", attrname);
    00417
    00418         std::vector<std::string> ret;
    00419         const char *value = 0;
    00420         bool needs_freeing = false;
    00421
    00422         b_VFormatAttribute *attr = b_vformat_find_attribute(m_format, attrname, 0, block);
    00423         if( attr ) {
    00424                 if( b_vformat_attribute_is_single_valued(attr) ) {
    00425                         value = b_vformat_attribute_get_value(attr);
    00426                         needs_freeing = true;
    00427                 } else {
    00428                         // nasty, but avoids tweaking vformat.
    00429                         int idx = 0;
    00430                         do {
    00431                                 value = b_vformat_attribute_get_nth_value(attr, idx++);
    00432                                 if( value ) {
    00433                                         ret.push_back(value);
    00434                                 }
    00435                         } while( value );
    00436                 }
    00437         }
    00438
    00439         if( needs_freeing )
    00440                 g_free((char *)value);
    00441
    00442         return ret;
    00443 }
    00444
    00445 vAttr vBase::GetAttrObj(const char *attrname, int nth, const char *block)
    00446 {
    00447 //      Trace trace("vBase::GetAttrObj");
    00448 //      trace.logf("getting attr: %s", attrname);
    00449
    00450         return vAttr(b_vformat_find_attribute(m_format, attrname, nth, block));
    00451 }
    00452
    00453 std::vector<std::string> vBase::Tokenize(const std::string& str, const char delim)
    00454 {
    00455         std::vector<std::string> tokens;
    00456         std::string::size_type delimPos = 0, tokenPos = 0, pos = 0;
    00457
    00458         if( str.length() < 1 ) {
    00459                 return tokens;
    00460         }
    00461
    00462         while( 1 ) {
    00463                 delimPos = str.find_first_of(delim, pos);
    00464                 tokenPos = str.find_first_not_of(delim, pos);
    00465
    00466                 if( std::string::npos != delimPos ) {
    00467                         if( std::string::npos != tokenPos ) {
    00468                                 if( tokenPos < delimPos ) {
    00469                                         tokens.push_back(str.substr(pos, delimPos-pos));
    00470                                 } else {
    00471                                         tokens.push_back("");
    00472                                 }
    00473                         } else {
    00474                                 tokens.push_back("");
    00475                         }
    00476                         pos = delimPos + 1;
    00477                 } else {
    00478                         if( std::string::npos != tokenPos ){
    00479                                 tokens.push_back(str.substr(pos));
    00480                         } else {
    00481                                 tokens.push_back("");
    00482                         }
    00483                         break;
    00484                 }
    00485         }
    00486         return tokens;
    00487 }
    00488
    00489 std::string vBase::ToStringList(const std::vector<std::string> &list, const char delim)
    00490 {
    00491         std::string str;
    00492         for( unsigned int idx = 0; idx < list.size(); idx++ ) {
    00493                 if( idx ) {
    00494                         str += delim;
    00495                 }
    00496                 str += list[idx];
    00497         }
    00498         return str;
    00499 }
    00500
    00501 }} // namespace Barry::Sync
    00502