pidgin: 3435ea1c: Fix purple_str_to_time(). Fixes #13131.
rekkanoryo at pidgin.im
rekkanoryo at pidgin.im
Sun Jan 9 15:25:36 EST 2011
----------------------------------------------------------------------
Revision: 3435ea1c22455d6bafdda7845e20a498b39f839b
Parent: 539a3b8b9f11b96523e13451db703549d281d372
Author: morshed.nader at gmail.com
Date: 01/09/11 15:08:29
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/3435ea1c22455d6bafdda7845e20a498b39f839b
Changelog:
Fix purple_str_to_time(). Fixes #13131.
Changes against parent 539a3b8b9f11b96523e13451db703549d281d372
patched configure.ac
patched libpurple/util.c
-------------- next part --------------
============================================================
--- libpurple/util.c c6df0cbf873fdf6a665574175bb669bea13598e6
+++ libpurple/util.c be4a91e070c6e30f7d015e5a7c94790fa1ff3fe9
@@ -664,160 +664,193 @@ purple_time_build(int year, int month, i
return mktime(&tm);
}
+/* originally taken from GLib trunk 1-6-11 */
+/* originally licensed as LGPL 2+ */
+static time_t
+mktime_utc(struct tm *tm)
+{
+ time_t retval;
+
+#ifndef HAVE_TIMEGM
+ static const gint days_before[] =
+ {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+ };
+#endif
+
+#ifndef HAVE_TIMEGM
+ if (tm->tm_mon < 0 || tm->tm_mon > 11)
+ return (time_t) -1;
+
+ retval = (tm->tm_year - 70) * 365;
+ retval += (tm->tm_year - 68) / 4;
+ retval += days_before[tm->tm_mon] + tm->tm_mday - 1;
+
+ if (tm->tm_year % 4 == 0 && tm->tm_mon < 2)
+ retval -= 1;
+
+ retval = ((((retval * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60 + tm->tm_sec;
+#else
+ retval = timegm (tm);
+#endif /* !HAVE_TIMEGM */
+
+ return retval;
+}
+
time_t
purple_str_to_time(const char *timestamp, gboolean utc,
- struct tm *tm, long *tz_off, const char **rest)
+ struct tm *tm, long *tz_off, const char **rest)
{
- time_t retval = 0;
- static struct tm t;
- const char *c = timestamp;
- int year = 0;
+ struct tm t;
+ const gchar *str;
+ gint year = 0;
long tzoff = PURPLE_NO_TZ_OFF;
+ time_t retval;
+ gboolean mktime_with_utc = TRUE;
- time(&retval);
- localtime_r(&retval, &t);
-
if (rest != NULL)
*rest = NULL;
+ g_return_val_if_fail(timestamp != NULL, 0);
+
+ str = timestamp;
+
+ /* Strip leading whitespace */
+ while (g_ascii_isspace(*str))
+ str++;
+
+ if (*str == '\0') {
+ if (rest != NULL && *str != '\0')
+ *rest = str;
+
+ return 0;
+ }
+
+ if (!g_ascii_isdigit(*str) && *str != '-' && *str != '+') {
+ if (rest != NULL && *str != '\0')
+ *rest = str;
+
+ return 0;
+ }
+
/* 4 digit year */
- if (sscanf(c, "%04d", &year) && year > 1900)
- {
- c += 4;
- if (*c == '-')
- c++;
+ if (sscanf(str, "%04d", &year) && year >= 1900) {
+ str += 4;
+
+ if (*str == '-' || *str == '/')
+ str++;
+
t.tm_year = year - 1900;
}
/* 2 digit month */
- if (!sscanf(c, "%02d", &t.tm_mon))
- {
- if (rest != NULL && *c != '\0')
- *rest = c;
+ if (!sscanf(str, "%02d", &t.tm_mon)) {
+ if (rest != NULL && *str != '\0')
+ *rest = str;
+
return 0;
}
- c += 2;
- if (*c == '-' || *c == '/')
- c++;
+
+ str += 2;
t.tm_mon -= 1;
+ if (*str == '-' || *str == '/')
+ str++;
+
/* 2 digit day */
- if (!sscanf(c, "%02d", &t.tm_mday))
- {
- if (rest != NULL && *c != '\0')
- *rest = c;
+ if (!sscanf(str, "%02d", &t.tm_mday)) {
+ if (rest != NULL && *str != '\0')
+ *rest = str;
+
return 0;
}
- c += 2;
- if (*c == '/')
- {
- c++;
- if (!sscanf(c, "%04d", &t.tm_year))
- {
- if (rest != NULL && *c != '\0')
- *rest = c;
+ str += 2;
+
+ /* Grab the year off the end if there's still stuff */
+ if (*str == '/' || *str == '-') {
+ /* But make sure we don't read the year twice */
+ if (year >= 1900) {
+ if (rest != NULL && *str != '\0')
+ *rest = str;
+
return 0;
}
+
+ str++;
+
+ if (!sscanf(str, "%04d", &t.tm_year)) {
+ if (rest != NULL && *str != '\0')
+ *rest = str;
+
+ return 0;
+ }
+
t.tm_year -= 1900;
- }
- else if (*c == 'T' || *c == '.')
- {
- c++;
- /* we have more than a date, keep going */
+ } else if (*str == 'T' || *str == '.') {
+ str++;
- /* 2 digit hour */
- if ((sscanf(c, "%02d:%02d:%02d", &t.tm_hour, &t.tm_min, &t.tm_sec) == 3 && (c = c + 8)) ||
- (sscanf(c, "%02d%02d%02d", &t.tm_hour, &t.tm_min, &t.tm_sec) == 3 && (c = c + 6)))
+ /* Continue grabbing the hours/minutes/seconds */
+ if ((sscanf(str, "%02d:%02d:%02d", &t.tm_hour, &t.tm_min, &t.tm_sec) == 3 &&
+ (str += 8)) ||
+ (sscanf(str, "%02d%02d%02d", &t.tm_hour, &t.tm_min, &t.tm_sec) == 3 &&
+ (str += 6)))
{
- gboolean offset_positive = FALSE;
- int tzhrs;
- int tzmins;
+ gint sign, tzhrs, tzmins;
- t.tm_isdst = -1;
-
- if (*c == '.') {
+ if (*str == '.') {
+ /* Cut off those pesky micro-seconds */
do {
- c++;
- } while (*c >= '0' && *c <= '9'); /* dealing with precision we don't care about */
+ str++;
+ } while (*str >= '0' && *str <= '9');
}
- if (*c == '+')
- offset_positive = TRUE;
- if (((*c == '+' || *c == '-') && (c = c + 1)) &&
- ((sscanf(c, "%02d:%02d", &tzhrs, &tzmins) == 2 && (c = c + 5)) ||
- (sscanf(c, "%02d%02d", &tzhrs, &tzmins) == 2 && (c = c + 4))))
- {
- tzoff = tzhrs*60*60 + tzmins*60;
- if (offset_positive)
- tzoff *= -1;
- }
- else if ((*c == 'Z') && (c = c + 1))
- {
- /* 'Z' = Zulu = UTC */
- tzoff = 0;
- }
- else if (utc)
- {
- static struct tm tmptm;
- time_t tmp;
- tmp = mktime(&t);
- /* we care about whether it *was* dst, and the offset, here on this
- * date, not whether we are currently observing dst locally *now*.
- * This isn't perfect, because we would need to know in advance the
- * offset we are trying to work out in advance to be sure this
- * works for times around dst transitions but it'll have to do. */
- localtime_r(&tmp, &tmptm);
- t.tm_isdst = tmptm.tm_isdst;
-#ifdef HAVE_TM_GMTOFF
- t.tm_gmtoff = tmptm.tm_gmtoff;
-#endif
- }
- if (rest != NULL && *c != '\0')
- {
- if (*c == ' ')
- c++;
- if (*c != '\0')
- *rest = c;
- }
+ sign = (*str == '+') ? -1 : 1;
- if (tzoff != PURPLE_NO_TZ_OFF || utc)
- {
-#if defined(_WIN32)
- long sys_tzoff;
-#endif
+ /* Process the timezone */
+ if (*str == '+' || *str == '-') {
+ str++;
-#if defined(_WIN32) || defined(HAVE_TM_GMTOFF) || defined (HAVE_TIMEZONE)
- if (tzoff == PURPLE_NO_TZ_OFF)
- tzoff = 0;
-#endif
+ if (((sscanf(str, "%02d:%02d", &tzhrs, &tzmins) == 2 && (str += 5)) ||
+ (sscanf(str, "%02d%02d", &tzhrs, &tzmins) == 2 && (str += 4))))
+ {
+ tzoff = tzhrs * 60 * 60 + tzmins * 60;
+ tzoff *= sign;
+ } else {
+ if (rest != NULL && *str != '\0')
+ *rest = str;
-#ifdef _WIN32
- if ((sys_tzoff = wpurple_get_tz_offset()) == -1)
- tzoff = PURPLE_NO_TZ_OFF;
- else
- tzoff += sys_tzoff;
-#else
-#ifdef HAVE_TM_GMTOFF
- tzoff += t.tm_gmtoff;
-#else
-# ifdef HAVE_TIMEZONE
- tzset(); /* making sure */
- tzoff -= timezone;
-# endif
-#endif
-#endif /* _WIN32 */
+ return 0;
+ }
+ } else if (*str == 'Z') {
+ /* 'Z' = Zulu = UTC */
+ str++;
+ utc = TRUE;
+ } else if (!utc) {
+ /* Local Time */
+ t.tm_isdst = -1;
+ mktime_with_utc = FALSE;
}
+
+ if (utc)
+ tzoff = 0;
}
- else
- {
- if (rest != NULL && *c != '\0')
- *rest = c;
- }
}
- retval = mktime(&t);
+ if (rest != NULL && *str != '\0') {
+ /* Strip trailing whitespace */
+ while (g_ascii_isspace(*str))
+ str++;
+ if (*str != '\0')
+ *rest = str;
+ }
+
+ if (mktime_with_utc)
+ retval = mktime_utc(&t);
+ else
+ retval = mktime(&t);
+
if (tm != NULL)
*tm = t;
============================================================
--- configure.ac c6764653fb2d48c55b9d9ce91e7b8d3b0b360ba9
+++ configure.ac 775030e1640659136fe71e5e2f24c480e9c78fd9
@@ -329,7 +329,7 @@ dnl ####################################
dnl #######################################################################
dnl # Check for GLib 2.12 (required)
dnl #######################################################################
-PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.12.0 gobject-2.0 gmodule-2.0 gthread-2.0], , [
+PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.12.0 gio-2.0 gobject-2.0 gmodule-2.0 gthread-2.0], , [
AC_MSG_RESULT(no)
AC_MSG_ERROR([
@@ -2406,7 +2406,7 @@ AC_MSG_RESULT(no)
AC_MSG_CHECKING(for me pot o' gold)
AC_MSG_RESULT(no)
-AC_CHECK_FUNCS(gethostid lrand48)
+AC_CHECK_FUNCS(gethostid lrand48 timegm)
AC_CHECK_FUNCS(memcpy memmove random strchr strerror vprintf)
AC_CHECK_HEADERS(malloc.h paths.h sgtty.h stdarg.h sys/cdefs.h)
AC_CHECK_HEADERS(sys/file.h sys/filio.h sys/ioctl.h sys/msgbuf.h)
More information about the Commits
mailing list