OpenSync  0.22
opensync_time.c
1 /*
2  * libopensync - A synchronization framework
3  * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org>
4  * Copyright (C) 2006 Daniel Gollub <dgollub@suse.de>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #include <time.h>
23 
24 #include "opensync.h"
25 #include "opensync_internals.h"
26 
27 /*
28  * On solaris no timegm function exists,
29  * we must implement it here
30  */
31 #ifdef SOLARIS
32 time_t timegm(struct tm *t)
33 {
34  time_t tl, tb;
35  struct tm *tg;
36 
37  tl = mktime (t);
38  if (tl == -1)
39  {
40  t->tm_hour--;
41  tl = mktime (t);
42  if (tl == -1)
43  return -1; /* can't deal with output from strptime */
44  tl += 3600;
45  }
46  tg = gmtime (&tl);
47  tg->tm_isdst = 0;
48  tb = mktime (tg);
49  if (tb == -1)
50  {
51  tg->tm_hour--;
52  tb = mktime (tg);
53  if (tb == -1)
54  return -1; /* can't deal with output from gmtime */
55  tb += 3600;
56  }
57  return (tl - (tb - tl));
58 }
59 #endif
60 
61 /* Floating Timestamps...... (handle tzid!) */
62 
63 /*
64  * Time formatting helper
65  */
66 
72 static char *osync_time_timestamp_remove_dash(const char *timestamp) {
73  int i, len;
74  GString *str = g_string_new("");
75 
76  len = strlen(timestamp);
77 
78  for (i=0; i < len; i++) {
79  if (timestamp[i] == '-')
80  continue;
81 
82  if (timestamp[i] == ':')
83  continue;
84 
85  str = g_string_append_c(str, timestamp[i]);
86  }
87 
88  return (char*) g_string_free(str, FALSE);
89 }
90 
96 char *osync_time_timestamp(const char *vtime) {
97  osync_trace(TRACE_ENTRY, "%s(%s)", __func__, vtime);
98 
99  char *timestamp;
100 
101  timestamp = osync_time_timestamp_remove_dash(vtime);
102 
103  osync_trace(TRACE_EXIT, "%s: %s", __func__, timestamp);
104  return timestamp;
105 }
106 
112 char *osync_time_datestamp(const char *vtime) {
113  osync_trace(TRACE_ENTRY, "%s(%s)", __func__, vtime);
114 
115  char *tmp;
116  const char *p;
117  GString *str = g_string_new ("");
118 
119  tmp = osync_time_timestamp_remove_dash(vtime);
120 
121  for (p=tmp; *p && *p != 'T'; p++)
122  str = g_string_append_c (str, *p);
123 
124  free(tmp);
125 
126  osync_trace(TRACE_EXIT, "%s: %s", __func__, str->str);
127  return (char*) g_string_free(str, FALSE);
128 }
129 
134 osync_bool osync_time_isdate(const char *vtime) {
135 
136  int year, month, day;
137 
138  if (strstr(vtime, "T"))
139  return FALSE;
140 
141  /* YYYYMMDD */
142  if (sscanf(vtime, "%04d%02d%02d", &year, &month, &day) != 3)
143  return FALSE;
144 
145  return TRUE;
146 }
147 
152 osync_bool osync_time_isutc(const char *vtime) {
153 
154  if (!strstr(vtime, "Z"))
155  return FALSE;
156 
157  return TRUE;
158 }
159 
172 /*
173 char *osync_time_set_vtime(const char *vtime, const char *time, osync_bool is_utc) {
174  osync_trace(TRACE_ENTRY, "%s(%s, %s)", __func__, vtime, time);
175 
176  char *tmp = NULL;
177 
178  // TODO
179 
180  osync_trace(TRACE_EXIT, "%s: %s", __func__, tmp);
181  return tmp;
182 }
183 */
184 
185 /*
186  * Timetype helper
187  */
188 
194 struct tm *osync_time_vtime2tm(const char *vtime) {
195 
196  osync_trace(TRACE_ENTRY, "%s(%s)", __func__, vtime);
197 
198  struct tm *utime = g_malloc0(sizeof(struct tm));
199 
200  utime->tm_year = 0;
201  utime->tm_mon = 0;
202  utime->tm_mday = 0;
203  utime->tm_hour = 0;
204  utime->tm_min = 0;
205  utime->tm_sec = 0;
206 
207  sscanf(vtime, "%04d%02d%02dT%02d%02d%02d%*01c",
208  &(utime->tm_year), &(utime->tm_mon), &(utime->tm_mday),
209  &(utime->tm_hour), &(utime->tm_min), &(utime->tm_sec));
210 
211  utime->tm_year -= 1900;
212  utime->tm_mon -= 1;
213 
214  /* isdst is handled by tz offset calcualtion */
215  utime->tm_isdst = -1;
216 
217  osync_trace(TRACE_EXIT, "%s", __func__);
218  return utime;
219 }
220 
230 char *osync_time_tm2vtime(const struct tm *time, osync_bool is_utc) {
231 
232  osync_trace(TRACE_ENTRY, "%s(%p, %i)", __func__, time, is_utc);
233  GString *vtime = g_string_new("");
234 
235  g_string_printf(vtime, "%04d%02d%02dT%02d%02d%02d",
236  time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
237  time->tm_hour, time->tm_min, time->tm_sec);
238 
239  if (is_utc)
240  vtime = g_string_append(vtime, "Z");
241 
242  osync_trace(TRACE_EXIT, "%s: %s", __func__, vtime->str);
243  return g_string_free(vtime, FALSE);
244 }
245 
252 time_t osync_time_vtime2unix(const char *vtime, int offset) {
253 
254  osync_trace(TRACE_ENTRY, "%s(%s, %i)", __func__, vtime, offset);
255  struct tm *utime = NULL;
256  time_t timestamp;
257  char *utc = NULL;
258 
259  utc = osync_time_vtime2utc(vtime, offset);
260  utime = osync_time_vtime2tm(utc);
261 
262  timestamp = osync_time_tm2unix(utime);
263 
264  g_free(utc);
265  g_free(utime);
266 
267  osync_trace(TRACE_EXIT, "%s: %lu", __func__, timestamp);
268  return timestamp;
269 }
270 
276 char *osync_time_unix2vtime(const time_t *timestamp) {
277 
278  osync_trace(TRACE_ENTRY, "%s(%lu)", __func__, *timestamp);
279  char *vtime;
280  struct tm utc;
281 
282  gmtime_r(timestamp, &utc);
283  vtime = osync_time_tm2vtime(&utc, TRUE);
284 
285  osync_trace(TRACE_EXIT, "%s: %s", __func__, vtime);
286  return vtime;
287 }
288 
294 time_t osync_time_tm2unix(const struct tm *tmtime) {
295 
296  time_t timestamp;
297  struct tm *tmp = g_malloc0(sizeof(struct tm));
298 
299  memcpy(tmp, tmtime, sizeof(struct tm));
300 
301  timestamp = timegm(tmp);
302 
303  g_free(tmp);
304 
305  return timestamp;
306 }
307 
313 struct tm *osync_time_unix2tm(const time_t *timestamp) {
314 
315  struct tm *ptr_tm;
316  struct tm tmtime;
317 
318  gmtime_r(timestamp, &tmtime);
319 
320  ptr_tm = &tmtime;
321 
322  return ptr_tm;
323 }
324 
325 /*
326  * Timezone helper
327  */
328 
334 int osync_time_timezone_diff(const struct tm *time) {
335  osync_trace(TRACE_ENTRY, "%s()", __func__);
336 
337  struct tm ltime, utime;
338  unsigned int lsecs, usecs;
339  long zonediff;
340  time_t timestamp;
341 
342  timestamp = osync_time_tm2unix(time);
343 
344  tzset();
345 
346  localtime_r(&timestamp, &ltime);
347  gmtime_r(&timestamp, &utime);
348 
349  lsecs = 3600 * ltime.tm_hour + 60 * ltime.tm_min + ltime.tm_sec;
350  usecs = 3600 * utime.tm_hour + 60 * utime.tm_min + utime.tm_sec;
351 
352  zonediff = lsecs - usecs;
353 
354  /* check for different day */
355  if (utime.tm_mday != ltime.tm_mday) {
356  if (utime.tm_mday < ltime.tm_mday)
357  zonediff += 24 * 3600;
358  else
359  zonediff -= 24 * 3600;
360  }
361 
362  osync_trace(TRACE_EXIT, "%s: %i", __func__, zonediff);
363  return zonediff;
364 }
365 
373 struct tm *osync_time_tm2utc(const struct tm *ltime, int offset) {
374 
375  osync_trace(TRACE_ENTRY, "%s(%p, %i)", __func__, ltime, offset);
376  struct tm *tmtime = g_malloc0(sizeof(struct tm));
377 
378  tmtime->tm_year = ltime->tm_year;
379  tmtime->tm_mon = ltime->tm_mon;
380  tmtime->tm_mday = ltime->tm_mday;
381  tmtime->tm_hour = ltime->tm_hour;
382  tmtime->tm_min = ltime->tm_min;
383  tmtime->tm_sec = ltime->tm_sec;
384 
385  /* in seconds - to have a exactly timezone diff like -13.5h */
386  tmtime->tm_hour -= offset / 3600;
387  tmtime->tm_min -= (offset % 3600) / 60;
388 
389  if (tmtime->tm_hour > 23 || tmtime->tm_hour < 0) {
390 
391  if (tmtime->tm_hour < 0) {
392  tmtime->tm_hour += 24;
393  tmtime->tm_mday -= 1;
394  } else {
395  tmtime->tm_hour -= 24;
396  tmtime->tm_mday += 1;
397  }
398  }
399 
400  osync_trace(TRACE_EXIT, "%s: %p", __func__, tmtime);
401  return tmtime;
402 }
403 
411 struct tm *osync_time_tm2localtime(const struct tm *utime, int offset) {
412 
413  struct tm *tmtime = g_malloc0(sizeof(struct tm));
414 
415  tmtime->tm_year = utime->tm_year;
416  tmtime->tm_mon = utime->tm_mon;
417  tmtime->tm_mday = utime->tm_mday;
418  tmtime->tm_hour = utime->tm_hour;
419  tmtime->tm_min = utime->tm_min;
420  tmtime->tm_sec = utime->tm_sec;
421 
422  tmtime->tm_hour += offset / 3600;
423  tmtime->tm_min += (offset % 3600) / 60;
424 
425  if (tmtime->tm_hour > 23 || tmtime->tm_hour < 0) {
426 
427  if (tmtime->tm_hour < 0) {
428  tmtime->tm_mday -= 1;
429  tmtime->tm_hour += 24;
430  } else {
431  tmtime->tm_mday += 1;
432  tmtime->tm_hour -= 24;
433  }
434  }
435 
436  return tmtime;
437 }
438 
445 char *osync_time_vtime2utc(const char* localtime, int offset) {
446  osync_trace(TRACE_ENTRY, "%s(%s)", __func__, localtime);
447 
448  char *utc = NULL;
449  struct tm *tm_local = NULL, *tm_utc = NULL;
450 
451  if (strstr(localtime, "Z")) {
452  utc = strdup(localtime);
453  goto end;
454  }
455 
456  tm_local = osync_time_vtime2tm(localtime);
457  tm_utc = osync_time_tm2utc(tm_local, offset);
458  utc = osync_time_tm2vtime(tm_utc, TRUE);
459 
460  g_free(tm_local);
461 // FIXME is it really a memory leak?
462 // g_free(tm_utc);
463 
464 end:
465  osync_trace(TRACE_EXIT, "%s: %s", __func__, utc);
466  return utc;
467 }
468 
474 char *osync_time_vtime2localtime(const char* utc, int offset) {
475 
476  char *localtime = NULL;
477  struct tm *tm_local = NULL, *tm_utc = NULL;
478 
479  if (!strstr(utc, "Z")) {
480  localtime = strdup(utc);
481  return localtime;
482  }
483 
484  tm_utc = osync_time_vtime2tm(utc);
485  tm_local = osync_time_tm2localtime(tm_utc, offset);
486  localtime = osync_time_tm2vtime(tm_local, FALSE);
487 
488  g_free(tm_local);
489  g_free(tm_utc);
490 
491  return localtime;
492 }
493 
494 
495 
496 /* XXX This functions should only be used as workaround for plugins which
497  only supports localtime without any timezone information. */
498 
502 const char *_time_attr[] = {
503  "DTSTART:",
504  "DTEND:",
505  "DTSTAMP:",
506  "AALARM:",
507  "DALARM:",
508  "DUE:",
509  NULL
510 };
511 
518 static void _convert_time_field(GString *entry, const char *field, osync_bool toUTC) {
519 
520  int i, tzdiff;
521  char *res = NULL;
522  char *new_stamp = NULL;
523 
524  GString *stamp = g_string_new("");
525 
526  if ((res = strstr(entry->str, field))) {
527  res += strlen(field);
528 
529  for (i=0; res[i] != '\n' && res[i] != '\r'; i++)
530  stamp = g_string_append_c(stamp, res[i]);
531 
532  gssize pos = res - entry->str;
533  entry = g_string_erase(entry, pos, i);
534 
535  // Get System offset to UTC
536  struct tm *tm_stamp = osync_time_vtime2tm(stamp->str);
537  tzdiff = osync_time_timezone_diff(tm_stamp);
538  g_free(tm_stamp);
539 
540  if (toUTC)
541  new_stamp = osync_time_vtime2utc(stamp->str, tzdiff);
542  else
543  new_stamp = osync_time_vtime2localtime(stamp->str, tzdiff);
544 
545  entry = g_string_insert(entry, pos, new_stamp);
546  g_free(new_stamp);
547  }
548 }
549 
556 char *_convert_entry(const char *vcal, osync_bool toUTC) {
557 
558  int i = 0;
559  GString *new_entry = g_string_new(vcal);
560 
561  for (i=0; _time_attr[i] != NULL; i++)
562  _convert_time_field(new_entry, _time_attr[i], toUTC);
563 
564  return g_string_free(new_entry, FALSE);
565 }
566 
572 char *osync_time_vcal2localtime(const char *vcal) {
573 
574  return _convert_entry(vcal, FALSE);
575 }
576 
582 char *osync_time_vcal2utc(const char *vcal) {
583 
584  return _convert_entry(vcal, TRUE);
585 }
586 
593 char *osync_time_sec2alarmdu(int seconds) {
594 
595  osync_trace(TRACE_ENTRY, "%s(%i)", __func__, seconds);
596 
597  char *tmp = NULL;
598  char *prefix = NULL;
599 
600  if (!seconds) {
601  tmp = g_strdup("PT0S");
602  goto end;
603  }
604 
605  if (seconds > 0) {
606  prefix = g_strdup("P");
607  } else {
608  prefix = g_strdup("-P");
609  seconds *= -1;
610  }
611 
612  // Days
613  if (!(seconds % (3600 * 24))) {
614  tmp = g_strdup_printf("%s%iD", prefix, seconds / (3600 * 24));
615  goto end;
616  }
617 
618  // Hours
619  if (!(seconds % 3600)) {
620  tmp = g_strdup_printf("%sT%iH", prefix, seconds / 3600);
621  goto end;
622  }
623 
624  // Minutes
625  if (!(seconds % 60) && seconds < 3600) {
626  tmp = g_strdup_printf("%sT%iM", prefix, seconds / 60);
627  goto end;
628  }
629 
630  // Seconds
631  if (seconds < 60) {
632  tmp = g_strdup_printf("%sT%iS", prefix, seconds);
633  goto end;
634  }
635 
636  if (seconds > 60)
637  tmp = g_strdup_printf("%sT%iM", prefix, seconds / 60);
638 
639  if (seconds > 3600)
640  tmp = g_strdup_printf("%sT%iH%iM", prefix, seconds / 3600,
641  (seconds % 3600) / 60);
642 
643  if (seconds > (3600 * 24))
644  tmp = g_strdup_printf("%s%iDT%iH%iM", prefix, seconds / (3600 * 24),
645  seconds % (3600 * 24) / 3600,
646  ((seconds % (3600 * 24) % 3600)) / 60);
647 
648 end:
649  g_free(prefix);
650 
651  osync_trace(TRACE_EXIT, "%s: %s", __func__, tmp);
652  return tmp;
653 }
654 
663 int osync_time_alarmdu2sec(const char *alarm) {
664 
665  osync_trace(TRACE_ENTRY, "%s(%s)", __func__, alarm);
666 
667  int i, secs, digits;
668  int is_digit = 0;
669  int sign = 1; // when ical stamp doesn't start with '-' => seconds after event
670  int days = 0, weeks = 0, hours = 0, minutes = 0, seconds = 0;
671 
672  for (i=0; i < (int) strlen(alarm); i++) {
673 
674  switch (alarm[i]) {
675  case '-':
676  sign = -1; // seconds before event - change the sign
677  case 'P':
678  case 'T':
679  is_digit = 0;
680  break;
681  case 'W':
682  is_digit = 0;
683  weeks = digits;
684  break;
685  case 'D':
686  is_digit = 0;
687  days = digits;
688  break;
689  case 'H':
690  is_digit = 0;
691  hours = digits;
692  break;
693  case 'M':
694  is_digit = 0;
695  minutes = digits;
696  break;
697  case 'S':
698  is_digit = 0;
699  seconds = digits;
700  break;
701  case '0':
702  case '1':
703  case '2':
704  case '3':
705  case '4':
706  case '5':
707  case '6':
708  case '7':
709  case '8':
710  case '9':
711  if (is_digit)
712  break;
713 
714  sscanf((char*)(alarm+i),"%d",&digits);
715  is_digit = 1;
716  break;
717  }
718  }
719 
720  secs = (weeks * 7 * 24 * 3600) + (days * 24 * 3600) + (hours * 3600) + (minutes * 60) + seconds;
721 
722  secs = secs * sign; // change sign if the alarm is in seconds before event (leading '-')
723 
724  osync_trace(TRACE_EXIT, "%s: %i", __func__, secs);
725  return secs;
726 }
727 
728 /*
729  * Timezone ID helper
730  */
731 
737 int osync_time_str2wday(const char *swday) {
738 
739  int weekday = -1;
740 
741  if (!strcmp(swday, "SU"))
742  weekday = 0;
743  else if (!strcmp(swday, "MO"))
744  weekday = 1;
745  else if (!strcmp(swday, "TU"))
746  weekday = 2;
747  else if (!strcmp(swday, "WE"))
748  weekday = 3;
749  else if (!strcmp(swday, "TH"))
750  weekday = 4;
751  else if (!strcmp(swday, "FR"))
752  weekday = 5;
753  else if (!strcmp(swday, "SA"))
754  weekday = 6;
755 
756  return weekday;
757 }
758 
769 struct tm *osync_time_relative2tm(const char *byday, const int bymonth, const int year) {
770 
771  struct tm *datestamp = g_malloc0(sizeof(struct tm));
772  char weekday[3];
773  int first_wday = 0, last_wday = 0;
774  int daymod, mday, searched_wday;
775 
776  sscanf(byday, "%d%s", &daymod, weekday);
777  weekday[2] = '\0';
778 
779  searched_wday = osync_time_str2wday(weekday);
780 
781  datestamp->tm_year = year - 1900;
782  datestamp->tm_mon = bymonth - 1;
783  datestamp->tm_mday = 0;
784  datestamp->tm_hour = 0;
785  datestamp->tm_min = 0;
786  datestamp->tm_sec = 0;
787  datestamp->tm_isdst = -1;
788 
789  for (mday = 0; mday <= 31; mday++) {
790  datestamp->tm_mday = mday;
791  mktime(datestamp);
792 
793  if (datestamp->tm_wday == searched_wday) {
794  if (!first_wday)
795  first_wday = searched_wday;
796 
797  last_wday = searched_wday;
798  }
799  }
800 
801  if (daymod > 0)
802  datestamp->tm_mday = first_wday + (7 * (daymod - 1));
803  else
804  datestamp->tm_mday = last_wday - (7 * (daymod - 1));
805 
806  mktime(datestamp);
807 
808  return datestamp;
809 }
810 
816 int osync_time_utcoffset2sec(const char *offset) {
817  osync_trace(TRACE_ENTRY, "%s(%s)", __func__, offset);
818 
819  char csign = 0;
820  int seconds = 0, sign = 1;
821  int hours = 0, minutes = 0;
822 
823  sscanf(offset, "%c%2d%2d", &csign, &hours, &minutes);
824 
825  if (csign == '-')
826  sign = -1;
827 
828  seconds = (hours * 3600 + minutes * 60) * sign;
829 
830  osync_trace(TRACE_EXIT, "%s: %i", __func__, seconds);
831  return seconds;
832 }
833 
841 struct tm *osync_time_dstchange(xmlNode *dstNode) {
842 
843  int month;
844  struct tm *dst_change = NULL, *tm_started = NULL;
845  char *started = NULL, *rule = NULL, *byday = NULL;
846 
847  xmlNode *current = osxml_get_node(dstNode, "DateStarted");
848  started = (char*) xmlNodeGetContent(current);
849  tm_started = osync_time_vtime2tm(started);
850 
851  g_free(started);
852 
853  current = osxml_get_node(dstNode, "RecurrenceRule");
854  current = current->children;
855 
856  while (current) {
857  rule = (char *) xmlNodeGetContent(current);
858 
859  if (strstr(rule, "BYDAY="))
860  byday = g_strdup(rule + 6);
861  else if (strstr(rule, "BYMONTH="))
862  sscanf(rule, "BYMONTH=%d", &month);
863 
864  g_free(rule);
865 
866  current = current->next;
867  }
868 
869  dst_change = osync_time_relative2tm(byday, month, tm_started->tm_year + 1900);
870 
871  g_free(byday);
872 
873  dst_change->tm_hour = tm_started->tm_hour;
874  dst_change->tm_min = tm_started->tm_min;
875 
876  g_free(tm_started);
877 
878  return dst_change;
879 }
880 
887 osync_bool osync_time_isdst(const char *vtime, xmlNode *tzid) {
888 
889  osync_trace(TRACE_ENTRY, "%s(%s, %p)", __func__, vtime, tzid);
890 
891  int year;
892  /* KH: Fails with -Werror=unused-but-set-variable as newyear and newyear_t aren't used anywhere
893  char *newyear = NULL;
894  time_t newyear_t, timestamp;
895  */
896  time_t timestamp;
897  struct tm *std_changetime, *dst_changetime;
898  time_t dstStamp, stdStamp;
899  xmlNode *current = NULL;
900 
901  sscanf(vtime, "%4d%*2d%*2dT%*2d%*d%*2d%*c", &year);
902 
903  /* KH: See comment above
904  newyear = g_strdup_printf("%4d0101T000000", year);
905  newyear_t = osync_time_vtime2unix(newyear, 0);
906  */
907  timestamp = osync_time_vtime2unix(vtime, 0);
908 
909  /* Handle XML Timezone field */
910  current = osxml_get_node(tzid, "Standard");
911  std_changetime = osync_time_dstchange(current);
912 
913  current = osxml_get_node(tzid, "DaylightSavings");
914  dst_changetime = osync_time_dstchange(current);
915 
916  /* determine in which timezone is vtime */
917  dstStamp = osync_time_tm2unix(dst_changetime);
918  stdStamp = osync_time_tm2unix(std_changetime);
919 
920  if (timestamp > stdStamp && timestamp < dstStamp) {
921  osync_trace(TRACE_EXIT, "%s: FALSE (Standard Timezone)", __func__);
922  return FALSE;
923  }
924 
925  osync_trace(TRACE_EXIT, "%s: TRUE (Daylight Saving Timezone)", __func__);
926  return TRUE;
927 }
928 
936 int osync_time_tzoffset(const char *vtime, xmlNode *tz) {
937 
938  osync_trace(TRACE_ENTRY, "%s(%s, %p)", __func__, vtime, tz);
939 
940  int seconds;
941  char *offset = NULL;
942  xmlNode *current = NULL;
943 
944  if (osync_time_isdst(vtime, tz))
945  current = osxml_get_node(tz, "DaylightSavings");
946  else
947  current = osxml_get_node(tz, "Standard");
948 
949  offset = osxml_find_node(current, "TZOffsetFrom");
950  seconds = osync_time_utcoffset2sec(offset);
951 
952  osync_trace(TRACE_EXIT, "%s: %i", __func__, seconds);
953  return seconds;
954 }
955 
961 char *osync_time_tzid(xmlNode *tz) {
962  osync_trace(TRACE_ENTRY, "%s(%p)", __func__, tz);
963 
964  char *id = NULL;
965 
966  id = osxml_find_node(tz, "TimezoneID");
967 
968  osync_trace(TRACE_EXIT, "%s: %s", __func__, id);
969  return id;
970 }
971 
977 char *osync_time_tzlocation(xmlNode *tz) {
978  osync_trace(TRACE_ENTRY, "%s(%p)", __func__, tz);
979 
980  char *location = NULL;
981 
982  location = osxml_find_node(tz, "TimezoneLocation");
983 
984  osync_trace(TRACE_EXIT, "%s: %s", __func__, location);
985  return location;
986 }
987 
994 xmlNode *osync_time_tzinfo(xmlNode *root, const char *tzid) {
995 
996  osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, root, tzid);
997 
998  int numnodes, i;
999  char *tzinfo_tzid = NULL;
1000 
1001  xmlNode *tz = NULL;
1002  xmlNodeSet *nodes = NULL;
1003  xmlXPathObject *xobj = NULL;
1004 
1005  /* search matching Timezone information */
1006  xobj = osxml_get_nodeset(root->doc, "/vcal/Timezone");
1007  nodes = xobj->nodesetval;
1008  numnodes = (nodes) ? nodes->nodeNr : 0;
1009 
1010  osync_trace(TRACE_INTERNAL, "Found %i Timezone field(s)", numnodes);
1011 
1012  if (!numnodes)
1013  goto noresult;
1014 
1015 
1016  for (i=0; i < numnodes; i++) {
1017  tz = nodes->nodeTab[i];
1018  tzinfo_tzid = osync_time_tzid(tz);
1019 
1020  if (!tzinfo_tzid) {
1021  g_free(tzinfo_tzid);
1022  tz = NULL;
1023  continue;
1024  }
1025 
1026  if (!strcmp(tzinfo_tzid, tzid))
1027  break;
1028  }
1029 
1030  g_free(tzinfo_tzid);
1031 
1032  if (!tz)
1033  goto noresult;
1034 
1035 
1036  osync_trace(TRACE_EXIT, "%s: %p", __func__, tz);
1037  return tz;
1038 
1039 noresult:
1040  osync_trace(TRACE_EXIT, "%s: No matching Timezone node found. Seems to be a be a floating timestamp.", __func__);
1041  return NULL;
1042 }
1043 
1050 char *osync_time_tzlocal2utc(xmlNode *root, const char *field) {
1051  osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, root, field);
1052 
1053  int offset = 0;
1054  char *utc = NULL, *field_tzid = NULL, *vtime = NULL;
1055  xmlNode *tz = NULL;
1056 
1057  /*
1058  node = osxml_get_node(root, field);
1059  if (!node) {
1060  osync_trace(TRACE_EXIT, "%s: field \"%s\" not found", __func__, field);
1061  return NULL;
1062  }
1063  */
1064 
1065  field_tzid = osync_time_tzid(root);
1066  if (!field_tzid) {
1067  g_free(field_tzid);
1068  goto noresult;
1069  }
1070 
1071  tz = osync_time_tzinfo(root, field_tzid);
1072  g_free(field_tzid);
1073 
1074  if (!tz)
1075  goto noresult;
1076 
1077  vtime = osxml_find_node(root, "Content");
1078 
1079  /* Handle UTC offset like 13.5h */
1080  offset = osync_time_tzoffset(vtime, tz);
1081  struct tm *ttm = osync_time_vtime2tm(vtime);
1082  ttm->tm_hour -= offset / 3600;
1083  ttm->tm_min -= (offset % 3600) / 60;
1084  mktime(ttm);
1085  utc = osync_time_tm2vtime(ttm, TRUE);
1086 
1087  g_free(vtime);
1088  g_free(ttm);
1089 
1090  osync_trace(TRACE_EXIT, "%s: %s", __func__, utc);
1091  return utc;
1092 
1093 noresult:
1094  osync_trace(TRACE_EXIT, "%s: No matching Timezone node is found.", __func__);
1095  return NULL;
1096 }
1097 
void osync_trace(OSyncTraceType type, const char *message,...)
Used for tracing the application.