3 /// vformat support routines in base class
7 Copyright (C) 2006-2013, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
25 #include "vformat.h" // comes from opensync, but not a public header yet
26 #include "tzwrapper.h"
27 #include "r_contact.h" // for CategoryList
37 namespace Barry
{ namespace Sync
{
39 //////////////////////////////////////////////////////////////////////////////
42 std::string
vTimeConverter::unix2vtime(const time_t *timestamp
)
45 if( !gmtime_r(timestamp
, &split
) ) {
47 oss
<< _("gmtime_r() failed on time_t of: ");
51 oss
<< _("(null pointer)");
52 throw Barry::ConvertError(oss
.str());
55 return tm_to_iso(&split
, true);
58 time_t vTimeConverter::vtime2unix(const char *vtime
)
60 return TzWrapper::iso_mktime(vtime
);
64 // The following implementation is taken from opensync's
65 // opensync_time.c implementation with the following copyright
66 // notices at the top as of July 2010:
68 // * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org>
69 // * Copyright (C) 2006-2008 Daniel Gollub <gollub@b1-systems.de>
70 // * Copyright (C) 2007 Chris Frey <cdfrey@netdirect.ca>
72 // License: LGPL 2.1 or later
74 int vTimeConverter::alarmduration2sec(const char *alarm
)
76 int i
, secs
, digits
= 0;
78 int sign
= 1; // when ical stamp doesn't start with '-' => seconds after event
79 int days
= 0, weeks
= 0, hours
= 0, minutes
= 0, seconds
= 0;
80 int len
= strlen(alarm
);
82 for (i
=0; i
< len
; i
++) {
86 sign
= -1; // seconds before event - change the sign
124 if (sscanf((char*)(alarm
+i
),"%d",&digits
) == EOF
)
132 secs
= (weeks
* 7 * 24 * 3600) + (days
* 24 * 3600) + (hours
* 3600) + (minutes
* 60) + seconds
;
134 secs
= secs
* sign
; // change sign if the alarm is in seconds before event (leading '-')
141 //////////////////////////////////////////////////////////////////////////////
144 std::string
vAttr::GetName()
151 const char *name
= b_vformat_attribute_get_name(m_attr
);
157 std::string
vAttr::GetValue(int nth
)
160 const char *value
= 0;
163 if( b_vformat_attribute_is_single_valued(m_attr
) ) {
165 value
= b_vformat_attribute_get_value(m_attr
);
168 value
= b_vformat_attribute_get_nth_value(m_attr
, nth
);
178 std::string
vAttr::GetDecodedValue()
181 GString
*value
= NULL
;
184 if( b_vformat_attribute_is_single_valued(m_attr
) ) {
185 value
= b_vformat_attribute_get_value_decoded(m_attr
);
190 ret
.assign(value
->str
, value
->len
);
195 std::string
vAttr::GetParam(const char *name
, int nth
)
202 b_VFormatParam
*param
= b_vformat_attribute_find_param(m_attr
, name
, 0);
206 const char *value
= b_vformat_attribute_param_get_nth_value(param
, nth
);
213 /// Does an exhaustive search through the attribute, searching for all
214 /// param values that exist for the given name, and returns all values
215 /// in a comma delimited string.
216 std::string
vAttr::GetAllParams(const char *name
)
223 b_VFormatParam
*param
= 0;
225 (param
= b_vformat_attribute_find_param(m_attr
, name
, level
));
228 const char *value
= 0;
230 (value
= b_vformat_attribute_param_get_nth_value(param
, nth
));
243 //////////////////////////////////////////////////////////////////////////////
247 : m_format(b_vformat_new())
251 vBase::vBase(b_VFormat
*format
)
255 throw Barry::Error(_("Cannot construct vBase with null format"));
261 b_vformat_free(m_format
);
266 void vBase::SetFormat(b_VFormat
*format
)
269 throw Barry::Error(_("Cannot set vBase with null format"));
272 b_vformat_free(m_format
);
281 b_vformat_free(m_format
);
282 m_format
= b_vformat_new();
286 vAttrPtr
vBase::NewAttr(const char *name
)
288 // Trace trace("vBase::NewAttr");
290 // trace.logf("creating valueless attr: %s", name);
292 vAttrPtr
attr(b_vformat_attribute_new(NULL
, name
));
294 throw Barry::ConvertError(_("resource error allocating vformat attribute"));
298 vAttrPtr
vBase::NewAttr(const char *name
, const char *value
)
300 // Trace trace("vBase::NewAttr");
303 some vCard values are positional (like name), so blank should be allowed...
305 if( strlen(value) == 0 ) {
306 trace.logf("attribute '%s' contains no data, skipping", name);
311 // trace.logf("creating attr: %s, %s", name, value);
313 vAttrPtr
attr(b_vformat_attribute_new(NULL
, name
));
315 throw ConvertError(_("resource error allocating vformat attribute"));
317 b_vformat_attribute_add_value(attr
.Get(), value
);
321 void vBase::AddAttr(vAttrPtr attr
)
323 // Trace trace("vBase::AddAttr");
326 // trace.log("attribute contains no data, skipping");
330 b_vformat_add_attribute(m_format
, attr
.Extract());
333 void vBase::AddValue(vAttrPtr
&attr
, const char *value
)
335 // Trace trace("vBase::AddValue");
337 // trace.log("attribute pointer contains no data, skipping");
341 if( strlen(value) == 0 ) {
342 trace.log("attribute value is empty, skipping");
346 b_vformat_attribute_add_value(attr
.Get(), value
);
349 void vBase::AddEncodedValue(vAttrPtr
&attr
, b_VFormatEncoding encoding
, const char *value
, int len
)
351 // Trace trace("vBase::AddValue");
353 // trace.log("attribute pointer contains no data, skipping");
357 attr
.Get()->encoding
= encoding
;
358 attr
.Get()->encoding_set
= TRUE
;
360 b_vformat_attribute_add_value_decoded(attr
.Get(), value
, len
);
363 void vBase::AddParam(vAttrPtr
&attr
, const char *name
, const char *value
)
365 // Trace trace("vBase::AddParam");
368 // trace.log("attribute pointer contains no data, skipping");
372 if( strlen(value) == 0 ) {
373 trace.log("parameter value is empty, skipping");
378 b_VFormatParam
*pParam
= b_vformat_attribute_param_new(name
);
379 b_vformat_attribute_param_add_value(pParam
, value
);
380 b_vformat_attribute_add_param(attr
.Get(), pParam
);
383 void vBase::AddCategories(const Barry::CategoryList
&categories
)
385 if( !categories
.size() )
388 vAttrPtr cat
= NewAttr("CATEGORIES"); // RFC 2426, 3.6.1
389 Barry::CategoryList::const_iterator i
= categories
.begin();
390 for( ; i
< categories
.end(); ++i
) {
391 AddValue(cat
, i
->c_str());
396 std::string
vBase::GetAttr(const char *attrname
, const char *block
)
398 // Trace trace("vBase::GetAttr");
399 // trace.logf("getting attr: %s", attrname);
402 const char *value
= 0;
404 bool needs_freeing
= false;
406 b_VFormatAttribute
*attr
= b_vformat_find_attribute(m_format
, attrname
, 0, block
);
408 if( b_vformat_attribute_is_single_valued(attr
) ) {
409 value
= b_vformat_attribute_get_value(attr
);
410 needs_freeing
= true;
413 // FIXME, this is hardcoded
414 value
= b_vformat_attribute_get_nth_value(attr
, 0);
422 g_free((char *)value
);
424 // trace.logf("attr value: %s", ret.c_str());
428 std::vector
<std::string
> vBase::GetValueVector(const char *attrname
, const char *block
)
430 // Trace trace("vBase::GetValueVector");
431 // trace.logf("getting value vector for: %s", attrname);
433 std::vector
<std::string
> ret
;
434 const char *value
= 0;
435 bool needs_freeing
= false;
437 b_VFormatAttribute
*attr
= b_vformat_find_attribute(m_format
, attrname
, 0, block
);
439 if( b_vformat_attribute_is_single_valued(attr
) ) {
440 value
= b_vformat_attribute_get_value(attr
);
441 needs_freeing
= true;
443 // nasty, but avoids tweaking vformat.
446 value
= b_vformat_attribute_get_nth_value(attr
, idx
++);
448 ret
.push_back(value
);
455 g_free((char *)value
);
460 vAttr
vBase::GetAttrObj(const char *attrname
, int nth
, const char *block
)
462 // Trace trace("vBase::GetAttrObj");
463 // trace.logf("getting attr: %s", attrname);
465 return vAttr(b_vformat_find_attribute(m_format
, attrname
, nth
, block
));
468 std::vector
<std::string
> vBase::Tokenize(const std::string
& str
, const char delim
)
470 std::vector
<std::string
> tokens
;
471 std::string::size_type delimPos
= 0, tokenPos
= 0, pos
= 0;
473 if( str
.length() < 1 ) {
478 delimPos
= str
.find_first_of(delim
, pos
);
479 tokenPos
= str
.find_first_not_of(delim
, pos
);
481 if( std::string::npos
!= delimPos
) {
482 if( std::string::npos
!= tokenPos
) {
483 if( tokenPos
< delimPos
) {
484 tokens
.push_back(str
.substr(pos
, delimPos
-pos
));
486 tokens
.push_back("");
489 tokens
.push_back("");
493 if( std::string::npos
!= tokenPos
){
494 tokens
.push_back(str
.substr(pos
));
496 tokens
.push_back("");
504 std::string
vBase::ToStringList(const std::vector
<std::string
> &list
, const char delim
)
507 for( unsigned int idx
= 0; idx
< list
.size(); idx
++ ) {
516 }} // namespace Barry::Sync