OpenSync 0.22
|
00001 /* 00002 * libopensync - A synchronization framework 00003 * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org> 00004 * Copyright (C) 2006 Daniel Gollub <dgollub@suse.de> 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 * 00020 */ 00021 00022 #include <time.h> 00023 00024 #include "opensync.h" 00025 #include "opensync_internals.h" 00026 00027 /* 00028 * On solaris no timegm function exists, 00029 * we must implement it here 00030 */ 00031 #ifdef SOLARIS 00032 time_t timegm(struct tm *t) 00033 { 00034 time_t tl, tb; 00035 struct tm *tg; 00036 00037 tl = mktime (t); 00038 if (tl == -1) 00039 { 00040 t->tm_hour--; 00041 tl = mktime (t); 00042 if (tl == -1) 00043 return -1; /* can't deal with output from strptime */ 00044 tl += 3600; 00045 } 00046 tg = gmtime (&tl); 00047 tg->tm_isdst = 0; 00048 tb = mktime (tg); 00049 if (tb == -1) 00050 { 00051 tg->tm_hour--; 00052 tb = mktime (tg); 00053 if (tb == -1) 00054 return -1; /* can't deal with output from gmtime */ 00055 tb += 3600; 00056 } 00057 return (tl - (tb - tl)); 00058 } 00059 #endif 00060 00061 /* Floating Timestamps...... (handle tzid!) */ 00062 00063 /* 00064 * Time formatting helper 00065 */ 00066 00072 static char *osync_time_timestamp_remove_dash(const char *timestamp) { 00073 int i, len; 00074 GString *str = g_string_new(""); 00075 00076 len = strlen(timestamp); 00077 00078 for (i=0; i < len; i++) { 00079 if (timestamp[i] == '-') 00080 continue; 00081 00082 if (timestamp[i] == ':') 00083 continue; 00084 00085 str = g_string_append_c(str, timestamp[i]); 00086 } 00087 00088 return (char*) g_string_free(str, FALSE); 00089 } 00090 00096 char *osync_time_timestamp(const char *vtime) { 00097 osync_trace(TRACE_ENTRY, "%s(%s)", __func__, vtime); 00098 00099 char *timestamp; 00100 00101 timestamp = osync_time_timestamp_remove_dash(vtime); 00102 00103 osync_trace(TRACE_EXIT, "%s: %s", __func__, timestamp); 00104 return timestamp; 00105 } 00106 00112 char *osync_time_datestamp(const char *vtime) { 00113 osync_trace(TRACE_ENTRY, "%s(%s)", __func__, vtime); 00114 00115 char *tmp; 00116 const char *p; 00117 GString *str = g_string_new (""); 00118 00119 tmp = osync_time_timestamp_remove_dash(vtime); 00120 00121 for (p=tmp; *p && *p != 'T'; p++) 00122 str = g_string_append_c (str, *p); 00123 00124 free(tmp); 00125 00126 osync_trace(TRACE_EXIT, "%s: %s", __func__, str->str); 00127 return (char*) g_string_free(str, FALSE); 00128 } 00129 00134 osync_bool osync_time_isdate(const char *vtime) { 00135 00136 int year, month, day; 00137 00138 if (strstr(vtime, "T")) 00139 return FALSE; 00140 00141 /* YYYYMMDD */ 00142 if (sscanf(vtime, "%04d%02d%02d", &year, &month, &day) != 3) 00143 return FALSE; 00144 00145 return TRUE; 00146 } 00147 00152 osync_bool osync_time_isutc(const char *vtime) { 00153 00154 if (!strstr(vtime, "Z")) 00155 return FALSE; 00156 00157 return TRUE; 00158 } 00159 00172 /* 00173 char *osync_time_set_vtime(const char *vtime, const char *time, osync_bool is_utc) { 00174 osync_trace(TRACE_ENTRY, "%s(%s, %s)", __func__, vtime, time); 00175 00176 char *tmp = NULL; 00177 00178 // TODO 00179 00180 osync_trace(TRACE_EXIT, "%s: %s", __func__, tmp); 00181 return tmp; 00182 } 00183 */ 00184 00185 /* 00186 * Timetype helper 00187 */ 00188 00194 struct tm *osync_time_vtime2tm(const char *vtime) { 00195 00196 osync_trace(TRACE_ENTRY, "%s(%s)", __func__, vtime); 00197 00198 struct tm *utime = g_malloc0(sizeof(struct tm)); 00199 00200 utime->tm_year = 0; 00201 utime->tm_mon = 0; 00202 utime->tm_mday = 0; 00203 utime->tm_hour = 0; 00204 utime->tm_min = 0; 00205 utime->tm_sec = 0; 00206 00207 sscanf(vtime, "%04d%02d%02dT%02d%02d%02d%*01c", 00208 &(utime->tm_year), &(utime->tm_mon), &(utime->tm_mday), 00209 &(utime->tm_hour), &(utime->tm_min), &(utime->tm_sec)); 00210 00211 utime->tm_year -= 1900; 00212 utime->tm_mon -= 1; 00213 00214 /* isdst is handled by tz offset calcualtion */ 00215 utime->tm_isdst = -1; 00216 00217 osync_trace(TRACE_EXIT, "%s", __func__); 00218 return utime; 00219 } 00220 00230 char *osync_time_tm2vtime(const struct tm *time, osync_bool is_utc) { 00231 00232 osync_trace(TRACE_ENTRY, "%s(%p, %i)", __func__, time, is_utc); 00233 GString *vtime = g_string_new(""); 00234 00235 g_string_printf(vtime, "%04d%02d%02dT%02d%02d%02d", 00236 time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, 00237 time->tm_hour, time->tm_min, time->tm_sec); 00238 00239 if (is_utc) 00240 vtime = g_string_append(vtime, "Z"); 00241 00242 osync_trace(TRACE_EXIT, "%s: %s", __func__, vtime->str); 00243 return g_string_free(vtime, FALSE); 00244 } 00245 00252 time_t osync_time_vtime2unix(const char *vtime, int offset) { 00253 00254 osync_trace(TRACE_ENTRY, "%s(%s, %i)", __func__, vtime, offset); 00255 struct tm *utime = NULL; 00256 time_t timestamp; 00257 char *utc = NULL; 00258 00259 utc = osync_time_vtime2utc(vtime, offset); 00260 utime = osync_time_vtime2tm(utc); 00261 00262 timestamp = osync_time_tm2unix(utime); 00263 00264 g_free(utc); 00265 g_free(utime); 00266 00267 osync_trace(TRACE_EXIT, "%s: %lu", __func__, timestamp); 00268 return timestamp; 00269 } 00270 00276 char *osync_time_unix2vtime(const time_t *timestamp) { 00277 00278 osync_trace(TRACE_ENTRY, "%s(%lu)", __func__, *timestamp); 00279 char *vtime; 00280 struct tm utc; 00281 00282 gmtime_r(timestamp, &utc); 00283 vtime = osync_time_tm2vtime(&utc, TRUE); 00284 00285 osync_trace(TRACE_EXIT, "%s: %s", __func__, vtime); 00286 return vtime; 00287 } 00288 00294 time_t osync_time_tm2unix(const struct tm *tmtime) { 00295 00296 time_t timestamp; 00297 struct tm *tmp = g_malloc0(sizeof(struct tm)); 00298 00299 memcpy(tmp, tmtime, sizeof(struct tm)); 00300 00301 timestamp = timegm(tmp); 00302 00303 g_free(tmp); 00304 00305 return timestamp; 00306 } 00307 00313 struct tm *osync_time_unix2tm(const time_t *timestamp) { 00314 00315 struct tm *ptr_tm; 00316 struct tm tmtime; 00317 00318 gmtime_r(timestamp, &tmtime); 00319 00320 ptr_tm = &tmtime; 00321 00322 return ptr_tm; 00323 } 00324 00325 /* 00326 * Timezone helper 00327 */ 00328 00334 int osync_time_timezone_diff(const struct tm *time) { 00335 osync_trace(TRACE_ENTRY, "%s()", __func__); 00336 00337 struct tm ltime, utime; 00338 unsigned int lsecs, usecs; 00339 long zonediff; 00340 time_t timestamp; 00341 00342 timestamp = osync_time_tm2unix(time); 00343 00344 tzset(); 00345 00346 localtime_r(×tamp, <ime); 00347 gmtime_r(×tamp, &utime); 00348 00349 lsecs = 3600 * ltime.tm_hour + 60 * ltime.tm_min + ltime.tm_sec; 00350 usecs = 3600 * utime.tm_hour + 60 * utime.tm_min + utime.tm_sec; 00351 00352 zonediff = lsecs - usecs; 00353 00354 /* check for different day */ 00355 if (utime.tm_mday != ltime.tm_mday) { 00356 if (utime.tm_mday < ltime.tm_mday) 00357 zonediff += 24 * 3600; 00358 else 00359 zonediff -= 24 * 3600; 00360 } 00361 00362 osync_trace(TRACE_EXIT, "%s: %i", __func__, zonediff); 00363 return zonediff; 00364 } 00365 00373 struct tm *osync_time_tm2utc(const struct tm *ltime, int offset) { 00374 00375 osync_trace(TRACE_ENTRY, "%s(%p, %i)", __func__, ltime, offset); 00376 struct tm *tmtime = g_malloc0(sizeof(struct tm)); 00377 00378 tmtime->tm_year = ltime->tm_year; 00379 tmtime->tm_mon = ltime->tm_mon; 00380 tmtime->tm_mday = ltime->tm_mday; 00381 tmtime->tm_hour = ltime->tm_hour; 00382 tmtime->tm_min = ltime->tm_min; 00383 tmtime->tm_sec = ltime->tm_sec; 00384 00385 /* in seconds - to have a exactly timezone diff like -13.5h */ 00386 tmtime->tm_hour -= offset / 3600; 00387 tmtime->tm_min -= (offset % 3600) / 60; 00388 00389 if (tmtime->tm_hour > 23 || tmtime->tm_hour < 0) { 00390 00391 if (tmtime->tm_hour < 0) { 00392 tmtime->tm_hour += 24; 00393 tmtime->tm_mday -= 1; 00394 } else { 00395 tmtime->tm_hour -= 24; 00396 tmtime->tm_mday += 1; 00397 } 00398 } 00399 00400 osync_trace(TRACE_EXIT, "%s: %p", __func__, tmtime); 00401 return tmtime; 00402 } 00403 00411 struct tm *osync_time_tm2localtime(const struct tm *utime, int offset) { 00412 00413 struct tm *tmtime = g_malloc0(sizeof(struct tm)); 00414 00415 tmtime->tm_year = utime->tm_year; 00416 tmtime->tm_mon = utime->tm_mon; 00417 tmtime->tm_mday = utime->tm_mday; 00418 tmtime->tm_hour = utime->tm_hour; 00419 tmtime->tm_min = utime->tm_min; 00420 tmtime->tm_sec = utime->tm_sec; 00421 00422 tmtime->tm_hour += offset / 3600; 00423 tmtime->tm_min += (offset % 3600) / 60; 00424 00425 if (tmtime->tm_hour > 23 || tmtime->tm_hour < 0) { 00426 00427 if (tmtime->tm_hour < 0) { 00428 tmtime->tm_mday -= 1; 00429 tmtime->tm_hour += 24; 00430 } else { 00431 tmtime->tm_mday += 1; 00432 tmtime->tm_hour -= 24; 00433 } 00434 } 00435 00436 return tmtime; 00437 } 00438 00445 char *osync_time_vtime2utc(const char* localtime, int offset) { 00446 osync_trace(TRACE_ENTRY, "%s(%s)", __func__, localtime); 00447 00448 char *utc = NULL; 00449 struct tm *tm_local = NULL, *tm_utc = NULL; 00450 00451 if (strstr(localtime, "Z")) { 00452 utc = strdup(localtime); 00453 goto end; 00454 } 00455 00456 tm_local = osync_time_vtime2tm(localtime); 00457 tm_utc = osync_time_tm2utc(tm_local, offset); 00458 utc = osync_time_tm2vtime(tm_utc, TRUE); 00459 00460 g_free(tm_local); 00461 // FIXME is it really a memory leak? 00462 // g_free(tm_utc); 00463 00464 end: 00465 osync_trace(TRACE_EXIT, "%s: %s", __func__, utc); 00466 return utc; 00467 } 00468 00474 char *osync_time_vtime2localtime(const char* utc, int offset) { 00475 00476 char *localtime = NULL; 00477 struct tm *tm_local = NULL, *tm_utc = NULL; 00478 00479 if (!strstr(utc, "Z")) { 00480 localtime = strdup(utc); 00481 return localtime; 00482 } 00483 00484 tm_utc = osync_time_vtime2tm(utc); 00485 tm_local = osync_time_tm2localtime(tm_utc, offset); 00486 localtime = osync_time_tm2vtime(tm_local, FALSE); 00487 00488 g_free(tm_local); 00489 g_free(tm_utc); 00490 00491 return localtime; 00492 } 00493 00494 00495 00496 /* XXX This functions should only be used as workaround for plugins which 00497 only supports localtime without any timezone information. */ 00498 00502 const char *_time_attr[] = { 00503 "DTSTART:", 00504 "DTEND:", 00505 "DTSTAMP:", 00506 "AALARM:", 00507 "DALARM:", 00508 "DUE:", 00509 NULL 00510 }; 00511 00518 static void _convert_time_field(GString *entry, const char *field, osync_bool toUTC) { 00519 00520 int i, tzdiff; 00521 char *res = NULL; 00522 char *new_stamp = NULL; 00523 00524 GString *stamp = g_string_new(""); 00525 00526 if ((res = strstr(entry->str, field))) { 00527 res += strlen(field); 00528 00529 for (i=0; res[i] != '\n' && res[i] != '\r'; i++) 00530 stamp = g_string_append_c(stamp, res[i]); 00531 00532 gssize pos = res - entry->str; 00533 entry = g_string_erase(entry, pos, i); 00534 00535 // Get System offset to UTC 00536 struct tm *tm_stamp = osync_time_vtime2tm(stamp->str); 00537 tzdiff = osync_time_timezone_diff(tm_stamp); 00538 g_free(tm_stamp); 00539 00540 if (toUTC) 00541 new_stamp = osync_time_vtime2utc(stamp->str, tzdiff); 00542 else 00543 new_stamp = osync_time_vtime2localtime(stamp->str, tzdiff); 00544 00545 entry = g_string_insert(entry, pos, new_stamp); 00546 g_free(new_stamp); 00547 } 00548 } 00549 00556 char *_convert_entry(const char *vcal, osync_bool toUTC) { 00557 00558 int i = 0; 00559 GString *new_entry = g_string_new(vcal); 00560 00561 for (i=0; _time_attr[i] != NULL; i++) 00562 _convert_time_field(new_entry, _time_attr[i], toUTC); 00563 00564 return g_string_free(new_entry, FALSE); 00565 } 00566 00572 char *osync_time_vcal2localtime(const char *vcal) { 00573 00574 return _convert_entry(vcal, FALSE); 00575 } 00576 00582 char *osync_time_vcal2utc(const char *vcal) { 00583 00584 return _convert_entry(vcal, TRUE); 00585 } 00586 00593 char *osync_time_sec2alarmdu(int seconds) { 00594 00595 osync_trace(TRACE_ENTRY, "%s(%i)", __func__, seconds); 00596 00597 char *tmp = NULL; 00598 char *prefix = NULL; 00599 00600 if (!seconds) { 00601 tmp = g_strdup("PT0S"); 00602 goto end; 00603 } 00604 00605 if (seconds > 0) { 00606 prefix = g_strdup("P"); 00607 } else { 00608 prefix = g_strdup("-P"); 00609 seconds *= -1; 00610 } 00611 00612 // Days 00613 if (!(seconds % (3600 * 24))) { 00614 tmp = g_strdup_printf("%s%iD", prefix, seconds / (3600 * 24)); 00615 goto end; 00616 } 00617 00618 // Hours 00619 if (!(seconds % 3600)) { 00620 tmp = g_strdup_printf("%sT%iH", prefix, seconds / 3600); 00621 goto end; 00622 } 00623 00624 // Minutes 00625 if (!(seconds % 60) && seconds < 3600) { 00626 tmp = g_strdup_printf("%sT%iM", prefix, seconds / 60); 00627 goto end; 00628 } 00629 00630 // Seconds 00631 if (seconds < 60) { 00632 tmp = g_strdup_printf("%sT%iS", prefix, seconds); 00633 goto end; 00634 } 00635 00636 if (seconds > 60) 00637 tmp = g_strdup_printf("%sT%iM", prefix, seconds / 60); 00638 00639 if (seconds > 3600) 00640 tmp = g_strdup_printf("%sT%iH%iM", prefix, seconds / 3600, 00641 (seconds % 3600) / 60); 00642 00643 if (seconds > (3600 * 24)) 00644 tmp = g_strdup_printf("%s%iDT%iH%iM", prefix, seconds / (3600 * 24), 00645 seconds % (3600 * 24) / 3600, 00646 ((seconds % (3600 * 24) % 3600)) / 60); 00647 00648 end: 00649 g_free(prefix); 00650 00651 osync_trace(TRACE_EXIT, "%s: %s", __func__, tmp); 00652 return tmp; 00653 } 00654 00663 int osync_time_alarmdu2sec(const char *alarm) { 00664 00665 osync_trace(TRACE_ENTRY, "%s(%s)", __func__, alarm); 00666 00667 int i, secs, digits; 00668 int is_digit = 0; 00669 int sign = 1; // when ical stamp doesn't start with '-' => seconds after event 00670 int days = 0, weeks = 0, hours = 0, minutes = 0, seconds = 0; 00671 00672 for (i=0; i < (int) strlen(alarm); i++) { 00673 00674 switch (alarm[i]) { 00675 case '-': 00676 sign = -1; // seconds before event - change the sign 00677 case 'P': 00678 case 'T': 00679 is_digit = 0; 00680 break; 00681 case 'W': 00682 is_digit = 0; 00683 weeks = digits; 00684 break; 00685 case 'D': 00686 is_digit = 0; 00687 days = digits; 00688 break; 00689 case 'H': 00690 is_digit = 0; 00691 hours = digits; 00692 break; 00693 case 'M': 00694 is_digit = 0; 00695 minutes = digits; 00696 break; 00697 case 'S': 00698 is_digit = 0; 00699 seconds = digits; 00700 break; 00701 case '0': 00702 case '1': 00703 case '2': 00704 case '3': 00705 case '4': 00706 case '5': 00707 case '6': 00708 case '7': 00709 case '8': 00710 case '9': 00711 if (is_digit) 00712 break; 00713 00714 sscanf((char*)(alarm+i),"%d",&digits); 00715 is_digit = 1; 00716 break; 00717 } 00718 } 00719 00720 secs = (weeks * 7 * 24 * 3600) + (days * 24 * 3600) + (hours * 3600) + (minutes * 60) + seconds; 00721 00722 secs = secs * sign; // change sign if the alarm is in seconds before event (leading '-') 00723 00724 osync_trace(TRACE_EXIT, "%s: %i", __func__, secs); 00725 return secs; 00726 } 00727 00728 /* 00729 * Timezone ID helper 00730 */ 00731 00737 int osync_time_str2wday(const char *swday) { 00738 00739 int weekday = -1; 00740 00741 if (!strcmp(swday, "SU")) 00742 weekday = 0; 00743 else if (!strcmp(swday, "MO")) 00744 weekday = 1; 00745 else if (!strcmp(swday, "TU")) 00746 weekday = 2; 00747 else if (!strcmp(swday, "WE")) 00748 weekday = 3; 00749 else if (!strcmp(swday, "TH")) 00750 weekday = 4; 00751 else if (!strcmp(swday, "FR")) 00752 weekday = 5; 00753 else if (!strcmp(swday, "SA")) 00754 weekday = 6; 00755 00756 return weekday; 00757 } 00758 00769 struct tm *osync_time_relative2tm(const char *byday, const int bymonth, const int year) { 00770 00771 struct tm *datestamp = g_malloc0(sizeof(struct tm)); 00772 char weekday[3]; 00773 int first_wday = 0, last_wday = 0; 00774 int daymod, mday, searched_wday; 00775 00776 sscanf(byday, "%d%s", &daymod, weekday); 00777 weekday[2] = '\0'; 00778 00779 searched_wday = osync_time_str2wday(weekday); 00780 00781 datestamp->tm_year = year - 1900; 00782 datestamp->tm_mon = bymonth - 1; 00783 datestamp->tm_mday = 0; 00784 datestamp->tm_hour = 0; 00785 datestamp->tm_min = 0; 00786 datestamp->tm_sec = 0; 00787 datestamp->tm_isdst = -1; 00788 00789 for (mday = 0; mday <= 31; mday++) { 00790 datestamp->tm_mday = mday; 00791 mktime(datestamp); 00792 00793 if (datestamp->tm_wday == searched_wday) { 00794 if (!first_wday) 00795 first_wday = searched_wday; 00796 00797 last_wday = searched_wday; 00798 } 00799 } 00800 00801 if (daymod > 0) 00802 datestamp->tm_mday = first_wday + (7 * (daymod - 1)); 00803 else 00804 datestamp->tm_mday = last_wday - (7 * (daymod - 1)); 00805 00806 mktime(datestamp); 00807 00808 return datestamp; 00809 } 00810 00816 int osync_time_utcoffset2sec(const char *offset) { 00817 osync_trace(TRACE_ENTRY, "%s(%s)", __func__, offset); 00818 00819 char csign = 0; 00820 int seconds = 0, sign = 1; 00821 int hours = 0, minutes = 0; 00822 00823 sscanf(offset, "%c%2d%2d", &csign, &hours, &minutes); 00824 00825 if (csign == '-') 00826 sign = -1; 00827 00828 seconds = (hours * 3600 + minutes * 60) * sign; 00829 00830 osync_trace(TRACE_EXIT, "%s: %i", __func__, seconds); 00831 return seconds; 00832 } 00833 00841 struct tm *osync_time_dstchange(xmlNode *dstNode) { 00842 00843 int month; 00844 struct tm *dst_change = NULL, *tm_started = NULL; 00845 char *started = NULL, *rule = NULL, *byday = NULL; 00846 00847 xmlNode *current = osxml_get_node(dstNode, "DateStarted"); 00848 started = (char*) xmlNodeGetContent(current); 00849 tm_started = osync_time_vtime2tm(started); 00850 00851 g_free(started); 00852 00853 current = osxml_get_node(dstNode, "RecurrenceRule"); 00854 current = current->children; 00855 00856 while (current) { 00857 rule = (char *) xmlNodeGetContent(current); 00858 00859 if (strstr(rule, "BYDAY=")) 00860 byday = g_strdup(rule + 6); 00861 else if (strstr(rule, "BYMONTH=")) 00862 sscanf(rule, "BYMONTH=%d", &month); 00863 00864 g_free(rule); 00865 00866 current = current->next; 00867 } 00868 00869 dst_change = osync_time_relative2tm(byday, month, tm_started->tm_year + 1900); 00870 00871 g_free(byday); 00872 00873 dst_change->tm_hour = tm_started->tm_hour; 00874 dst_change->tm_min = tm_started->tm_min; 00875 00876 g_free(tm_started); 00877 00878 return dst_change; 00879 } 00880 00887 osync_bool osync_time_isdst(const char *vtime, xmlNode *tzid) { 00888 00889 osync_trace(TRACE_ENTRY, "%s(%s, %p)", __func__, vtime, tzid); 00890 00891 int year; 00892 /* KH: Fails with -Werror=unused-but-set-variable as newyear and newyear_t aren't used anywhere 00893 char *newyear = NULL; 00894 time_t newyear_t, timestamp; 00895 */ 00896 time_t timestamp; 00897 struct tm *std_changetime, *dst_changetime; 00898 time_t dstStamp, stdStamp; 00899 xmlNode *current = NULL; 00900 00901 sscanf(vtime, "%4d%*2d%*2dT%*2d%*d%*2d%*c", &year); 00902 00903 /* KH: See comment above 00904 newyear = g_strdup_printf("%4d0101T000000", year); 00905 newyear_t = osync_time_vtime2unix(newyear, 0); 00906 */ 00907 timestamp = osync_time_vtime2unix(vtime, 0); 00908 00909 /* Handle XML Timezone field */ 00910 current = osxml_get_node(tzid, "Standard"); 00911 std_changetime = osync_time_dstchange(current); 00912 00913 current = osxml_get_node(tzid, "DaylightSavings"); 00914 dst_changetime = osync_time_dstchange(current); 00915 00916 /* determine in which timezone is vtime */ 00917 dstStamp = osync_time_tm2unix(dst_changetime); 00918 stdStamp = osync_time_tm2unix(std_changetime); 00919 00920 if (timestamp > stdStamp && timestamp < dstStamp) { 00921 osync_trace(TRACE_EXIT, "%s: FALSE (Standard Timezone)", __func__); 00922 return FALSE; 00923 } 00924 00925 osync_trace(TRACE_EXIT, "%s: TRUE (Daylight Saving Timezone)", __func__); 00926 return TRUE; 00927 } 00928 00936 int osync_time_tzoffset(const char *vtime, xmlNode *tz) { 00937 00938 osync_trace(TRACE_ENTRY, "%s(%s, %p)", __func__, vtime, tz); 00939 00940 int seconds; 00941 char *offset = NULL; 00942 xmlNode *current = NULL; 00943 00944 if (osync_time_isdst(vtime, tz)) 00945 current = osxml_get_node(tz, "DaylightSavings"); 00946 else 00947 current = osxml_get_node(tz, "Standard"); 00948 00949 offset = osxml_find_node(current, "TZOffsetFrom"); 00950 seconds = osync_time_utcoffset2sec(offset); 00951 00952 osync_trace(TRACE_EXIT, "%s: %i", __func__, seconds); 00953 return seconds; 00954 } 00955 00961 char *osync_time_tzid(xmlNode *tz) { 00962 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, tz); 00963 00964 char *id = NULL; 00965 00966 id = osxml_find_node(tz, "TimezoneID"); 00967 00968 osync_trace(TRACE_EXIT, "%s: %s", __func__, id); 00969 return id; 00970 } 00971 00977 char *osync_time_tzlocation(xmlNode *tz) { 00978 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, tz); 00979 00980 char *location = NULL; 00981 00982 location = osxml_find_node(tz, "TimezoneLocation"); 00983 00984 osync_trace(TRACE_EXIT, "%s: %s", __func__, location); 00985 return location; 00986 } 00987 00994 xmlNode *osync_time_tzinfo(xmlNode *root, const char *tzid) { 00995 00996 osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, root, tzid); 00997 00998 int numnodes, i; 00999 char *tzinfo_tzid = NULL; 01000 01001 xmlNode *tz = NULL; 01002 xmlNodeSet *nodes = NULL; 01003 xmlXPathObject *xobj = NULL; 01004 01005 /* search matching Timezone information */ 01006 xobj = osxml_get_nodeset(root->doc, "/vcal/Timezone"); 01007 nodes = xobj->nodesetval; 01008 numnodes = (nodes) ? nodes->nodeNr : 0; 01009 01010 osync_trace(TRACE_INTERNAL, "Found %i Timezone field(s)", numnodes); 01011 01012 if (!numnodes) 01013 goto noresult; 01014 01015 01016 for (i=0; i < numnodes; i++) { 01017 tz = nodes->nodeTab[i]; 01018 tzinfo_tzid = osync_time_tzid(tz); 01019 01020 if (!tzinfo_tzid) { 01021 g_free(tzinfo_tzid); 01022 tz = NULL; 01023 continue; 01024 } 01025 01026 if (!strcmp(tzinfo_tzid, tzid)) 01027 break; 01028 } 01029 01030 g_free(tzinfo_tzid); 01031 01032 if (!tz) 01033 goto noresult; 01034 01035 01036 osync_trace(TRACE_EXIT, "%s: %p", __func__, tz); 01037 return tz; 01038 01039 noresult: 01040 osync_trace(TRACE_EXIT, "%s: No matching Timezone node found. Seems to be a be a floating timestamp.", __func__); 01041 return NULL; 01042 } 01043 01050 char *osync_time_tzlocal2utc(xmlNode *root, const char *field) { 01051 osync_trace(TRACE_ENTRY, "%s(%p, %s)", __func__, root, field); 01052 01053 int offset = 0; 01054 char *utc = NULL, *field_tzid = NULL, *vtime = NULL; 01055 xmlNode *tz = NULL; 01056 01057 /* 01058 node = osxml_get_node(root, field); 01059 if (!node) { 01060 osync_trace(TRACE_EXIT, "%s: field \"%s\" not found", __func__, field); 01061 return NULL; 01062 } 01063 */ 01064 01065 field_tzid = osync_time_tzid(root); 01066 if (!field_tzid) { 01067 g_free(field_tzid); 01068 goto noresult; 01069 } 01070 01071 tz = osync_time_tzinfo(root, field_tzid); 01072 g_free(field_tzid); 01073 01074 if (!tz) 01075 goto noresult; 01076 01077 vtime = osxml_find_node(root, "Content"); 01078 01079 /* Handle UTC offset like 13.5h */ 01080 offset = osync_time_tzoffset(vtime, tz); 01081 struct tm *ttm = osync_time_vtime2tm(vtime); 01082 ttm->tm_hour -= offset / 3600; 01083 ttm->tm_min -= (offset % 3600) / 60; 01084 mktime(ttm); 01085 utc = osync_time_tm2vtime(ttm, TRUE); 01086 01087 g_free(vtime); 01088 g_free(ttm); 01089 01090 osync_trace(TRACE_EXIT, "%s: %s", __func__, utc); 01091 return utc; 01092 01093 noresult: 01094 osync_trace(TRACE_EXIT, "%s: No matching Timezone node is found.", __func__); 01095 return NULL; 01096 } 01097