1 /*
2  * Copyright 2001-2004 Brandon Long
3  * All Rights Reserved.
4  *
5  * ClearSilver Templating System
6  *
7  * This code is made available under the terms of the ClearSilver License.
8  * http://www.clearsilver.net/license.hdf
9  *
10  */
11 
12 #include "cs_config.h"
13 
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <time.h>
18 #include <limits.h>
19 #include "util/neo_misc.h"
20 #include "neo_date.h"
21 
22 /* This is pretty much a HACK.  Eventually, we might bring the parsing
23  * and stuff into this library (we can use the public domain source code
24  * from ftp://elsie.nci.nih.gov/pub/ as a base)
25  *
26  * For now, we just do a putenv(TZ)... which sucks, especially since
27  * many versions of putenv do a strdup... and then leak the memory the
28  * next time you putenv the same var.
29  */
30 
31 /* Since this is set to a partial filename and TZ=, it can't be bigger
32  * than this */
33 static char TzBuf[_POSIX_PATH_MAX + 4];
34 
time_set_tz(const char * mytimezone)35 static int time_set_tz (const char *mytimezone)
36 {
37   snprintf (TzBuf, sizeof(TzBuf), "TZ=%s", mytimezone);
38   putenv(TzBuf);
39   tzset();
40   return 0;
41 }
42 
neo_time_expand(const time_t tt,const char * mytimezone,struct tm * ttm)43 void neo_time_expand (const time_t tt, const char *mytimezone, struct tm *ttm)
44 {
45   const char *cur_tz = getenv("TZ");
46   int change_back = 0;
47   if (cur_tz == NULL || strcmp(mytimezone, cur_tz)) {
48     time_set_tz (mytimezone);
49     change_back = 1;
50   }
51   localtime_r (&tt, ttm);
52   if (cur_tz && change_back) {
53     time_set_tz(cur_tz);
54   }
55 }
56 
neo_time_compact(struct tm * ttm,const char * mytimezone)57 time_t neo_time_compact (struct tm *ttm, const char *mytimezone)
58 {
59   time_t r;
60   int save_isdst = ttm->tm_isdst;
61 
62   const char *cur_tz = getenv("TZ");
63   int change_back = 0;
64   if (cur_tz == NULL || strcmp(mytimezone, cur_tz)) {
65     time_set_tz (mytimezone);
66     change_back = 1;
67   }
68   ttm->tm_isdst = -1;
69   r = mktime(ttm);
70   ttm->tm_isdst = save_isdst;
71   if (cur_tz && change_back) {
72     time_set_tz(cur_tz);
73   }
74   return r;
75 }
76 
77 /* Hefted from NCSA HTTPd src/util.c -- What a pain in the ass. */
neo_tz_offset(struct tm * ttm)78 long neo_tz_offset(struct tm *ttm) {
79   /* We assume here that HAVE_TM_ZONE implies HAVE_TM_GMTOFF and
80    * HAVE_TZNAME implies HAVE_TIMEZONE since AC_STRUCT_TIMEZONE defines
81    * the former and not the latter */
82 #if defined(HAVE_TM_ZONE)
83   return ttm->tm_gmtoff;
84 #elif defined(HAVE_TZNAME)
85   long tz;
86 #ifndef __CYGWIN__
87   tz = - timezone;
88 #else
89   tz = - _timezone;
90 #endif
91   if(ttm->tm_isdst)
92     tz += 3600;
93   return tz;
94 #else
95   long tz;
96   struct tm loc_tm, gmt_tm;
97   time_t tt;
98 
99   /* We probably shouldn't use the _r versions here since this
100    * is for older platforms... */
101   tt = time(NULL);
102   localtime_r(&tt, &loc_tm);
103   gmtime_r(&tt, &gmt_tm);
104 
105   tz = mktime(&loc_tm) - mktime(&gmt_tm);
106   return tz;
107 #endif /* GMT OFFSet Crap */
108 }
109 
110