[cosmetics] update date in GPL header
[vuplus_xbmc] / xbmc / linux / LinuxTimezone.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include <time.h>
22 #include "system.h"
23 #ifdef TARGET_ANDROID
24 #include "android/bionic_supplement/bionic_supplement.h"
25 #endif
26 #include "PlatformInclude.h"
27 #include "LinuxTimezone.h"
28 #include "utils/SystemInfo.h"
29 #if defined(TARGET_DARWIN)
30 #include "osx/OSXGNUReplacements.h"
31 #endif
32 #ifdef __FreeBSD__
33 #include "freebsd/FreeBSDGNUReplacements.h"
34 #endif
35
36 #include "Util.h"
37
38 using namespace std;
39
40 CLinuxTimezone::CLinuxTimezone() : m_IsDST(0)
41 {
42    char* line = NULL;
43    size_t linelen = 0;
44    int nameonfourthfield = 0;
45    CStdString s;
46    vector<CStdString> tokens;
47
48    // Load timezones
49    FILE* fp = fopen("/usr/share/zoneinfo/zone.tab", "r");
50    if (fp)
51    {
52       CStdString countryCode;
53       CStdString timezoneName;
54
55       while (getdelim(&line, &linelen, '\n', fp) > 0)
56       {
57          tokens.clear();
58          s = line;
59          s.TrimLeft(" \t").TrimRight(" \n");
60
61          if (s.length() == 0)
62             continue;
63
64          if (s[0] == '#')
65             continue;
66
67          CUtil::Tokenize(s, tokens, " \t");
68          if (tokens.size() < 3)
69             continue;
70
71          countryCode = tokens[0];
72          timezoneName = tokens[2];
73
74          if (m_timezonesByCountryCode.count(countryCode) == 0)
75          {
76             vector<CStdString> timezones;
77             timezones.push_back(timezoneName);
78             m_timezonesByCountryCode[countryCode] = timezones;
79          }
80          else
81          {
82             vector<CStdString>& timezones = m_timezonesByCountryCode[countryCode];
83             timezones.push_back(timezoneName);
84          }
85
86          m_countriesByTimezoneName[timezoneName] = countryCode;
87       }
88       fclose(fp);
89    }
90
91    if (line)
92    {
93      free(line);
94      line = NULL;
95      linelen = 0;
96    }
97
98    // Load countries
99    fp = fopen("/usr/share/zoneinfo/iso3166.tab", "r");
100    if (!fp)
101    {
102       fp = fopen("/usr/share/misc/iso3166", "r");
103       nameonfourthfield = 1;
104    }
105    if (fp)
106    {
107       CStdString countryCode;
108       CStdString countryName;
109
110       while (getdelim(&line, &linelen, '\n', fp) > 0)
111       {
112          s = line;
113          s.TrimLeft(" \t").TrimRight(" \n");
114
115          if (s.length() == 0)
116             continue;
117
118          if (s[0] == '#')
119             continue;
120
121          // Search for the first non space from the 2nd character and on
122          int i = 2;
123          while (s[i] == ' ' || s[i] == '\t') i++;
124
125          if (nameonfourthfield)
126          {
127             // skip three letter
128             while (s[i] != ' ' && s[i] != '\t') i++;
129             while (s[i] == ' ' || s[i] == '\t') i++;
130             // skip number
131             while (s[i] != ' ' && s[i] != '\t') i++;
132             while (s[i] == ' ' || s[i] == '\t') i++;
133          }
134
135          countryCode = s.Left(2);
136          countryName = s.Mid(i);
137
138          m_counties.push_back(countryName);
139          m_countryByCode[countryCode] = countryName;
140          m_countryByName[countryName] = countryCode;
141       }
142       sort(m_counties.begin(), m_counties.end(), sortstringbyname());
143       fclose(fp);
144    }
145    free(line);
146 }
147
148 vector<CStdString> CLinuxTimezone::GetCounties()
149 {
150    return m_counties;
151 }
152
153 vector<CStdString> CLinuxTimezone::GetTimezonesByCountry(const CStdString country)
154 {
155    return m_timezonesByCountryCode[m_countryByName[country]];
156 }
157
158 CStdString CLinuxTimezone::GetCountryByTimezone(const CStdString timezone)
159 {
160 #if defined(TARGET_DARWIN)
161    return CStdString("?");
162 #else
163    return m_countryByCode[m_countriesByTimezoneName[timezone]];
164 #endif
165 }
166
167 void CLinuxTimezone::SetTimezone(CStdString timezoneName)
168 {
169   bool use_timezone = false;
170   
171 #if !defined(TARGET_DARWIN)
172   use_timezone = true;
173 #else
174   if (g_sysinfo.IsAppleTV2())
175     use_timezone = true;  
176 #endif
177   
178   if (use_timezone)
179   {
180     static char env_var[255];
181     sprintf(env_var, "TZ=:%s", timezoneName.c_str());
182     putenv(env_var);
183     tzset();
184   }
185 }
186
187 CStdString CLinuxTimezone::GetOSConfiguredTimezone()
188 {
189    char timezoneName[255];
190
191    // try Slackware approach first
192    ssize_t rlrc = readlink("/etc/localtime-copied-from"
193                            , timezoneName, sizeof(timezoneName)-1);
194    if (rlrc != -1)
195    {
196      timezoneName[rlrc] = '\0';
197
198      char* p = strrchr(timezoneName,'/');
199      if (p)
200      { // we want the previous '/'
201        char* q = p;
202        *q = 0;
203        p = strrchr(timezoneName,'/');
204        *q = '/';
205        if (p)
206          p++;
207      }
208      return p;
209    }
210
211    // now try Debian approach
212    timezoneName[0] = 0;
213    FILE* fp = fopen("/etc/timezone", "r");
214    if (fp)
215    {
216       if (fgets(timezoneName, sizeof(timezoneName), fp))
217         timezoneName[strlen(timezoneName)-1] = '\0';
218       fclose(fp);
219    }
220
221    return timezoneName;
222 }
223
224 CLinuxTimezone g_timezone;