menu: added new Keywords tag to .desktop files
[barry.git] / src / vbase.cc
blob17947de57303d3bd69306de8e5134f4e9057d9d9
1 ///
2 /// \file vbase.cc
3 /// vformat support routines in base class
4 ///
6 /*
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.
22 #include "i18n.h"
23 #include "vbase.h"
24 //#include "trace.h"
25 #include "vformat.h" // comes from opensync, but not a public header yet
26 #include "tzwrapper.h"
27 #include "r_contact.h" // for CategoryList
28 #include <stdio.h>
29 #include <stdarg.h>
30 #include <stdint.h>
31 #include <string.h>
32 #include <glib.h>
33 #include <sstream>
35 using namespace std;
37 namespace Barry { namespace Sync {
39 //////////////////////////////////////////////////////////////////////////////
40 // vTimeConverter
42 std::string vTimeConverter::unix2vtime(const time_t *timestamp)
44 struct tm split;
45 if( !gmtime_r(timestamp, &split) ) {
46 ostringstream oss;
47 oss << _("gmtime_r() failed on time_t of: ");
48 if( timestamp )
49 oss << *timestamp;
50 else
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;
77 int is_digit = 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++) {
84 switch (alarm[i]) {
85 case '-':
86 sign = -1; // seconds before event - change the sign
87 case 'P':
88 case 'T':
89 is_digit = 0;
90 break;
91 case 'W':
92 is_digit = 0;
93 weeks = digits;
94 break;
95 case 'D':
96 is_digit = 0;
97 days = digits;
98 break;
99 case 'H':
100 is_digit = 0;
101 hours = digits;
102 break;
103 case 'M':
104 is_digit = 0;
105 minutes = digits;
106 break;
107 case 'S':
108 is_digit = 0;
109 seconds = digits;
110 break;
111 case '0':
112 case '1':
113 case '2':
114 case '3':
115 case '4':
116 case '5':
117 case '6':
118 case '7':
119 case '8':
120 case '9':
121 if (is_digit)
122 break;
124 if (sscanf((char*)(alarm+i),"%d",&digits) == EOF)
125 return -1;
127 is_digit = 1;
128 break;
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 '-')
136 return secs;
141 //////////////////////////////////////////////////////////////////////////////
142 // vAttr
144 std::string vAttr::GetName()
146 std::string ret;
148 if( !m_attr )
149 return ret;
151 const char *name = b_vformat_attribute_get_name(m_attr);
152 if( name )
153 ret = name;
154 return ret;
157 std::string vAttr::GetValue(int nth)
159 std::string ret;
160 const char *value = 0;
162 if( m_attr ) {
163 if( b_vformat_attribute_is_single_valued(m_attr) ) {
164 if( nth == 0 )
165 value = b_vformat_attribute_get_value(m_attr);
167 else {
168 value = b_vformat_attribute_get_nth_value(m_attr, nth);
172 if( value )
173 ret = value;
175 return ret;
178 std::string vAttr::GetDecodedValue()
180 std::string ret;
181 GString *value = NULL;
183 if( m_attr ) {
184 if( b_vformat_attribute_is_single_valued(m_attr) ) {
185 value = b_vformat_attribute_get_value_decoded(m_attr);
189 if( value )
190 ret.assign(value->str, value->len);
192 return ret;
195 std::string vAttr::GetParam(const char *name, int nth)
197 std::string ret;
199 if( !m_attr )
200 return ret;
202 b_VFormatParam *param = b_vformat_attribute_find_param(m_attr, name, 0);
203 if( !param )
204 return ret;
206 const char *value = b_vformat_attribute_param_get_nth_value(param, nth);
207 if( value )
208 ret = value;
210 return ret;
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)
218 std::string ret;
220 if( !m_attr )
221 return ret;
223 b_VFormatParam *param = 0;
224 for( int level = 0;
225 (param = b_vformat_attribute_find_param(m_attr, name, level));
226 level++ )
228 const char *value = 0;
229 for( int nth = 0;
230 (value = b_vformat_attribute_param_get_nth_value(param, nth));
231 nth++ )
233 if( ret.size() )
234 ret += ",";
235 ret += value;
239 return ret;
243 //////////////////////////////////////////////////////////////////////////////
244 // vCalendar
246 vBase::vBase()
247 : m_format(b_vformat_new())
251 vBase::vBase(b_VFormat *format)
252 : m_format(format)
254 if( !format )
255 throw Barry::Error(_("Cannot construct vBase with null format"));
258 vBase::~vBase()
260 if( m_format ) {
261 b_vformat_free(m_format);
262 m_format = 0;
266 void vBase::SetFormat(b_VFormat *format)
268 if( !format )
269 throw Barry::Error(_("Cannot set vBase with null format"));
271 if( m_format ) {
272 b_vformat_free(m_format);
273 m_format = 0;
275 m_format = format;
278 void vBase::Clear()
280 if( 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));
293 if( !attr.Get() )
294 throw Barry::ConvertError(_("resource error allocating vformat attribute"));
295 return attr;
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);
307 return vAttrPtr();
311 // trace.logf("creating attr: %s, %s", name, value);
313 vAttrPtr attr(b_vformat_attribute_new(NULL, name));
314 if( !attr.Get() )
315 throw ConvertError(_("resource error allocating vformat attribute"));
317 b_vformat_attribute_add_value(attr.Get(), value);
318 return attr;
321 void vBase::AddAttr(vAttrPtr attr)
323 // Trace trace("vBase::AddAttr");
325 if( !attr.Get() ) {
326 // trace.log("attribute contains no data, skipping");
327 return;
330 b_vformat_add_attribute(m_format, attr.Extract());
333 void vBase::AddValue(vAttrPtr &attr, const char *value)
335 // Trace trace("vBase::AddValue");
336 if( !attr.Get() ) {
337 // trace.log("attribute pointer contains no data, skipping");
338 return;
341 if( strlen(value) == 0 ) {
342 trace.log("attribute value is empty, skipping");
343 return;
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");
352 if( !attr.Get() ) {
353 // trace.log("attribute pointer contains no data, skipping");
354 return;
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");
367 if( !attr.Get() ) {
368 // trace.log("attribute pointer contains no data, skipping");
369 return;
372 if( strlen(value) == 0 ) {
373 trace.log("parameter value is empty, skipping");
374 return;
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() )
386 return;
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());
393 AddAttr(cat);
396 std::string vBase::GetAttr(const char *attrname, const char *block)
398 // Trace trace("vBase::GetAttr");
399 // trace.logf("getting attr: %s", attrname);
401 std::string ret;
402 const char *value = 0;
404 bool needs_freeing = false;
406 b_VFormatAttribute *attr = b_vformat_find_attribute(m_format, attrname, 0, block);
407 if( attr ) {
408 if( b_vformat_attribute_is_single_valued(attr) ) {
409 value = b_vformat_attribute_get_value(attr);
410 needs_freeing = true;
412 else {
413 // FIXME, this is hardcoded
414 value = b_vformat_attribute_get_nth_value(attr, 0);
418 if( value )
419 ret = value;
421 if( needs_freeing )
422 g_free((char *)value);
424 // trace.logf("attr value: %s", ret.c_str());
425 return ret;
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);
438 if( attr ) {
439 if( b_vformat_attribute_is_single_valued(attr) ) {
440 value = b_vformat_attribute_get_value(attr);
441 needs_freeing = true;
442 } else {
443 // nasty, but avoids tweaking vformat.
444 int idx = 0;
445 do {
446 value = b_vformat_attribute_get_nth_value(attr, idx++);
447 if( value ) {
448 ret.push_back(value);
450 } while( value );
454 if( needs_freeing )
455 g_free((char *)value);
457 return ret;
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 ) {
474 return tokens;
477 while( 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));
485 } else {
486 tokens.push_back("");
488 } else {
489 tokens.push_back("");
491 pos = delimPos + 1;
492 } else {
493 if( std::string::npos != tokenPos ){
494 tokens.push_back(str.substr(pos));
495 } else {
496 tokens.push_back("");
498 break;
501 return tokens;
504 std::string vBase::ToStringList(const std::vector<std::string> &list, const char delim)
506 std::string str;
507 for( unsigned int idx = 0; idx < list.size(); idx++ ) {
508 if( idx ) {
509 str += delim;
511 str += list[idx];
513 return str;
516 }} // namespace Barry::Sync