Code sync from tizen_2.4 45/42745/1 accepted/tizen/mobile/20150708.070016 accepted/tizen/tv/20150708.070034 accepted/tizen/wearable/20150708.070051 submit/tizen/20150630.051205 submit/tizen/20150708.045531
authorJiwan Kim <ji-wan.kim@samsung.com>
Thu, 2 Jul 2015 05:01:44 +0000 (14:01 +0900)
committerJiwan Kim <ji-wan.kim@samsung.com>
Thu, 2 Jul 2015 05:01:44 +0000 (14:01 +0900)
Change-Id: I6efe601d017219a2cbcee850cc597a9088314799

CMakeLists.txt
include/common.h [moved from src/common.h with 59% similarity]
include/time_update.h [moved from src/time_update.h with 68% similarity]
packaging/tel-plugin-nitz.spec
resources/mcctable.xml [new file with mode: 0644]
src/citylist.c [deleted file]
src/citylist.h [deleted file]
src/desc-nitz.c
src/time_update.c

index 8208729..c89fd59 100644 (file)
@@ -9,13 +9,23 @@ SET(INCLUDEDIR "\${prefix}/include")
 
 # Set required packages
 INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED glib-2.0 gio-2.0 tcore vconf deviced)
+pkg_check_modules(pkgs REQUIRED
+       glib-2.0
+       tcore
+       vconf
+       alarm-service
+       libxml-2.0
+       icu-i18n
+       capi-system-device
+)
 
 FOREACH(flag ${pkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
 ENDFOREACH(flag)
 
-INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include/)
+INCLUDE_DIRECTORIES(
+       ${CMAKE_SOURCE_DIR}/include/
+)
 
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
 SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wextra -fvisibility=hidden -fPIC")
@@ -26,13 +36,16 @@ ADD_DEFINITIONS("-DTCORE_LOG_TAG=\"NITZ\"")
 ADD_DEFINITIONS("-DPLUGIN_VERSION=${VERSION}")
 ADD_DEFINITIONS("-DEXPORT_API=__attribute__((visibility(\"default\")))")
 
+IF (TIZEN_FEATURE_NEED_RESTORED_GMT)
+       ADD_DEFINITIONS("-DTIZEN_FEATURE_NEED_RESTORED_GMT")
+ENDIF (TIZEN_FEATURE_NEED_RESTORED_GMT)
+
 MESSAGE(${CMAKE_C_FLAGS})
 MESSAGE(${pkgs_LDFLAGS})
 
 SET(SRCS
        src/desc-nitz.c
        src/time_update.c
-       src/citylist.c
 )
 
 # library build
@@ -43,3 +56,5 @@ SET_TARGET_PROPERTIES(nitz-plugin PROPERTIES PREFIX "" OUTPUT_NAME nitz-plugin)
 # install
 INSTALL(TARGETS nitz-plugin
                LIBRARY DESTINATION ${LIBDIR}/telephony/plugins)
+
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/resources/mcctable.xml DESTINATION /opt/data/etc PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ WORLD_READ)
\ No newline at end of file
similarity index 59%
rename from src/common.h
rename to include/common.h
index ebab6d6..9ed5cac 100644 (file)
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <unicode/ustring.h>
+#include <unicode/ucal.h>
+
+#ifdef FEATURE_FILE_LOG
 
 /* filelog */
 #ifndef NITZ_LOG_FILE
-#define NITZ_LOG_FILE  "/opt/var/log/nitz.log"
+#define NITZ_LOG_FILE          "/opt/var/log/nitz.log"
 #endif
 
 #ifndef NITZ_LOG_FUNC
                } \
        }
 
+#else
+#define filelog(fmt, args...) warn(fmt, ##args);
+#endif
+
+#define NITZ_TIMEZONE_MAX_LEN 64
+
+struct nitz_custom_data {
+       gboolean nitz_updated;
+       gboolean need_fix_zone;
+       gboolean wait_for_icc_card;
+       gboolean wait_for_net_registration;
+
+       char *plmn;
+       GHashTable *mcctable_hash;
+
+       GQueue *nitz_pending_queue;
+       CoreObject *co_network;
+       TcorePlugin *plugin;
+};
+
+typedef enum ConnMode {
+       CONN_MODE_COMPAINION,
+       CONN_MODE_REMOTE,
+       CONN_MODE_STANDALONE,
+       CONN_MODE_UNKNOWN
+} ConnMode;
+
+char * __nitz_get_country_code_for_mcc(char *operator_mcc, struct nitz_custom_data *custom_data);
+
 #endif
similarity index 68%
rename from src/time_update.h
rename to include/time_update.h
index 5c2f758..7ad3246 100644 (file)
 #ifndef __NITZ_TIME_H__
 #define __NITZ_TIME_H__
 
-int nitz_apply_tzfile(const char *tzfilename, gboolean mode_auto);
-long nitz_get_uptime();
-gboolean nitz_time_update(const struct tnoti_network_timeinfo *time_info, gboolean mode_auto);
+int nitz_apply_tzfile (const char *tzfilename);
+gboolean nitz_is_auto_timezone (void);
+gboolean nitz_time_update (const struct tnoti_network_timeinfo *time_info, struct nitz_custom_data *data, gint delay);
+GList * nitz_get_tzlist(char *iso, const struct tnoti_network_timeinfo *ti);
+gboolean nitz_set_time (time_t tt_gmt_nitz);
 
 #endif
index ee8a996..030980f 100644 (file)
@@ -1,6 +1,7 @@
 %define major 0
 %define minor 1
-%define patchlevel 19
+%define patchlevel 70
+
 Name:       tel-plugin-nitz
 Summary:    nitz plugin for telephony
 Version:    %{major}.%{minor}.%{patchlevel}
@@ -12,10 +13,12 @@ Requires(post): /sbin/ldconfig
 Requires(postun): /sbin/ldconfig
 BuildRequires:  cmake
 BuildRequires:  pkgconfig(glib-2.0)
-BuildRequires:  pkgconfig(gio-2.0)
+BuildRequires:  pkgconfig(libxml-2.0)
+BuildRequires:  pkgconfig(icu-i18n)
 BuildRequires:  pkgconfig(tcore)
 BuildRequires:  pkgconfig(vconf)
-BuildRequires:  pkgconfig(deviced)
+BuildRequires:  pkgconfig(alarm-service)
+BuildRequires:  pkgconfig(capi-system-device)
 
 %description
 nitz plugin for telephony
@@ -28,7 +31,7 @@ versionint=$[%{major} * 1000000 + %{minor} * 1000 + %{patchlevel}]
 cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \
        -DLIB_INSTALL_DIR=%{_libdir} \
        -DVERSION=$versionint
-make %{?jobs:-j%jobs}
+make %{?_smp_mflags}
 
 %post
 /sbin/ldconfig
@@ -41,6 +44,6 @@ rm -rf %{buildroot}
 
 %files
 %manifest tel-plugin-nitz.manifest
-%defattr(-,root,root,-)
-#%doc COPYING
+%defattr(644,system,system,-)
 %{_libdir}/telephony/plugins/*
+/opt/data/etc/mcctable.xml
diff --git a/resources/mcctable.xml b/resources/mcctable.xml
new file mode 100644 (file)
index 0000000..c40d566
--- /dev/null
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mcctable>
+       <entry mcc="202" iso="gr"/>
+       <entry mcc="204" iso="nl"/>
+       <entry mcc="206" iso="be"/>
+       <entry mcc="208" iso="fr"/>
+       <entry mcc="212" iso="mc"/>
+       <entry mcc="213" iso="ad"/>
+       <entry mcc="214" iso="es"/>
+       <entry mcc="216" iso="hu"/>
+       <entry mcc="218" iso="ba"/>
+       <entry mcc="219" iso="hr"/>
+       <entry mcc="220" iso="rs"/>
+       <entry mcc="222" iso="it"/>
+       <entry mcc="225" iso="va"/>
+       <entry mcc="226" iso="ro"/>
+       <entry mcc="228" iso="ch"/>
+       <entry mcc="230" iso="cz"/>
+       <entry mcc="231" iso="sk"/>
+       <entry mcc="232" iso="at"/>
+       <entry mcc="234" iso="gb"/>
+       <entry mcc="235" iso="gb"/>
+       <entry mcc="238" iso="dk"/>
+       <entry mcc="240" iso="se"/>
+       <entry mcc="242" iso="no"/>
+       <entry mcc="244" iso="fi"/>
+       <entry mcc="246" iso="lt"/>
+       <entry mcc="247" iso="lv"/>
+       <entry mcc="248" iso="ee"/>
+       <entry mcc="250" iso="ru"/>
+       <entry mcc="255" iso="ua"/>
+       <entry mcc="257" iso="by"/>
+       <entry mcc="259" iso="md"/>
+       <entry mcc="260" iso="pl"/>
+       <entry mcc="262" iso="de"/>
+       <entry mcc="266" iso="gi"/>
+       <entry mcc="268" iso="pt"/>
+       <entry mcc="270" iso="lu"/>
+       <entry mcc="272" iso="ie"/>
+       <entry mcc="274" iso="is"/>
+       <entry mcc="276" iso="al"/>
+       <entry mcc="278" iso="mt"/>
+       <entry mcc="280" iso="cy"/>
+       <entry mcc="282" iso="ge"/>
+       <entry mcc="283" iso="am"/>
+       <entry mcc="284" iso="bg"/>
+       <entry mcc="286" iso="tr"/>
+       <entry mcc="288" iso="fo"/>
+       <entry mcc="289" iso="ge"/>
+       <entry mcc="290" iso="gl"/>
+       <entry mcc="292" iso="sm"/>
+       <entry mcc="293" iso="si"/>
+       <entry mcc="294" iso="mk"/>
+       <entry mcc="295" iso="li"/>
+       <entry mcc="297" iso="me"/>
+       <entry mcc="302" iso="ca"/>
+       <entry mcc="308" iso="pm"/>
+       <entry mcc="310" iso="us"/>
+       <entry mcc="311" iso="us"/>
+       <entry mcc="312" iso="us"/>
+       <entry mcc="313" iso="us"/>
+       <entry mcc="314" iso="us"/>
+       <entry mcc="315" iso="us"/>
+       <entry mcc="316" iso="us"/>
+       <entry mcc="330" iso="pr"/>
+       <entry mcc="332" iso="vi"/>
+       <entry mcc="334" iso="mx"/>
+       <entry mcc="338" iso="jm"/>
+       <entry mcc="340" iso="gp"/>
+       <entry mcc="342" iso="bb"/>
+       <entry mcc="344" iso="ag"/>
+       <entry mcc="346" iso="ky"/>
+       <entry mcc="348" iso="vg"/>
+       <entry mcc="350" iso="bm"/>
+       <entry mcc="352" iso="gd"/>
+       <entry mcc="354" iso="ms"/>
+       <entry mcc="356" iso="kn"/>
+       <entry mcc="358" iso="lc"/>
+       <entry mcc="360" iso="vc"/>
+       <entry mcc="362" iso="ai"/>
+       <entry mcc="363" iso="aw"/>
+       <entry mcc="364" iso="bs"/>
+       <entry mcc="365" iso="ai"/>
+       <entry mcc="366" iso="dm"/>
+       <entry mcc="368" iso="cu"/>
+       <entry mcc="370" iso="do"/>
+       <entry mcc="372" iso="ht"/>
+       <entry mcc="374" iso="tt"/>
+       <entry mcc="376" iso="tc"/>
+       <entry mcc="400" iso="az"/>
+       <entry mcc="401" iso="kz"/>
+       <entry mcc="402" iso="bt"/>
+       <entry mcc="404" iso="in"/>
+       <entry mcc="405" iso="in"/>
+       <entry mcc="410" iso="pk"/>
+       <entry mcc="412" iso="af"/>
+       <entry mcc="413" iso="lk"/>
+       <entry mcc="414" iso="mm"/>
+       <entry mcc="415" iso="lb"/>
+       <entry mcc="416" iso="jo"/>
+       <entry mcc="417" iso="sy"/>
+       <entry mcc="418" iso="iq"/>
+       <entry mcc="419" iso="kw"/>
+       <entry mcc="420" iso="sa"/>
+       <entry mcc="421" iso="ye"/>
+       <entry mcc="422" iso="om"/>
+       <entry mcc="423" iso="ps"/>
+       <entry mcc="424" iso="ae"/>
+       <entry mcc="425" iso="il"/>
+       <entry mcc="426" iso="bh"/>
+       <entry mcc="427" iso="qa"/>
+       <entry mcc="428" iso="mn"/>
+       <entry mcc="429" iso="np"/>
+       <entry mcc="430" iso="ae"/>
+       <entry mcc="431" iso="ae"/>
+       <entry mcc="432" iso="ir"/>
+       <entry mcc="434" iso="uz"/>
+       <entry mcc="436" iso="tj"/>
+       <entry mcc="437" iso="kg"/>
+       <entry mcc="438" iso="tm"/>
+       <entry mcc="440" iso="jp"/>
+       <entry mcc="441" iso="jp"/>
+       <entry mcc="450" iso="kr"/>
+       <entry mcc="452" iso="vn"/>
+       <entry mcc="454" iso="hk"/>
+       <entry mcc="455" iso="mo"/>
+       <entry mcc="456" iso="kh"/>
+       <entry mcc="457" iso="la"/>
+       <entry mcc="460" iso="cn"/>
+       <entry mcc="461" iso="cn"/>
+       <entry mcc="466" iso="tw"/>
+       <entry mcc="467" iso="kp"/>
+       <entry mcc="470" iso="bd"/>
+       <entry mcc="472" iso="mv"/>
+       <entry mcc="502" iso="my"/>
+       <entry mcc="505" iso="au"/>
+       <entry mcc="510" iso="id"/>
+       <entry mcc="514" iso="tl"/>
+       <entry mcc="515" iso="ph"/>
+       <entry mcc="520" iso="th"/>
+       <entry mcc="525" iso="sg"/>
+       <entry mcc="528" iso="bn"/>
+       <entry mcc="530" iso="nz"/>
+       <entry mcc="534" iso="mp"/>
+       <entry mcc="535" iso="gu"/>
+       <entry mcc="536" iso="nr"/>
+       <entry mcc="537" iso="pg"/>
+       <entry mcc="539" iso="to"/>
+       <entry mcc="540" iso="sb"/>
+       <entry mcc="541" iso="vu"/>
+       <entry mcc="542" iso="fj"/>
+       <entry mcc="543" iso="wf"/>
+       <entry mcc="544" iso="as"/>
+       <entry mcc="545" iso="ki"/>
+       <entry mcc="546" iso="nc"/>
+       <entry mcc="547" iso="pf"/>
+       <entry mcc="548" iso="ck"/>
+       <entry mcc="549" iso="ws"/>
+       <entry mcc="550" iso="fm"/>
+       <entry mcc="551" iso="mh"/>
+       <entry mcc="552" iso="pw"/>
+       <entry mcc="602" iso="eg"/>
+       <entry mcc="603" iso="dz"/>
+       <entry mcc="604" iso="ma"/>
+       <entry mcc="605" iso="tn"/>
+       <entry mcc="606" iso="ly"/>
+       <entry mcc="607" iso="gm"/>
+       <entry mcc="608" iso="sn"/>
+       <entry mcc="609" iso="mr"/>
+       <entry mcc="610" iso="ml"/>
+       <entry mcc="611" iso="gn"/>
+       <entry mcc="612" iso="ci"/>
+       <entry mcc="613" iso="bf"/>
+       <entry mcc="614" iso="ne"/>
+       <entry mcc="615" iso="tg"/>
+       <entry mcc="616" iso="bj"/>
+       <entry mcc="617" iso="mu"/>
+       <entry mcc="618" iso="lr"/>
+       <entry mcc="619" iso="sl"/>
+       <entry mcc="620" iso="gh"/>
+       <entry mcc="621" iso="ng"/>
+       <entry mcc="622" iso="td"/>
+       <entry mcc="623" iso="cf"/>
+       <entry mcc="624" iso="cm"/>
+       <entry mcc="625" iso="cv"/>
+       <entry mcc="626" iso="st"/>
+       <entry mcc="627" iso="gq"/>
+       <entry mcc="628" iso="ga"/>
+       <entry mcc="629" iso="cg"/>
+       <entry mcc="630" iso="cg"/>
+       <entry mcc="631" iso="ao"/>
+       <entry mcc="632" iso="gw"/>
+       <entry mcc="633" iso="sc"/>
+       <entry mcc="634" iso="sd"/>
+       <entry mcc="635" iso="rw"/>
+       <entry mcc="636" iso="et"/>
+       <entry mcc="637" iso="so"/>
+       <entry mcc="638" iso="dj"/>
+       <entry mcc="639" iso="ke"/>
+       <entry mcc="640" iso="tz"/>
+       <entry mcc="641" iso="ug"/>
+       <entry mcc="642" iso="bi"/>
+       <entry mcc="643" iso="mz"/>
+       <entry mcc="645" iso="zm"/>
+       <entry mcc="646" iso="mg"/>
+       <entry mcc="647" iso="re"/>
+       <entry mcc="648" iso="zw"/>
+       <entry mcc="649" iso="na"/>
+       <entry mcc="650" iso="mw"/>
+       <entry mcc="651" iso="ls"/>
+       <entry mcc="652" iso="bw"/>
+       <entry mcc="653" iso="sz"/>
+       <entry mcc="654" iso="km"/>
+       <entry mcc="655" iso="za"/>
+       <entry mcc="657" iso="er"/>
+       <entry mcc="702" iso="bz"/>
+       <entry mcc="704" iso="gt"/>
+       <entry mcc="706" iso="sv"/>
+       <entry mcc="708" iso="hn"/>
+       <entry mcc="710" iso="ni"/>
+       <entry mcc="712" iso="cr"/>
+       <entry mcc="714" iso="pa"/>
+       <entry mcc="716" iso="pe"/>
+       <entry mcc="722" iso="ar"/>
+       <entry mcc="724" iso="br"/>
+       <entry mcc="730" iso="cl"/>
+       <entry mcc="732" iso="co"/>
+       <entry mcc="734" iso="ve"/>
+       <entry mcc="736" iso="bo"/>
+       <entry mcc="738" iso="gy"/>
+       <entry mcc="740" iso="ec"/>
+       <entry mcc="742" iso="gf"/>
+       <entry mcc="744" iso="py"/>
+       <entry mcc="746" iso="sr"/>
+       <entry mcc="748" iso="uy"/>
+       <entry mcc="750" iso="fk"/>
+</mcctable>
\ No newline at end of file
diff --git a/src/citylist.c b/src/citylist.c
deleted file mode 100644 (file)
index 76693e3..0000000
+++ /dev/null
@@ -1,733 +0,0 @@
-/*
- * tel-plugin-nitz
- *
- * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <glib.h>
-
-#include <tcore.h>
-
-#include "common.h"
-#include "citylist.h"
-
-static NITZ_MCC_TZFILE_MAP nitz_table_mcc_tzfile[] =
-{
-       { 202,  "GR", -1, +2, +1, "Europe/Athens" },    // Greece -- Athens
-       { 204,  "NL", -1, +1, +1, "Europe/Amsterdam" }, // Netherlands -- Amsterdam
-       { 206,  "BE", -1, +1, +1, "Europe/Brussels" },  // Belgium -- Brussels
-       { 208,  "FR", -1, +1, +1, "Europe/Paris" },     // France -- Paris
-       { 212,  "MC", -1, +1, +1, "Europe/Monaco" },    // Monaco -- Monaco
-       { 213,  "AD", -1, +1, +1, "Europe/Andorra" },   // Andorra -- Andorra la Vella
-
-       { 214,  "ES",  0, +1, +1, "Europe/Madrid" },    // Spain -- Madrid
-       { 214,  "ES",  1, +1, +1, "Africa/Ceuta" },     //
-       { 214,  "ES",  2,  0, +1, "Atlantic/Canary" },  //
-
-       { 216,  "HU", -1, 0, 0, "Europe/Budapest" },    // Hungary -- Budapest
-       { 218,  "BA", -1, 0, 0, "Europe/Sarajevo" },    // Bosnia and Herzegovina -- Sarajevo
-       { 219,  "HR", -1, 0, 0, "Europe/Zagreb" },      // Croatia -- Zagreb
-       { 220,  "RS", -1, 0, 0, "Europe/Belgrade" },    // Serbia -- Belgrade
-       { 222,  "IT", -1, 0, 0, "Europe/Rome" },        // Italy -- Rome
-       { 225,  "VA", -1, 0, 0, "Europe/Vatican" },
-       { 226,  "RO", -1, 0, 0, "Europe/Bucharest" },   // Romania -- Bucharest
-       { 228,  "CH", -1, 0, 0, "Europe/Zurich" },      // Switzerland -- Bern
-       { 230,  "CZ", -1, 0, 0, "Europe/Prague" },      // Czech Republic -- Prague
-       { 231,  "SK", -1, 0, 0, "Europe/Bratislava" },  // Slovak Republic -- Bratislava
-       { 232,  "AT", -1, 0, 0, "Europe/Vienna" },      // Austria -- Vienna
-       { 234,  "GB", -1, 0, 0, "Europe/London" },      // United Kingdom -- London
-       { 235,  "GB", -1, 0, 0, "Europe/London" },      // United Kingdom -- London
-       { 238,  "DK", -1, 0, 0, "Europe/Copenhagen" },  // Denmark -- Copenhagen
-       { 240,  "SE", -1, 0, 0, "Europe/Stockholm" },   // Sweden -- Stockholm
-       { 242,  "NO", -1, 0, 0, "Europe/Oslo" },        // Norway -- Oslo
-       { 244,  "FI", -1, 0, 0, "Europe/Helsinki" },    // Finland -- Helsinki
-       { 246,  "LT", -1, 0, 0, "Europe/Vilnius" },     // Lithuania -- Vilnius
-       { 247,  "LV", -1, 0, 0, "Europe/Riga" },        // Latvia -- Riga
-       { 248,  "EE", -1, 0, 0, "Europe/Tallinn" },     // Estonia -- Tallinn
-
-       { 250,  "RU",  0,  +3, +1, "Europe/Moscow" },           // Russia -- Moscow+00
-       { 250,  "RU",  1,  +2, +1, "Europe/Kaliningrad" },      // Russia -- Moscow-01
-       { 250,  "RU",  2,  +3, +1, "Europe/Volgograd" },        // Russia -- Moscow+00
-       { 250,  "RU",  3,  +3, +1, "Europe/Samara" },           // Russia -- Moscow
-       { 250,  "RU",  4,  +5, +1, "Asia/Yekaterinburg" },      // Russia -- Moscow+02
-       { 250,  "RU",  5,  +6, +1, "Asia/Omsk" },               // Russia -- Moscow+03
-       { 250,  "RU",  6,  +6, +1, "Asia/Novosibirsk" },        // Russia -- Moscow+03
-       { 250,  "RU",  7,  +6, +1, "Asia/Novokuznetsk" },       // Russia -- Moscow+03
-       { 250,  "RU",  8,  +7, +1, "Asia/Krasnoyarsk" },        // Russia -- Moscow+04
-       { 250,  "RU",  9,  +8, +1, "Asia/Irkutsk" },            // Russia -- Moscow+05
-       { 250,  "RU", 10,  +9, +1, "Asia/Yakutsk" },            // Russia -- Moscow+06
-       { 250,  "RU", 11, +10, +1, "Asia/Vladivostok" },        // Russia -- Moscow+07
-       { 250,  "RU", 12, +10, +1, "Asia/Sakhalin" },           // Russia -- Moscow+07
-       { 250,  "RU", 13, +11, +1, "Asia/Magadan" },            // Russia -- Moscow+08
-       { 250,  "RU", 14, +11, +1, "Asia/Kamchatka" },          // Russia -- Moscow+08
-       { 250,  "RU", 15, +11, +1, "Asia/Anadyr" },             // Russia -- Moscow+08
-
-       { 255,  "UA",  0, +2, +1, "Europe/Kiev" },              // Ukraine -- Kiev
-       { 255,  "UA",  1, +2, +1, "Europe/Uzhgorod" },          // Ukraine --
-       { 255,  "UA",  2, +2, +1, "Europe/Zaporozhye" },        // Ukraine --
-       { 255,  "UA",  3, +2, +1, "Europe/Simferopol" },        // Ukraine --
-
-       { 257,  "BY", -1, 0, 0, "Europe/Minsk" },               // Belarus Republic -- Minsk
-       { 259,  "MD", -1, 0, 0, "Europe/Chisinau" },            // Moldova -- Kishinev(Chisinau)
-       { 260,  "PL", -1, 0, 0, "Europe/Warsaw" },              // Poland -- Warsaw
-       { 262,  "DE", -1, 0, 0, "Europe/Berlin" },              // Germany -- Berlin
-       { 266,  "GI", -1, 0, 0, "Europe/Gibraltar" },           // Gibraltar -- Gibraltar
-
-       { 268,  "PT",  0, +0, +1, "Europe/Lisbon" },    // Portugal -- Lisbon
-       { 268,  "PT",  1, +0, +1, "Atlantic/Madeira" }, //
-       { 268,  "PT",  2, -1, +1, "Atlantic/Azores" },  //
-
-       { 270,  "LU", -1, 0, 0, "Europe/Luxembourg" },  // Luxembourg -- Luxembourg
-       { 272,  "IE", -1, 0, 0, "Europe/Dublin" },      // Ireland -- Dublin
-       { 274,  "IS", -1, 0, 0, "Atlantic/Reykjavik" }, // Iceland -- Reykjavik
-       { 276,  "AL", -1, 0, 0, "Europe/Tirane" },      // Albania -- Tirane
-       { 278,  "MT", -1, 0, 0, "Europe/Malta" },       // Malta -- Valletta
-       { 280,  "CY", -1, 0, 0, "Asia/Nicosia" },       // Cyprus -- Nicosia
-       { 282,  "GE", -1, 0, 0, "Asia/Tbilisi" },       // Georgia -- Tbilisi
-       { 283,  "AM", -1, 0, 0, "Asia/Yerevan" },       // Armenia -- Yerevan
-       { 284,  "BG", -1, 0, 0, "Europe/Sofia" },       // Bulgaria -- Sofia
-       { 286,  "TR", -1, 0, 0, "Europe/Istanbul" },    // Turkey -- Ankara
-       { 288,  "FO", -1, 0, 0, "Atlantic/Faroe" },     // Faroe Islands -- Torshavn
-
-       { 290,  "GL",  0, -3, +1, "America/Godthab" },  // Greenland -- Nuuk                                                            /*!*/
-       { 290,  "GL",  1, +0, +0, "America/Danmarkshavn" },     //
-       { 290,  "GL",  2, -1, +1, "America/Scoresbysund" },     //
-       { 290,  "GL",  3, -4, +1, "America/Thule" },            //
-
-       { 292,  "SM", -1, 0, 0, "Europe/San_Marino" },  // San Marino -- San Marino
-       { 293,  "SI", -1, 0, 0, "Europe/Ljubljana" },   // Slovenia -- Ljubljana
-       { 294,  "MK", -1, 0, 0, "Europe/Skopje" },      // Macedonia -- Skopje
-       { 295,  "LI", -1, 0, 0, "Europe/Vaduz" },       // Liechtenstein -- Vaduz
-       { 297,  "ME", -1, 0, 0, "Europe/Podgorica" },   // Montenegro -- Podgorica
-
-       { 302,  "CA",  0, -4, +1, "America/St_Johns" },         //
-       { 302,  "CA",  1, -4, +1, "America/Halifax" },          //
-       { 302,  "CA",  2, -4, +1, "America/Glace_Bay" },        //
-       { 302,  "CA",  3, -4, +1, "America/Moncton" },          //
-       { 302,  "CA",  4, -4, +1, "America/Goose_Bay" },        //
-       { 302,  "CA",  5, -4, +0, "America/Blanc-Sablon" },     //
-       { 302,  "CA",  6, -5, +1, "America/Montreal" },         //
-       { 302,  "CA",  7, -5, +1, "America/Toronto" },          //Canada -- Ottawa                                                                      /*!*/
-       { 302,  "CA",  8, -5, +1, "America/Nipigon" },          //
-       { 302,  "CA",  9, -5, +1, "America/Thunder_Bay" },      //
-       { 302,  "CA", 10, -5, +1, "America/Iqaluit" },          //
-       { 302,  "CA", 11, -5, +1, "America/Pangnirtung" },      //
-       { 302,  "CA", 12, -6, +1, "America/Resolute" },         //
-       { 302,  "CA", 13, -6, +1, "America/Atikokan" },         //
-       { 302,  "CA", 14, -6, +1, "America/Rankin_Inlet" },     //
-       { 302,  "CA", 15, -6, +1, "America/Winnipeg" },         //
-       { 302,  "CA", 16, -6, +1, "America/Rainy_River" },      //
-       { 302,  "CA", 17, -6, +0, "America/Regina" },           //
-       { 302,  "CA", 18, -8, +1, "America/Swift_Current" },    //
-       { 302,  "CA", 19, -7, +1, "America/Edmonton" },         //
-       { 302,  "CA", 20, -7, +1, "America/Cambridge_Bay" },    //
-       { 302,  "CA", 21, -7, +1, "America/Yellowknife" },      //
-       { 302,  "CA", 22, -7, +1, "America/Inuvik" },           //
-       { 302,  "CA", 23, -7, +0, "America/Dawson_Creek" },     //
-       { 302,  "CA", 24, -8, +1, "America/Vancouver" },        //
-       { 302,  "CA", 25, -8, +1, "America/Whitehorse" },       //
-       { 302,  "CA", 26, -8, +1, "America/Dawson" },           //
-
-       { 308,  "PM", -1, 0, 0, "America/Miquelon" },   // Saint Pierre and Miquelon -- Saint-Pierre
-
-       { 310,  "US",  0,  -5, +1, "America/New_York" },        // U.S.A                                                                                        /*!*/
-       { 310,  "US",  1,  -5, +1, "America/Detroit" },                 //
-       { 310,  "US",  2,  -5, +1, "America/Kentucky/Louisville" },     //
-       { 310,  "US",  3,  -5, +1, "America/Kentucky/Monticello" },     //
-       { 310,  "US",  4,  -5, +1, "America/Indiana/Indianapolis" },    //
-       { 310,  "US",  5,  -5, +1, "America/Indiana/Vincennes" },       //
-       { 310,  "US",  6,  -5, +1, "America/Indiana/Winamac" },         //
-       { 310,  "US",  7,  -5, +1, "America/Indiana/Marengo" },         //
-       { 310,  "US",  8,  -5, +1, "America/Indiana/Petersburg" },      //
-       { 310,  "US",  9,  -5, +1, "America/Indiana/Vevay" },           //
-       { 310,  "US", 10,  -6, +1, "America/Chicago" },                 //
-       { 310,  "US", 11,  -6, +1, "America/Indiana/Tell_City" },       //
-       { 310,  "US", 12,  -6, +1, "America/Indiana/Knox" },            //
-       { 310,  "US", 13,  -6, +1, "America/Menominee" },               //
-       { 310,  "US", 14,  -6, +1, "America/North_Dakota/Center" },     //
-       { 310,  "US", 15,  -6, +1, "America/North_Dakota/New_Salem" },  //
-       { 310,  "US", 16,  -7, +1, "America/Denver" },          //
-       { 310,  "US", 17,  -7, +1, "America/Boise" },           //
-       { 310,  "US", 18,  -7, +1, "America/Shiprock" },        //
-       { 310,  "US", 19,  -7, +0, "America/Phoenix" },         //
-       { 310,  "US", 20,  -8, +1, "America/Los_Angeles" },     //
-       { 310,  "US", 21,  -9, +1, "America/Anchorage" },       // = Alaska
-       { 310,  "US", 22,  -9, +1, "America/Juneau" },          //
-       { 310,  "US", 23,  -9, +1, "America/Yakutat" },         //
-       { 310,  "US", 24,  -9, +1, "America/Nome" },            //
-       { 310,  "US", 25, -10, +1, "America/Adak" },            //
-       { 310,  "US", 26, -10, +0, "Pacific/Honolulu" },        //
-
-       { 311,  "US",  0,  -5, +1, "America/New_York" },        // U.S.A                                                                                        /*!*/
-       { 311,  "US",  1,  -5, +1, "America/Detroit" },         //
-       { 311,  "US",  2,  -5, +1, "America/Kentucky/Louisville" },     //
-       { 311,  "US",  3,  -5, +1, "America/Kentucky/Monticello" },     //
-       { 311,  "US",  4,  -5, +1, "America/Indiana/Indianapolis" },    //
-       { 311,  "US",  5,  -5, +1, "America/Indiana/Vincennes" },       //
-       { 311,  "US",  6,  -5, +1, "America/Indiana/Winamac" },         //
-       { 311,  "US",  7,  -5, +1, "America/Indiana/Marengo" },         //
-       { 311,  "US",  8,  -5, +1, "America/Indiana/Petersburg" },      //
-       { 311,  "US",  9,  -5, +1, "America/Indiana/Vevay" },           //
-       { 311,  "US", 10,  -6, +1, "America/Chicago" },                 //
-       { 311,  "US", 11,  -6, +1, "America/Indiana/Tell_City" },       //
-       { 311,  "US", 12,  -6, +1, "America/Indiana/Knox" },            //
-       { 311,  "US", 13,  -6, +1, "America/Menominee" },               //
-       { 311,  "US", 14,  -6, +1, "America/North_Dakota/Center" },     //
-       { 311,  "US", 15,  -6, +1, "America/North_Dakota/New_Salem" },  //
-       { 311,  "US", 16,  -7, +1, "America/Denver" },          //
-       { 311,  "US", 17,  -7, +1, "America/Boise" },           //
-       { 311,  "US", 18,  -7, +1, "America/Shiprock" },        //
-       { 311,  "US", 19,  -7, +0, "America/Phoenix" },         //
-       { 311,  "US", 20,  -8, +1, "America/Los_Angeles" },     //
-       { 311,  "US", 21,  -9, +1, "America/Anchorage" },       //
-       { 311,  "US", 22,  -9, +1, "America/Juneau" },          //
-       { 311,  "US", 23,  -9, +1, "America/Yakutat" },         //
-       { 311,  "US", 24,  -9, +1, "America/Nome" },            //
-       { 311,  "US", 25, -10, +1, "America/Adak" },            //
-       { 311,  "US", 26, -10, +0, "Pacific/Honolulu" },        //
-
-       { 312,  "US",  0,  -5, +1, "America/New_York" },        // U.S.A                                                                                        /*!*/
-       { 312,  "US",  1,  -5, +1, "America/Detroit" },         //
-       { 312,  "US",  2,  -5, +1, "America/Kentucky/Louisville" },     //
-       { 312,  "US",  3,  -5, +1, "America/Kentucky/Monticello" },     //
-       { 312,  "US",  4,  -5, +1, "America/Indiana/Indianapolis" },    //
-       { 312,  "US",  5,  -5, +1, "America/Indiana/Vincennes" },       //
-       { 312,  "US",  6,  -5, +1, "America/Indiana/Winamac" },         //
-       { 312,  "US",  7,  -5, +1, "America/Indiana/Marengo" },         //
-       { 312,  "US",  8,  -5, +1, "America/Indiana/Petersburg" },      //
-       { 312,  "US",  9,  -5, +1, "America/Indiana/Vevay" },           //
-       { 312,  "US", 10,  -6, +1, "America/Chicago" },                 //
-       { 312,  "US", 11,  -6, +1, "America/Indiana/Tell_City" },       //
-       { 312,  "US", 12,  -6, +1, "America/Indiana/Knox" },            //
-       { 312,  "US", 13,  -6, +1, "America/Menominee" },               //
-       { 312,  "US", 14,  -6, +1, "America/North_Dakota/Center" },     //
-       { 312,  "US", 15,  -6, +1, "America/North_Dakota/New_Salem" },  //
-       { 312,  "US", 16,  -7, +1, "America/Denver" },          //
-       { 312,  "US", 17,  -7, +1, "America/Boise" },           //
-       { 312,  "US", 18,  -7, +1, "America/Shiprock" },        //
-       { 312,  "US", 19,  -7, +0, "America/Phoenix" },         //
-       { 312,  "US", 20,  -8, +1, "America/Los_Angeles" },     //
-       { 312,  "US", 21,  -9, +1, "America/Anchorage" },       //
-       { 312,  "US", 22,  -9, +1, "America/Juneau" },          //
-       { 312,  "US", 23,  -9, +1, "America/Yakutat" },         //
-       { 312,  "US", 24,  -9, +1, "America/Nome" },            //
-       { 312,  "US", 25, -10, +1, "America/Adak" },            //
-       { 312,  "US", 26, -10, +0, "Pacific/Honolulu" },        //
-
-       { 313,  "US",  0,  -5, +1, "America/New_York" },        // U.S.A                                                                                        /*!*/
-       { 313,  "US",  1,  -5, +1, "America/Detroit" },         //
-       { 313,  "US",  2,  -5, +1, "America/Kentucky/Louisville" },     //
-       { 313,  "US",  3,  -5, +1, "America/Kentucky/Monticello" },     //
-       { 313,  "US",  4,  -5, +1, "America/Indiana/Indianapolis" },    //
-       { 313,  "US",  5,  -5, +1, "America/Indiana/Vincennes" },       //
-       { 313,  "US",  6,  -5, +1, "America/Indiana/Winamac" },         //
-       { 313,  "US",  7,  -5, +1, "America/Indiana/Marengo" },         //
-       { 313,  "US",  8,  -5, +1, "America/Indiana/Petersburg" },      //
-       { 313,  "US",  9,  -5, +1, "America/Indiana/Vevay" },           //
-       { 313,  "US", 10,  -6, +1, "America/Chicago" },                 //
-       { 313,  "US", 11,  -6, +1, "America/Indiana/Tell_City" },       //
-       { 313,  "US", 12,  -6, +1, "America/Indiana/Knox" },            //
-       { 313,  "US", 13,  -6, +1, "America/Menominee" },               //
-       { 313,  "US", 14,  -6, +1, "America/North_Dakota/Center" },     //
-       { 313,  "US", 15,  -6, +1, "America/North_Dakota/New_Salem" },  //
-       { 313,  "US", 16,  -7, +1, "America/Denver" },          //
-       { 313,  "US", 17,  -7, +1, "America/Boise" },           //
-       { 313,  "US", 18,  -7, +1, "America/Shiprock" },        //
-       { 313,  "US", 19,  -7, +0, "America/Phoenix" },         //
-       { 313,  "US", 20,  -8, +1, "America/Los_Angeles" },     //
-       { 313,  "US", 21,  -9, +1, "America/Anchorage" },       //
-       { 313,  "US", 22,  -9, +1, "America/Juneau" },          //
-       { 313,  "US", 23,  -9, +1, "America/Yakutat" },         //
-       { 313,  "US", 24,  -9, +1, "America/Nome" },            //
-       { 313,  "US", 25, -10, +1, "America/Adak" },            //
-       { 313,  "US", 26, -10, +0, "Pacific/Honolulu" },        //
-
-       { 314,  "US",  0,  -5, +1, "America/New_York" },        // U.S.A                                                                                        /*!*/
-       { 314,  "US",  1,  -5, +1, "America/Detroit" },         //
-       { 314,  "US",  2,  -5, +1, "America/Kentucky/Louisville" },     //
-       { 314,  "US",  3,  -5, +1, "America/Kentucky/Monticello" },     //
-       { 314,  "US",  4,  -5, +1, "America/Indiana/Indianapolis" },    //
-       { 314,  "US",  5,  -5, +1, "America/Indiana/Vincennes" },       //
-       { 314,  "US",  6,  -5, +1, "America/Indiana/Winamac" },         //
-       { 314,  "US",  7,  -5, +1, "America/Indiana/Marengo" },         //
-       { 314,  "US",  8,  -5, +1, "America/Indiana/Petersburg" },      //
-       { 314,  "US",  9,  -5, +1, "America/Indiana/Vevay" },           //
-       { 314,  "US", 10,  -6, +1, "America/Chicago" },                 //
-       { 314,  "US", 11,  -6, +1, "America/Indiana/Tell_City" },       //
-       { 314,  "US", 12,  -6, +1, "America/Indiana/Knox" },            //
-       { 314,  "US", 13,  -6, +1, "America/Menominee" },               //
-       { 314,  "US", 14,  -6, +1, "America/North_Dakota/Center" },     //
-       { 314,  "US", 15,  -6, +1, "America/North_Dakota/New_Salem" },  //
-       { 314,  "US", 16,  -7, +1, "America/Denver" },          //
-       { 314,  "US", 17,  -7, +1, "America/Boise" },           //
-       { 314,  "US", 18,  -7, +1, "America/Shiprock" },        //
-       { 314,  "US", 19,  -7, +0, "America/Phoenix" },         //
-       { 314,  "US", 20,  -8, +1, "America/Los_Angeles" },     //
-       { 314,  "US", 21,  -9, +1, "America/Anchorage" },       //
-       { 314,  "US", 22,  -9, +1, "America/Juneau" },          //
-       { 314,  "US", 23,  -9, +1, "America/Yakutat" },         //
-       { 314,  "US", 24,  -9, +1, "America/Nome" },            //
-       { 314,  "US", 25, -10, +1, "America/Adak" },            //
-       { 314,  "US", 26, -10, +0, "Pacific/Honolulu" },        //
-
-       { 315,  "US",  0,  -5, +1, "America/New_York" },        // U.S.A                                                                                        /*!*/
-       { 315,  "US",  1,  -5, +1, "America/Detroit" },         //
-       { 315,  "US",  2,  -5, +1, "America/Kentucky/Louisville" },     //
-       { 315,  "US",  3,  -5, +1, "America/Kentucky/Monticello" },     //
-       { 315,  "US",  4,  -5, +1, "America/Indiana/Indianapolis" },    //
-       { 315,  "US",  5,  -5, +1, "America/Indiana/Vincennes" },       //
-       { 315,  "US",  6,  -5, +1, "America/Indiana/Winamac" },         //
-       { 315,  "US",  7,  -5, +1, "America/Indiana/Marengo" },         //
-       { 315,  "US",  8,  -5, +1, "America/Indiana/Petersburg" },      //
-       { 315,  "US",  9,  -5, +1, "America/Indiana/Vevay" },           //
-       { 315,  "US", 10,  -6, +1, "America/Chicago" },                 //
-       { 315,  "US", 11,  -6, +1, "America/Indiana/Tell_City" },       //
-       { 315,  "US", 12,  -6, +1, "America/Indiana/Knox" },            //
-       { 315,  "US", 13,  -6, +1, "America/Menominee" },               //
-       { 315,  "US", 14,  -6, +1, "America/North_Dakota/Center" },     //
-       { 315,  "US", 15,  -6, +1, "America/North_Dakota/New_Salem" },  //
-       { 315,  "US", 16,  -7, +1, "America/Denver" },          //
-       { 315,  "US", 17,  -7, +1, "America/Boise" },           //
-       { 315,  "US", 18,  -7, +1, "America/Shiprock" },        //
-       { 315,  "US", 19,  -7, +0, "America/Phoenix" },         //
-       { 315,  "US", 20,  -8, +1, "America/Los_Angeles" },     //
-       { 315,  "US", 21,  -9, +1, "America/Anchorage" },       //
-       { 315,  "US", 22,  -9, +1, "America/Juneau" },          //
-       { 315,  "US", 23,  -9, +1, "America/Yakutat" },         //
-       { 315,  "US", 24,  -9, +1, "America/Nome" },            //
-       { 315,  "US", 25, -10, +1, "America/Adak" },            //
-       { 315,  "US", 26, -10, +0, "Pacific/Honolulu" },        //
-
-       { 316,  "US",  0,  -5, +1, "America/New_York" },        // U.S.A                                                                                        /*!*/
-       { 316,  "US",  1,  -5, +1, "America/Detroit" },         //
-       { 316,  "US",  2,  -5, +1, "America/Kentucky/Louisville" },     //
-       { 316,  "US",  3,  -5, +1, "America/Kentucky/Monticello" },     //
-       { 316,  "US",  4,  -5, +1, "America/Indiana/Indianapolis" },    //
-       { 316,  "US",  5,  -5, +1, "America/Indiana/Vincennes" },       //
-       { 316,  "US",  6,  -5, +1, "America/Indiana/Winamac" },         //
-       { 316,  "US",  7,  -5, +1, "America/Indiana/Marengo" },         //
-       { 316,  "US",  8,  -5, +1, "America/Indiana/Petersburg" },      //
-       { 316,  "US",  9,  -5, +1, "America/Indiana/Vevay" },           //
-       { 316,  "US", 10,  -6, +1, "America/Chicago" },                 //
-       { 316,  "US", 11,  -6, +1, "America/Indiana/Tell_City" },       //
-       { 316,  "US", 12,  -6, +1, "America/Indiana/Knox" },            //
-       { 316,  "US", 13,  -6, +1, "America/Menominee" },               //
-       { 316,  "US", 14,  -6, +1, "America/North_Dakota/Center" },     //
-       { 316,  "US", 15,  -6, +1, "America/North_Dakota/New_Salem" },  //
-       { 316,  "US", 16,  -7, +1, "America/Denver" },          //
-       { 316,  "US", 17,  -7, +1, "America/Boise" },           //
-       { 316,  "US", 18,  -7, +1, "America/Shiprock" },        //
-       { 316,  "US", 19,  -7, +0, "America/Phoenix" },         //
-       { 316,  "US", 20,  -8, +1, "America/Los_Angeles" },     //
-       { 316,  "US", 21,  -9, +1, "America/Anchorage" },       //
-       { 316,  "US", 22,  -9, +1, "America/Juneau" },          //
-       { 316,  "US", 23,  -9, +1, "America/Yakutat" },         //
-       { 316,  "US", 24,  -9, +1, "America/Nome" },            //
-       { 316,  "US", 25, -10, +1, "America/Adak" },            //
-       { 316,  "US", 26, -10, +0, "Pacific/Honolulu" },        //
-
-       { 330,  "PR", -1, 0, 0, "America/Puerto_Rico" },        // Puerto Rico -- San Juan
-       { 332,  "VI", -1, 0, 0, "America/St_Thomas" },          // United States Virgin Islands -- Charlotte Amalie     /*!*/
-
-       { 334,  "MX",  0, -6, +1, "America/Mexico_City" },      // Mexico -- Mexico City
-       { 334,  "MX",  1, -6, +1, "America/Cancun" },           //
-       { 334,  "MX",  2, -6, +1, "America/Merida" },           //
-       { 334,  "MX",  3, -6, +1, "America/Monterrey" },        //
-       { 334,  "MX",  4, -6, +1, "America/Matamoros" },        //
-       { 334,  "MX",  5, -7, +1, "America/Mazatlan" },         //
-       { 334,  "MX",  6, -7, +1, "America/Chihuahua" },        //
-       { 334,  "MX",  7, -6, +1, "America/Ojinaga" },          //
-       { 334,  "MX",  8, -7, +0, "America/Hermosillo" },       //
-       { 334,  "MX",  9, -8, +1, "America/Tijuana" },          //
-       { 334,  "MX", 10, -6, +1, "America/Santa_Isabel" },     //
-       { 334,  "MX", 11, -7, +1, "America/Bahia_Banderas" },   //
-
-       { 338,  "JM", -1, 0, 0, "America/Jamaica" },    // Jamaica -- Kingston
-       { 340,  "GP", -1, 0, 0, "America/Guadeloupe" }, // Guadeloupe(france) -- Basse-Terre
-       { 340,  "MQ", -1, 0, 0, "America/Martinique" },
-       { 342,  "BB", -1, 0, 0, "America/Barbados" },   // Barbados -- Bridgetown
-       { 344,  "AG", -1, 0, 0, "America/Antigua" },    // Antigua & Barbuda -- Saint John's
-       { 346,  "KY", -1, 0, 0, "America/Cayman" },     // Cayman Islands -- George Town
-       { 348,  "VG", -1, 0, 0, "America/Tortola" },    // British Virgin Islands -- Road Town
-       { 350,  "BM", -1, 0, 0, "Atlantic/Bermuda" },   // Bermuda -- Hamilton
-       { 352,  "GD", -1, 0, 0, "America/Grenada" },    // Grenada -- Saint George's
-       { 354,  "MS", -1, 0, 0, "America/Montserrat" }, // Montserrat(UK) -- Plymouth
-       { 356,  "KN", -1, 0, 0, "America/St_Kitts" },   // Saint Kitts and Nevis -- Basseterre
-       { 358,  "LC", -1, 0, 0, "America/St_Lucia" },   // Saint Lucia -- Castries
-       { 360,  "VC", -1, 0, 0, "America/St_Vincent" }, // Saint Vincent and the Grenadines -- Kingstown
-       { 362,  "AN", -1, 0, 0, "America/Curacao" },    // Netherlands Antilles -- Willemstad
-       { 363,  "AW", -1, 0, 0, "America/Aruba" },      // Aruba(netherlands) -- Oranjestad
-       { 364,  "BS", -1, 0, 0, "America/Nassau" },     // Bahamas -- Nassau
-       { 365,  "AI", -1, 0, 0, "America/Antigua" },    // Anguilla -- The Valley
-       { 366,  "DM", -1, 0, 0, "America/Dominica" },   // Dominica -- Roseau
-       { 368,  "CU", -1, 0, 0, "America/Havana" },             // Cuba -- Havana
-       { 370,  "DO", -1, 0, 0, "America/Santo_Domingo" },      // Dominican Republic -- Santo Domingo
-       { 372,  "HT", -1, 0, 0, "America/Port-au-Prince" },     // Haiti -- Port au Prince //world
-       { 374,  "TT", -1, 0, 0, "America/Port_of_Spain" },      // Trinidad and Tobago -- Port of Spain
-       { 376,  "TC", -1, 0, 0, "America/Grand_Turk" },         // Turks & Caicos islands(UK) -- Cockburn Town
-       { 400,  "AZ", -1, 0, 0, "Asia/Baku" },                  // Azerbaijan -- Baku
-
-       { 401,  "KZ",  0, +6, +0, "Asia/Almaty" },
-       { 401,  "KZ",  1, +5, +0, "Asia/Qyzylorda" },
-       { 401,  "KZ",  2, +5, +0, "Asia/Aqtobe" },
-       { 401,  "KZ",  3, +5, +0, "Asia/Aqtau" },
-       { 401,  "KZ",  4, +5, +0, "Asia/Oral" },
-
-       { 402,  "BT", -1, 0, 0, "Asia/Thimphu" },       // Bhutan -- Thimphu
-       { 404,  "IN", -1, 0, 0, "Asia/Kolkata" },       // India - New Delhi
-       { 405,  "IN", -1, 0, 0, "Asia/Kolkata" },       // India - New Delhi
-       { 410,  "PK", -1, 0, 0, "Asia/Karachi" },       // Pakistan -- Islamabad
-       { 412,  "AF", -1, 0, 0, "Asia/Kabul" },         // Afghanistan -- Kabul
-       { 413,  "LK", -1, 0, 0, "Asia/Colombo" },       // Sri Lanka -- Colombo
-       { 414,  "MM", -1, 0, 0, "Asia/Rangoon" },       // Myanmar -- Rangoon (Yangon)
-       { 415,  "LB", -1, 0, 0, "Asia/Beirut" },        // Lebanon -- Beirut
-       { 416,  "JO", -1, 0, 0, "Asia/Amman" },         // Jordan -- Amman
-       { 417,  "SY", -1, 0, 0, "Asia/Damascus" },      // Syria -- Damascus
-       { 418,  "IQ", -1, 0, 0, "Asia/Baghdad" },       // Iraq  -- Baghdad
-       { 419,  "KW", -1, 0, 0, "Asia/Kuwait" },        // Kuwait -- Kuwait City
-       { 420,  "SA", -1, 0, 0, "Asia/Riyadh" },        // Saudi Arabia -- Riyadh
-       { 421,  "YE", -1, 0, 0, "Asia/Aden" },          // Yemen -- Sanaa               /*!*/
-       { 422,  "OM", -1, 0, 0, "Asia/Muscat" },        // Oman -- Muscat
-       { 423,  "PS", -1, 0, 0, "Asia/Gaza" },
-       { 424,  "AE", -1, 0, 0, "Asia/Dubai" },         // United Arab Emirates -- Abu Dhabi    /*!*/
-       { 425,  "IL", -1, 0, 0, "Asia/Jerusalem" },     // Israel -- Tel Aviv                   /*!*/
-       { 426,  "BH", -1, 0, 0, "Asia/Bahrain" },       // Bahrain -- Manama
-       { 427,  "QA", -1, 0, 0, "Asia/Qatar" },         // Qatar -- Doha
-
-       { 428,  "MN",  0, +8, +0, "Asia/Ulaanbaatar" }, // Mongolia -- Ulaanbaatar
-       { 428,  "MN",  1, +7, +0, "Asia/Hovd" },        //
-       { 428,  "MN",  2, +8, +0, "Asia/Choibalsan" },  //
-
-       { 429,  "NP", -1, 0, 0, "Asia/Kathmandu" },     // Nepal -- Kathmandu
-       { 430,  "AE", -1, 0, 0, "Asia/Dubai" },         // Abu Dhabi
-       { 431,  "AE", -1, 0, 0, "Asia/Dubai" },         // Dubai
-       { 432,  "IR", -1, 0, 0, "Asia/Tehran" },        // Iran -- Tehran
-
-       { 434,  "UZ",  0, +5, +0, "Asia/Samarkand" },   // Uzbekistan -- Samarkand
-       { 434,  "UZ",  1, +5, +0, "Asia/Tashkent" },    // Uzbekistan -- Tashkent
-
-       { 436,  "TJ", -1, 0, 0, "Asia/Dushanbe" },      // Tajikistan -- Dushanbe
-       { 437,  "KG", -1, 0, 0, "Asia/Bishkek" },       // Kyrgyzstan -- Bishkek
-       { 438,  "TM", -1, 0, 0, "Asia/Ashgabat" },      // Turkmenistan -- Ashgabat
-       { 440,  "JP", -1, 0, 0, "Asia/Tokyo" },         // Japan -- Tokyo
-       { 441,  "JP", -1, 0, 0, "Asia/Tokyo" },
-       { 450,  "KR", -1, 0, 0, "Asia/Seoul" },         // South Korea -- Seoul
-       { 452,  "VN", -1, 0, 0, "Asia/Ho_Chi_Minh" },   // Vietnam -- Hanoi
-       { 454,  "HK", -1, 0, 0, "Asia/Hong_Kong" },     // Hong Kong - Hong Kong
-       { 455,  "MO", -1, 0, 0, "Asia/Macau" },         // Macau(PRC) -- ???
-       { 456,  "KH", -1, 0, 0, "Asia/Phnom_Penh" },    // Cambodia -- Phnom Penh
-       { 457,  "LA", -1, 0, 0, "Asia/Vientiane" },     // Laos -- Vientiane
-
-       { 460,  "CN",  0, +8, +0, "Asia/Shanghai" },    // China -- Beijing     /*!*/
-       { 460,  "CN",  1, +8, +0, "Asia/Harbin" },      //
-       { 460,  "CN",  2, +8, +0, "Asia/Chongqing" },   //
-       { 460,  "CN",  3, +8, +0, "Asia/Urumqi" },      //
-       { 460,  "CN",  4, +8, +0, "Asia/Kashgar" },     //
-
-       { 466,  "TW", -1, 0, 0, "Asia/Taipei" },        // Taiwan -- Taipei
-       { 467,  "KP", -1, 0, 0, "Asia/Pyongyang" },     // North Korea -- Pyongyang
-       { 470,  "BD", -1, 0, 0, "Asia/Dhaka" },         // Bangladesh -- Dhaka
-       { 472,  "MV", -1, 0, 0, "Indian/Maldives" },    // Maldives -- Male
-
-       { 502,  "MY",  0, +8, +0, "Asia/Kuala_Lumpur" },// Malaysia -- Kuala Lumpur
-       { 502,  "MY",  1, +8, +0, "Asia/Kuching" },             //
-
-       { 505,  "AU",  0, +10, +1, "Australia/Sydney" },        // Australia -- Canberra (n-project: Sydney)    /*!*/
-       { 505,  "AU",  1, +10, +1, "Australia/Lord_Howe" },     // +10:30, +00:30                               /*!*/
-       { 505,  "AU",  2, +10, +1, "Australia/Hobart" },        //
-       { 505,  "AU",  3, +10, +1, "Australia/Currie" },        //
-       { 505,  "AU",  4, +10, +1, "Australia/Melbourne" },     //
-       { 505,  "AU",  5, +10, +1, "Australia/Broken_Hill" },   //
-       { 505,  "AU",  6, +10, +0, "Australia/Brisbane" },      //
-       { 505,  "AU",  7, +10, +0, "Australia/Lindeman" },      //
-       { 505,  "AU",  8,  +9, +1, "Australia/Adelaide" },      // +09:30, +01:00
-       { 505,  "AU",  9,  +9, +0, "Australia/Darwin" },        // +09:30, +0
-       { 505,  "AU", 10,  +8, +0, "Australia/Perth" },         //
-       { 505,  "AU", 11,  +8, +0, "Australia/Eucla" },         // +08:45
-
-       { 510,  "ID",  0, +7, +0, "Asia/Jakarta" },     // Indonesia -- Jakarta
-       { 510,  "ID",  1, +7, +0, "Asia/Pontianak" },   //
-       { 510,  "ID",  2, +8, +0, "Asia/Makassar" },    //
-       { 510,  "ID",  3, +9, +0, "Asia/Jayapura" },    //
-
-       { 514,  "TL", -1, 0, 0, "Asia/Dili" },          // Timor -- Dili
-       { 515,  "PH", -1, 0, 0, "Asia/Manila" },        // Philippines -- Manila
-       { 520,  "TH", -1, 0, 0, "Asia/Bangkok" },       // Thailand -- Bangkok
-       { 525,  "SG", -1, 0, 0, "Asia/Singapore" },     // Singapore -- Singapore
-       { 528,  "BN", -1, 0, 0, "Asia/Brunei" },        // Brunei Darussalam -- Bandar Seri Begawan
-
-       { 530,  "NZ",  0, +12, +1, "Pacific/Auckland" },// New Zealand -- Wellington    /*!*/
-       { 530,  "NZ",  1, +12, +1, "Pacific/Chatham" }, // +12:45, +01:00
-
-       { 534,  "MP", -1, 0, 0, "Pacific/Saipan" },     // Northern Mariana Islands (US)
-       { 535,  "GU", -1, 0, 0, "Pacific/Guam" },       // Guam (US)
-       { 536,  "NR", -1, 0, 0, "Pacific/Nauru" },      // Nauru
-       { 537,  "PG", -1, 0, 0, "Pacific/Port_Moresby" }, // Papua New Guinea -- Port Moresby
-       { 539,  "TO", -1, 0, 0, "Pacific/Tongatapu" },  // Tonga -- Nuku'alofa                  /*!*/
-       { 540,  "SB", -1, 0, 0, "Pacific/Guadalcanal" },// Solomon -- Honiara                   /*!*/
-       { 541,  "VU", -1, 0, 0, "Pacific/Efate" },      // Vanuatu -- Port Vila                 /*!*/
-       { 542,  "FJ", -1, 0, 0, "Pacific/Fiji" },       // Fiji -- Suva
-       { 543,  "WF", -1, 0, 0, "Pacific/Wallis" },     // Wallis and Futuna (France)
-       { 544,  "AS", -1, 0, 0, "Pacific/Pago_Pago" },  // American Samoa(US) -- Pago Pago
-
-       { 545,  "KI",  0, +12, +0, "Pacific/Tarawa" },          //Kiribati -- Tarawa Atoll
-       { 545,  "KI",  1, +11, +0, "Pacific/Enderbury" },       //
-       { 545,  "KI",  2, +14, +0, "Pacific/Kiritimati" },      //
-
-       { 546,  "NC", -1, 0, 0, "Pacific/Noumea" },             // New Caledonia(France) -- Noumea
-
-       { 547,  "PF",  0, -10, +0, "Pacific/Tahiti" },  // French Polynesia(France) -- Papeete
-       { 547,  "PF",  1,  -9, +0, "Pacific/Marquesas" },//
-       { 547,  "PF",  2,  -9, +0, "Pacific/Gambier" }, //
-
-       { 548,  "CK", -1, 0, 0, "Pacific/Rarotonga" },  // Cook Islands(NZ) -- Avarua   /*!*/
-       { 549,  "WS", -1, 0, 0, "Pacific/Apia" },               // Samoa -- Apia
-
-       { 550,  "FM",  0, +11, +0, "Pacific/Pohnpei" }, // Micronesia -- Palikir
-       { 550,  "FM",  1, +10, +0, "Pacific/Chuuk" },   // Truk
-       { 550,  "FM",  2, +11, +0, "Pacific/Kosrae" },  //
-
-       { 551,  "MH",  0, +12, +0, "Pacific/Majuro" },  // Marshall Islands
-       { 551,  "MH",  1, +12, +0, "Pacific/Kwajalein" },//
-
-       { 552,  "PW", -1, 0, 0, "Pacific/Palau" },      // Palau -- Ngerulmud
-       { 602,  "EG", -1, 0, 0, "Africa/Cairo" },       // Cairo -- Cairo
-       { 603,  "DZ", -1, 0, 0, "Africa/Algiers" },     // Algeri -- Algiers
-       { 604,  "MA", -1, 0, 0, "Africa/Casablanca" },  // Morocco -- Rabat     /*!*/
-       { 605,  "TN", -1, 0, 0, "Africa/Tunis" },       // Tunisia -- Tunis
-       { 606,  "LY", -1, 0, 0, "Africa/Tripoli" },     // Libya -- Tripoli
-       { 607,  "GM", -1, 0, 0, "Africa/Banjul" },      // Gambia -- Banjul
-       { 608,  "SN", -1, 0, 0, "Africa/Dakar" },       // Senegal -- Dakar
-       { 609,  "MR", -1, 0, 0, "Africa/Nouakchott" },  // Mauritania -- Nouakchott
-       { 610,  "ML", -1, 0, 0, "Africa/Bamako" },      // Mali -- Bamako
-       { 611,  "GN", -1, 0, 0, "Africa/Conakry" },     // Guinea -- Conakry
-       { 612,  "CI", -1, 0, 0, "Africa/Abidjan" },     // lvory coast -- Yamoussoukro  /*!*/
-       { 613,  "BF", -1, 0, 0, "Africa/Ouagadougou" }, // Burkina faso -- Ouagadougou
-       { 614,  "NE", -1, 0, 0, "Africa/Niamey" },      // Niger -- Niamey
-       { 615,  "TG", -1, 0, 0, "Africa/Lome" },        // Togo -- Lome
-       { 616,  "BJ", -1, 0, 0, "Africa/Porto-Novo" },  // Benin -- Porto-Novo (n-project: Cotonou)
-       { 617,  "MU", -1, 0, 0, "Indian/Mauritius" },   // Mauritius -- Port Louis (n-project: Plaisance-PlaineMagnien)
-       { 618,  "LR", -1, 0, 0, "Africa/Monrovia" },    // Liberia -- Monrovia
-       { 619,  "SL", -1, 0, 0, "Africa/Freetown" },    // Sierra leone -- Freetown
-       { 620,  "GH", -1, 0, 0, "Africa/Accra" },       // Ghana -- Accra
-       { 621,  "NG", -1, 0, 0, "Africa/Lagos" },       // Nigeria -- Abuja     /*!*/
-       { 622,  "TD", -1, 0, 0, "Africa/Ndjamena" },    // Chad -- N'Djamena
-       { 623,  "CF", -1, 0, 0, "Africa/Bangui" },      // Central african republic -- Bangui
-       { 624,  "CM", -1, 0, 0, "Africa/Douala" },      // Cameroon -- Yaounde                  /*!*/
-       { 625,  "CV", -1, 0, 0, "Atlantic/Cape_Verde" },// Cape verde -- Praia (n-project: IlhaDoSal)
-       { 626,  "ST", -1, 0, 0, "Africa/Sao_Tome" },    // Sao tome and principe -- Sao Tome
-       { 627,  "GQ", -1, 0, 0, "Africa/Malabo" },      // Equatorial guinea -- Malabo
-       { 628,  "GA", -1, 0, 0, "Africa/Libreville" },  // Gabon -- Libreville
-       { 629,  "CG", -1, 0, 0, "Africa/Brazzaville" }, // Republic of the congo -- Brazzaville
-
-       { 630,  "CD",  0, +1, +0, "Africa/Kinshasa" },  // Democratic republic of the congo -- Kinshasa
-       { 630,  "CD",  1, +2, +0, "Africa/Lubumbashi" },//
-
-       { 631,  "AO", -1, 0, 0, "Africa/Luanda" },      // Angola -- Luanda
-       { 632,  "GW", -1, 0, 0, "Africa/Bissau" },      // Guinea-bissau -- Bissau
-       { 633,  "SC", -1, 0, 0, "Indian/Mahe" },        // Seychelles -- Victoria       /*!*/
-       { 634,  "SD", -1, 0, 0, "Africa/Khartoum" },    // Sudan -- Khartoum
-       { 635,  "RW", -1, 0, 0, "Africa/Kigali" },      // Rwanda -- Kigali
-       { 636,  "ET", -1, 0, 0, "Africa/Addis_Ababa" }, // Ethiopia -- Addis Ababa
-       { 637,  "SO", -1, 0, 0, "Africa/Mogadishu" },   // Somalia -- Mogadishu
-       { 638,  "DJ", -1, 0, 0, "Africa/Djibouti" },    // Djibouti -- Djibouti
-       { 639,  "KE", -1, 0, 0, "Africa/Nairobi" },     // Kenya -- Nairobi
-       { 640,  "TZ", -1, 0, 0, "Africa/Dar_es_Salaam" }, // Tanzania -- Dar es Salaam
-       { 641,  "UG", -1, 0, 0, "Africa/Kampala" },     // Uganda -- Kampala (n-project: Entebbe)
-       { 642,  "BI", -1, 0, 0, "Africa/Bujumbura" },   // Burundi -- Bujumbura
-       { 643,  "MZ", -1, 0, 0, "Africa/Maputo" },      // Mozambique -- Maputo
-       { 645,  "ZM", -1, 0, 0, "Africa/Lusaka" },      // Zambia -- Lusaka
-       { 646,  "MG", -1, 0, 0, "Indian/Antananarivo" },// Madagascar -- Antananarivo
-       { 647,  "RE", -1, 0, 0, "Indian/Reunion" },     // Reunion (France) -- no capital
-       { 648,  "ZW", -1, 0, 0, "Africa/Harare" },      // Zimbabwe -- Harare
-       { 649,  "NA", -1, 0, 0, "Africa/Windhoek" },    // Namibia -- Windhoek
-       { 650,  "MW", -1, 0, 0, "Africa/Blantyre" },    // Malawi -- Lilongwe   /*!*/
-       { 651,  "LS", -1, 0, 0, "Africa/Maseru" },      // Lesotho -- Maseru
-       { 652,  "BW", -1, 0, 0, "Africa/Gaborone" },    // Botswana -- Gaborone
-       { 653,  "SZ", -1, 0, 0, "Africa/Mbabane" },     // Swaziland -- Mbabane
-       { 654,  "KM", -1, 0, 0, "Indian/Comoro" },      // Comoros -- Moroni
-       { 655,  "ZA", -1, 0, 0, "Africa/Johannesburg" },// South africa -- Pretoria (administrative); Cape Town (legislative); Bloemfontein (judiciary)
-       { 657,  "ER", -1, 0, 0, "Africa/Asmara" },      // Eritrea
-       { 702,  "BZ", -1, 0, 0, "America/Belize" },     // Belize -- Belmopan
-       { 704,  "GT", -1, 0, 0, "America/Guatemala" },  // Guatemala -- Guatemala City
-       { 706,  "SV", -1, 0, 0, "America/El_Salvador" },// El salvador -- San Salvador
-       { 708,  "HN", -1, 0, 0, "America/Tegucigalpa" },// Honduras -- Tegucigalpa
-       { 710,  "NI", -1, 0, 0, "America/Managua" },    // Nicaragua -- Managua
-       { 712,  "CR", -1, 0, 0, "America/Costa_Rica" }, // Costa rica -- San Jose
-       { 714,  "PA", -1, 0, 0, "America/Panama" },     // Panama -- Panama City
-       { 716,  "PE", -1, 0, 0, "America/Lima" },       // Peru -- Lima
-
-       { 722,  "AR",  0, -3, +0, "America/Argentina/Buenos_Aires" },   // Argentina -- Buenos Aires
-       { 722,  "AR",  1, -3, +0, "America/Argentina/Cordoba" },        //
-       { 722,  "AR",  2, -3, +0, "America/Argentina/Salta" },          //
-       { 722,  "AR",  3, -3, +0, "America/Argentina/Jujuy" },          //
-       { 722,  "AR",  4, -3, +0, "America/Argentina/Tucuman" },        //
-       { 722,  "AR",  5, -3, +0, "America/Argentina/Catamarca" },      //
-       { 722,  "AR",  6, -3, +0, "America/Argentina/La_Rioja" },       //
-       { 722,  "AR",  7, -3, +0, "America/Argentina/San_Juan" },       //
-       { 722,  "AR",  8, -3, +0, "America/Argentina/Mendoza" },        //
-       { 722,  "AR",  9, -3, +0, "America/Argentina/San_Luis" },       //
-       { 722,  "AR", 10, -3, +0, "America/Argentina/Rio_Gallegos" },   //
-       { 722,  "AR", 11, -3, +0, "America/Argentina/Ushuaia" },        //
-
-       { 724,  "BR",  0, -3, +1, "America/Sao_Paulo" },        // Brazil -- Brasilia   /*!*/
-       { 724,  "BR",  1, -2, +0, "America/Noronha" },          //
-       { 724,  "BR",  2, -3, +0, "America/Belem" },            //
-       { 724,  "BR",  3, -3, +0, "America/Fortaleza" },        //
-       { 724,  "BR",  4, -3, +0, "America/Recife" },           //
-       { 724,  "BR",  5, -3, +0, "America/Araguaina" },        //
-       { 724,  "BR",  6, -3, +0, "America/Maceio" },           //
-       { 724,  "BR",  7, -3, +0, "America/Bahia" },            //
-       { 724,  "BR",  8, -4, +1, "America/Campo_Grande" },     //
-       { 724,  "BR",  9, -4, +1, "America/Cuiaba" },           //
-       { 724,  "BR", 10, -4, +0, "America/Santarem" },         //
-       { 724,  "BR", 11, -4, +0, "America/Porto_Velho" },      //
-       { 724,  "BR", 12, -4, +0, "America/Boa_Vista" },        //
-       { 724,  "BR", 13, -4, +0, "America/Manaus" },           //
-       { 724,  "BR", 14, -4, +0, "America/Eirunepe" },         //
-       { 724,  "BR", 15, -4, +0, "America/Rio_Branco" },       //
-
-       { 730,  "CL",  0, -4, +1, "America/Santiago" }, // Chile -- Santiago
-       { 730,  "CL",  1, -6, +1, "Pacific/Easter" },   //
-
-       { 734,  "VE", -1, 0, 0, "America/Caracas" },    // Venezuela -- Caracas
-       { 736,  "BO", -1, 0, 0, "America/La_Paz" },     // Bolivia -- La Paz (administrative); Sucre (judicial)
-       { 738,  "GY", -1, 0, 0, "America/Guyana" },     // Guyana -- Georgetown
-
-       { 740,  "EC",  0, -5, +0, "America/Guayaquil" },// Ecuador -- Quito     /*!*/
-       { 740,  "EC",  1, -6, +0, "Pacific/Galapagos" },//
-
-       { 742,  "GF", -1, 0, 0, "America/Cayenne" },    // French Guiana (France)
-       { 744,  "PY", -1, 0, 0, "America/Asuncion" },   // Paraguay -- Asuncion
-       { 746,  "SR", -1, 0, 0, "America/Paramaribo" }, // Suriname -- Paramaribo
-       { 748,  "UY", -1, 0, 0, "America/Montevideo" }, // Uruguay -- Montevideo
-       { 750,  "FK", -1, 0, 0, "Atlantic/Stanley" },   // Falkland Islands (Malvinas)
-
-       { -1, NULL, -1, -1, -1, NULL },
-};
-
-/*
- * FIXME: need to check exceptional timezone
- */
-static NITZ_MCC_TZFILE_MAP *nitz_find_tzinfo_by_mcc_timezone(int mcc, int tz, int dst, int dst_valid)
-{
-       NITZ_MCC_TZFILE_MAP *t = NULL;
-       int calc_tz = 0;
-
-       dbg("Request mcc: [%d], tz: [%d], dst: [%d], dst_valid: [%d]",
-                                               mcc, tz, dst, dst_valid);
-       filelog("Find tzfinfo - multi timezone (mcc = %d)", mcc);
-       filelog("+- wanted tz: %d,  dst: %d,  dst_valid: %d", tz, dst, dst_valid);
-
-       t = nitz_table_mcc_tzfile;
-       while (1) {
-               if (t->mcc == -1)
-                       return NULL;
-
-               if (t->mcc == mcc) {
-                       calc_tz = t->std_timezone * 60;
-                       dbg("mcc(%d) matched!! [tz=%d, dst=%d, calc_tz=%d, city=%s]", mcc, t->std_timezone, t->dst, calc_tz, t->city);
-
-                       filelog("+- tz: %d (%d), dst: %d, calc_tz: %d, city: %s",
-                                       t->std_timezone, t->std_timezone*60, t->dst, calc_tz, t->city);
-
-                       if (dst && dst_valid) {
-                               if (!t->dst)
-                                       goto CONT;
-
-                               calc_tz += t->dst * 60;
-                       }
-
-                       if (calc_tz == tz)
-                               return t;
-               }
-CONT:
-               t++;
-       }
-
-       return NULL;
-}
-
-static NITZ_MCC_TZFILE_MAP *nitz_find_tzinfo_by_mcc(int mcc)
-{
-       NITZ_MCC_TZFILE_MAP *t = NULL;
-
-       if (mcc <= 0)
-               return NULL;
-
-       t = nitz_table_mcc_tzfile;
-       while (1) {
-               if (t->mcc == -1)
-                       return NULL;
-
-               if (t->mcc == mcc)
-                       return t;
-
-               t++;
-       }
-
-       return NULL;
-}
-
-static gboolean nitz_is_multi_timezone(NITZ_MCC_TZFILE_MAP *m)
-{
-       if (m->id == -1)
-               return FALSE;
-
-       return TRUE;
-}
-
-NITZ_MCC_TZFILE_MAP *nitz_find_tzinfo(int mcc, int gmtoff, int dstoff, int isdst)
-{
-       NITZ_MCC_TZFILE_MAP *m;
-
-       m = nitz_find_tzinfo_by_mcc(mcc);
-       if (nitz_is_multi_timezone(m)) {
-               dbg("Multi timezone");
-               m = nitz_find_tzinfo_by_mcc_timezone(mcc, gmtoff, dstoff, isdst);
-       }
-
-       return m;
-}
-
-int nitz_self_check_tzfile(void)
-{
-       NITZ_MCC_TZFILE_MAP *t = NULL;
-       struct stat file_info;
-       char buf[255] = {0,};
-       int ret = TRUE;
-
-       t = nitz_table_mcc_tzfile;
-       while (1) {
-               if (t->mcc == -1)
-                       return ret;
-
-               /* check tzfile */
-               snprintf (buf, 255, "/usr/share/zoneinfo/%s", t->city);
-               if (stat(buf, &file_info) == -1) {
-                       filelog("file not exist!! [mcc=%d, tz=%3d, %s]", t->mcc, t->std_timezone, buf);
-                       ret = FALSE;
-               }
-
-               t++;
-       }
-
-       return ret;
-}
diff --git a/src/citylist.h b/src/citylist.h
deleted file mode 100644 (file)
index 8e8bfaf..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * tel-plugin-nitz
- *
- * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __NITZ_CITYLIST_H__
-#define __NITZ_CITYLIST_H__
-
-/*
- * http://en.wikipedia.org/wiki/List_of_mobile_country_codes
- * http://worldtimeengine.com
- */
-
-typedef struct {
-       int mcc;
-       char *country;  /* iso3166 */
-       int id;         /* id for city name (multi timezone in one country) */
-       int std_timezone;
-       int dst;
-       char *city;     /* timezone city filename */
-} NITZ_MCC_TZFILE_MAP;
-
-NITZ_MCC_TZFILE_MAP *nitz_find_tzinfo(int mcc, int gmtoff, int dstoff, int isdst);
-int nitz_self_check_tzfile(void);
-
-#endif
index 341321b..0f21cdc 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include <glib.h>
 #include <vconf.h>
 #include "common.h"
 #include "time_update.h"
 
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#define MCCTABLE_DIR_PATH "/opt/data/etc/mcctable.xml"
+
 #ifndef PLUGIN_VERSION
 #define PLUGIN_VERSION 1
 #endif
 
-static enum tcore_hook_return on_hook_network_timeinfo(Server *s,
-                       CoreObject *source,
-                       enum tcore_notification_command command,
-                       unsigned int data_len, void *data, void *user_data)
+#define VCONFKEY_WECONN_ALL_CONNECTED  "memory/private/weconn/all_connected"
+#define VCONFKEY_SAP_CONNECTION_TYPE   "memory/private/sap/conn_type"
+
+typedef enum SapConnType {
+       SAP_ALL = 0x00, /* All connectivity */
+       SAP_BT = 0x01, /* BT connectivity */
+       SAP_BLE = 0x02, /* BLE connectivity */
+       SAP_TCP_IP = 0x04, /* TCP connectivity */
+       SAP_USB = 0x08, /* USB connectivity */
+       SAP_MOBILE = 0x10, /* SCS connectivity */
+       SAP_CONNECTIVITY_END = 0xFF /* End of Connectivity */
+} SapConnType;
+
+struct nitz_time_update_s {
+       CoreObject *co_network;
+
+       struct tnoti_network_timeinfo *timeinfo;
+       struct nitz_custom_data *custom_data;
+       time_t start_time;
+};
+
+static void __load_XML(char *docname, char *groupname, void **i_doc, void **i_root_node)
+{
+       xmlDocPtr *doc = (xmlDocPtr *)i_doc;
+       xmlNodePtr *root_node = (xmlNodePtr *)i_root_node;
+
+       dbg("docname:%s, groupname:%s", docname, groupname);
+
+       *doc = xmlParseFile(docname);
+       if (*doc) {
+               *root_node = xmlDocGetRootElement(*doc);
+               if (*root_node) {
+                       dbg("*root_node->name:%s", (*root_node)->name);
+                       if (0 == xmlStrcmp((*root_node)->name, (const xmlChar *)groupname)) {
+                               *root_node = (*root_node)->xmlChildrenNode;
+                       } else {
+                               xmlFreeDoc(*doc);
+                               *doc = NULL;
+                               *root_node = NULL;
+                       }
+               } else {
+                       xmlFreeDoc(*doc);
+                       *doc = NULL;
+               }
+       } else
+               err("Cannot parse doc(%s)", docname);
+}
+
+static void __unload_XML(void **i_doc, void **i_root_node)
+{
+       xmlDocPtr *doc = (xmlDocPtr *)i_doc;
+       xmlNodePtr *root_node = (xmlNodePtr *)i_root_node;
+
+       dbg("unloading XML");
+       if (doc && *doc) {
+               xmlFreeDoc(*doc);
+               *doc = NULL;
+               if (root_node)
+                       *root_node = NULL;
+       }
+}
+
+char *__nitz_get_country_code_for_mcc(char *operator_mcc, struct nitz_custom_data *data)
+{
+       xmlNodePtr cur = NULL;
+       xmlNode *cur_node = NULL;
+       char *mcc_str = NULL, *iso = NULL;
+       void *xml_doc = NULL, *xml_root_node = NULL;
+
+       dbg("operator_mcc = %s", operator_mcc);
+
+       iso = (char *)g_hash_table_lookup(data->mcctable_hash, operator_mcc);
+       if (iso) {
+               dbg("Found a record in cache (mcc[%s], iso[%s])", operator_mcc, iso ? iso : "");
+               return g_strdup(iso);
+       }
+
+       __load_XML(MCCTABLE_DIR_PATH, "mcctable", &xml_doc, &xml_root_node);
+       if (!xml_root_node) {
+               err("mcctable.xml load error");
+               return NULL;
+       }
+
+       /* Get iso country code from mcctable for mcc */
+       cur = xml_root_node;
+       for (cur_node = cur; cur_node; cur_node = cur_node->next) {
+               if (cur_node->type == XML_ELEMENT_NODE) {
+                       mcc_str = (char *)xmlGetProp(cur_node, (const xmlChar *)"mcc");
+                       if (g_strcmp0(operator_mcc, mcc_str) == 0) {
+                               iso = g_strdup((char *)xmlGetProp(cur_node, (const xmlChar *)"iso"));
+                               dbg("Found a record(mcc[%s], iso[%s])", mcc_str, iso ? iso : "");
+                               break;
+                       }
+               }
+       }
+       __unload_XML(&xml_doc, &xml_root_node);
+       if (iso)
+               g_hash_table_insert(data->mcctable_hash, g_strdup(operator_mcc), g_strdup(iso));
+       return iso;
+}
+
+static enum ConnMode __nitz_get_device_connection_mode(void)
+{
+       int all_connected = FALSE;
+       int sap_conn_type = 0;
+
+#ifdef TIZEN_FEATURE_COMPANION_MODE_ENABLE
+       vconf_get_int(VCONFKEY_WECONN_ALL_CONNECTED, &all_connected);
+       vconf_get_int(VCONFKEY_SAP_CONNECTION_TYPE, &sap_conn_type);
+#endif
+       info("(%s : %d) (%s : %d)", VCONFKEY_WECONN_ALL_CONNECTED, all_connected, VCONFKEY_SAP_CONNECTION_TYPE, sap_conn_type);
+
+       if (!all_connected) {
+               return CONN_MODE_STANDALONE;
+       } else {
+               switch (sap_conn_type) {
+               case SAP_BT:
+                       return CONN_MODE_COMPAINION;
+
+               case SAP_MOBILE:
+                       return CONN_MODE_REMOTE;
+
+               default:
+               err("unknown type");
+               break;
+               }
+       }
+       return CONN_MODE_UNKNOWN;
+}
+
+static gboolean  _check_area_changed(char *iso)
+{
+       char *saved_iso = NULL;
+       gboolean area_changed = TRUE;
+
+       saved_iso = vconf_get_str(VCONFKEY_TELEPHONY_PRIVATE_NITZ_ISO);
+       if (saved_iso) {
+               info("saved iso:[%s], mcc iso:[%s]", saved_iso, iso);
+               if (g_ascii_strcasecmp(saved_iso, iso) == 0)
+                       area_changed = FALSE;
+
+               free(saved_iso);
+       }
+
+       return area_changed;
+}
+
+static void _check_fix_time_zone(struct nitz_custom_data *custom_data)
+{
+       char mcc_str[4] = {0,};
+       char *iso = NULL;
+       int mcc = 0;
+       int icc_card_exist = VCONFKEY_TELEPHONY_SIM_UNKNOWN;
+       enum telephony_network_service_type svc_type = NETWORK_SERVICE_TYPE_UNKNOWN;
+       Server *s = tcore_plugin_ref_server(custom_data->plugin);
+       GList *tz_list = NULL;
+       char *timezone_name = NULL;
+       int tz_count = 0;
+
+       if (!custom_data->need_fix_zone) {
+               info("We don't need to fix timezone");
+               return;
+       }
+
+       if (!nitz_is_auto_timezone()) {
+               info("We don't need to fix timezone in Manual timezone mode");
+               return;
+       }
+
+       vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &icc_card_exist);
+       if (icc_card_exist != VCONFKEY_TELEPHONY_SIM_INSERTED) {
+               if (tcore_server_get_modems_count(s) == 2) {
+                       int icc_card2_exist = VCONFKEY_TELEPHONY_SIM_UNKNOWN;
+                       vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT2, &icc_card2_exist);
+                       if (icc_card2_exist != VCONFKEY_TELEPHONY_SIM_INSERTED) {
+                               info("We don't need to fix timezone. Icc card is not exist.");
+                               custom_data->wait_for_icc_card = TRUE;
+                               return;
+                       }
+               } else {
+                       info("We don't need to fix timezone. Icc card is not exist.");
+                       custom_data->wait_for_icc_card = TRUE;
+                       return;
+               }
+       }
+
+       tcore_network_get_service_type(custom_data->co_network, &svc_type);
+       if (svc_type <= NETWORK_SERVICE_TYPE_SEARCH) {
+               info("We don't need to fix timezone. Not registered network yet");
+               custom_data->wait_for_net_registration = TRUE;
+               return;
+       } else {
+               custom_data->wait_for_net_registration = FALSE;
+       }
+
+       memcpy(mcc_str, custom_data->plmn, 3);
+       mcc = atoi(mcc_str);
+       iso = __nitz_get_country_code_for_mcc(mcc_str, custom_data);
+       if (iso) {
+               tz_list = nitz_get_tzlist(iso, NULL);
+               tz_count =  g_list_length(tz_list);
+               dbg("tz_count - %d", tz_count);
+               if (tz_count > 0) {
+                       if (_check_area_changed(iso)) {
+                               timezone_name = tz_list->data;
+                               if (tz_count > 1) {
+                                       info("Multi timezone, Can not select (Need gmtoff, dmtoff, ...");
+                               } else {
+                                       info("Single timezone. Apply (mcc:[%d] iso:[%s] zone:[%s])", mcc, iso, timezone_name);
+                                       nitz_apply_tzfile(timezone_name);
+                               }
+                       } else {
+                               info("Same Area. Do not change timezone now");
+                       }
+                       goto EXIT;
+               } else {
+                       info("timezone not found for mcc[%d] and iso[%s]", mcc, iso);
+               }
+       } else {
+               dbg("country code is NULL for mcc %d", mcc);
+       }
+
+EXIT:
+       g_list_free_full(tz_list, g_free);
+       g_free(iso);
+}
+
+static gboolean _update_network_timeinfo(gpointer user_data)
+{
+       struct nitz_time_update_s *time_update = user_data;
+       struct tnoti_network_timeinfo *timeinfo = NULL;
+       struct nitz_custom_data *custom_data = NULL;
+       time_t current_time = 0;
+       gint delay = 0;
+
+       if  (!time_update)
+               return FALSE;
+
+       if (nitz_is_auto_timezone()) {
+               /* Time update delay is calculated only for Automatic time update mode.
+                * For manual time update mode, we can't rely on system time for current time to derive offset/delay
+                */
+               time(&current_time);
+               delay = current_time - time_update->start_time;
+               info("Enqueued_timestamp[%u] Dequeued_timestamp[%u] delay[%d]", time_update->start_time, current_time, delay);
+       }
+
+       timeinfo = time_update->timeinfo;
+       custom_data = time_update->custom_data;
+       custom_data->nitz_updated = TRUE;
+       custom_data->need_fix_zone = FALSE;
+
+       info("[TIMESTAMP][STEP3-Processing] %04d-%02d-%02d %02d:%02d:%02d wday=%d GMT:%d, dstoff:%d, is_dst:%d",
+                       timeinfo->year, timeinfo->month, timeinfo->day,
+                       timeinfo->hour, timeinfo->minute, timeinfo->second,
+                       timeinfo->wday, timeinfo->gmtoff, timeinfo->dstoff, timeinfo->isdst);
+
+       if (CONN_MODE_COMPAINION == __nitz_get_device_connection_mode()) {
+               g_free(timeinfo);
+               g_free(time_update);
+               info("[TIMESTAMP] device is in companion mode! ignore NITZ update");
+               return FALSE;
+       }
+
+       if (!custom_data->co_network)
+               custom_data->co_network = time_update->co_network;
+
+       if (strlen(timeinfo->plmn) == 0 && custom_data->plmn != NULL) {
+               /* Updated PLMN from custom_data incase when received PLMN is empty. */
+               info("Received PLMN is empty, so use cached PLMN");
+               g_strlcpy(timeinfo->plmn, custom_data->plmn, strlen(custom_data->plmn)+1);
+       }
+
+       nitz_time_update(timeinfo, custom_data, delay);
+
+       g_free(timeinfo);
+       g_free(time_update);
+
+       return FALSE;
+}
+
+static gboolean _process_nitz_pending(gpointer user_data)
 {
+       struct nitz_custom_data *custom_data = user_data;
+       struct nitz_time_update_s *time_update = NULL;
+       struct tnoti_network_timeinfo *timeinfo = NULL;
+
+       if (!custom_data)
+               return FALSE;
+
+       while (1) {
+               time_update = g_queue_pop_head(custom_data->nitz_pending_queue);
+               if (!time_update)
+                       break;
+
+               timeinfo = time_update->timeinfo;
+               if (!timeinfo)
+                       continue;
+
+               if (g_queue_is_empty(custom_data->nitz_pending_queue))
+                       break;
+
+               info("[TIMESTAMP][STEP2-Discard] %04d-%02d-%02d %02d:%02d:%02d wday=%d GMT:%d, dstoff:%d, is_dst:%d",
+                               timeinfo->year, timeinfo->month, timeinfo->day,
+                               timeinfo->hour, timeinfo->minute, timeinfo->second,
+                               timeinfo->wday, timeinfo->gmtoff, timeinfo->dstoff, timeinfo->isdst);
+
+               g_free(timeinfo);
+               g_free(time_update);
+       }
+
+       _update_network_timeinfo(time_update);
+       return FALSE;
+}
+
+static enum tcore_hook_return on_hook_network_regist(Server *s,
+       CoreObject *source, enum tcore_notification_command command,
+       unsigned int data_len, void *data, void *user_data)
+{
+       struct nitz_custom_data *custom_data = user_data;
+       struct tnoti_network_registration_status *info = data;
+
+       if (!custom_data->co_network)
+               custom_data->co_network = source;
+
+       /*
+        * Handle MCC changed scenario -
+        * If MCC is changed and network is registered, update timezone
+        */
+       if ((info->service_type >= NETWORK_SERVICE_TYPE_SEARCH)
+               && (custom_data->wait_for_net_registration))
+                       _check_fix_time_zone(custom_data);
+
+       return TCORE_HOOK_RETURN_CONTINUE;
+}
+
+static enum tcore_hook_return on_hook_network(Server *s, CoreObject *source,
+       enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
+{
+       struct nitz_custom_data *custom_data = user_data;
+       struct tnoti_network_change *info = data;
+       gboolean is_mcc_changed = FALSE;
+
+       if (!info || strlen(info->plmn) == 0) {
+               info("Invalid data");
+               return TCORE_HOOK_RETURN_CONTINUE;
+       }
+
+       if (!custom_data->co_network)
+               custom_data->co_network = source;
+
+       /*
+        * Handle MCC changed scenario -
+        * If MCC is changed and network is registered, update timezone
+        */
+       if ((custom_data->plmn && strncmp(info->plmn, custom_data->plmn, 3)) || (!custom_data->plmn)) {
+               info("MCC change (%s) -> (%s)", custom_data->plmn ? custom_data->plmn : "", info->plmn);
+               g_free(custom_data->plmn);
+               custom_data->plmn = g_strdup(info->plmn);
+               is_mcc_changed = TRUE;
+       }
+
+       if (is_mcc_changed) {
+               if (CONN_MODE_COMPAINION == __nitz_get_device_connection_mode()) {
+                       info("device is in companion mode! ignore MCC change");
+               } else {
+                       custom_data->need_fix_zone = TRUE;
+                       _check_fix_time_zone(custom_data);
+               }
+       }
+
+       return TCORE_HOOK_RETURN_CONTINUE;
+}
+
+static enum tcore_hook_return on_hook_network_timeinfo(Server *s, CoreObject *source, enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
+{
+       struct nitz_time_update_s *time_update;
        struct tnoti_network_timeinfo *timeinfo = data;
-       gboolean flag_auto_update = FALSE;
+       struct nitz_custom_data *custom_data = user_data;
 
        filelog("NITZ !! (time(NULL) = %u)", (unsigned int)time(NULL));
-       dbg("+- %04d-%02d-%02d %02d:%02d:%02d wday=%d",
+
+       info("[TIMESTAMP][STEP1-AddQueue] %04d-%02d-%02d %02d:%02d:%02d wday=%d GMT:%d, dstoff:%d, is_dst:%d",
                        timeinfo->year, timeinfo->month, timeinfo->day,
                        timeinfo->hour, timeinfo->minute, timeinfo->second,
-                       timeinfo->wday);
-       dbg("+- GMT-offset:%d, DST-offset:%d, is_dst:%d",
-                       timeinfo->gmtoff, timeinfo->dstoff, timeinfo->isdst);
+                       timeinfo->wday, timeinfo->gmtoff, timeinfo->dstoff, timeinfo->isdst);
+
+       /* Allocate memory */
+       time_update = g_try_malloc0(sizeof(struct nitz_time_update_s));
+       if (time_update == NULL) {
+               err("Memory allocation failed");
+               return TCORE_HOOK_RETURN_CONTINUE;
+       }
 
-       vconf_get_bool(VCONFKEY_SETAPPL_STATE_AUTOMATIC_TIME_UPDATE_BOOL,
-                                                       &flag_auto_update);
-       if (flag_auto_update == FALSE)
-               dbg("manual time update mode");
+       time_update->custom_data = custom_data;
+       time_update->timeinfo = g_memdup(timeinfo, sizeof(struct tnoti_network_timeinfo));
+       time_update->co_network = source;
 
-       nitz_time_update(timeinfo, flag_auto_update);
+       if (g_queue_is_empty(custom_data->nitz_pending_queue)) {
+               info("No pending NITZ");
+               g_idle_add(_process_nitz_pending, custom_data);
+       }
+       info("Add nitz info to queue");
+       time(&time_update->start_time);
+       g_queue_push_tail(custom_data->nitz_pending_queue, time_update);
 
        return TCORE_HOOK_RETURN_CONTINUE;
 }
 
+static void on_vconf_sim_slot_state(keynode_t *node, void *user_data)
+{
+       int icc_card_exist = VCONFKEY_TELEPHONY_SIM_UNKNOWN;
+       struct nitz_custom_data *data = user_data;
+       Server *s = tcore_plugin_ref_server(data->plugin);
+
+       vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &icc_card_exist);
+       if (icc_card_exist == VCONFKEY_TELEPHONY_SIM_INSERTED)
+               goto UPDATE;
+       else {
+               if (tcore_server_get_modems_count(s) == 2) {
+                       int icc_card2_exist = VCONFKEY_TELEPHONY_SIM_UNKNOWN;
+                       vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT2, &icc_card2_exist);
+                       if (icc_card2_exist == VCONFKEY_TELEPHONY_SIM_INSERTED)
+                               goto UPDATE;
+               }
+               return;
+       }
+UPDATE:
+       {
+               struct nitz_custom_data *data = user_data;
+               if (data->wait_for_icc_card) {
+                       info("ICC CARD INSERTED. check timezone again");
+                       _check_fix_time_zone(user_data);
+                       data->wait_for_icc_card = FALSE;
+               }
+       }
+}
+
 static gboolean on_load()
 {
-       dbg("Load!!!");
+       dbg("i'm load!");
 
        return TRUE;
 }
@@ -71,26 +490,78 @@ static gboolean on_load()
 static gboolean on_init(TcorePlugin *p)
 {
        Server *s;
+       struct nitz_custom_data *data;
+       guint modems_count;
 
-       dbg("Init!!!");
+       if (!p)
+               return FALSE;
+
+       dbg("i'm init!");
 
        s = tcore_plugin_ref_server(p);
-       if (s == NULL)
+       if (!s)
+               return FALSE;
+
+       data = calloc(sizeof(struct nitz_custom_data), 1);
+       if (!data)
                return FALSE;
 
-       tcore_server_add_notification_hook(s, TNOTI_NETWORK_TIMEINFO,
-                                       on_hook_network_timeinfo, NULL);
+       data->plugin = p;
+       tcore_plugin_link_user_data(p, data);
+
+       data->nitz_updated = FALSE;
+       data->need_fix_zone = FALSE;
+       data->mcctable_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+       data->nitz_pending_queue = g_queue_new();
+       g_queue_init(data->nitz_pending_queue);
+
+       tcore_server_add_notification_hook(s, TNOTI_NETWORK_CHANGE, on_hook_network, data);
+       tcore_server_add_notification_hook(s, TNOTI_NETWORK_REGISTRATION_STATUS, on_hook_network_regist, data);
+       tcore_server_add_notification_hook(s, TNOTI_NETWORK_TIMEINFO, on_hook_network_timeinfo, data);
+
+       vconf_notify_key_changed(VCONFKEY_TELEPHONY_SIM_SLOT, on_vconf_sim_slot_state, data);
+
+       modems_count = tcore_server_get_modems_count(s);
+       dbg("get modems count - %d", modems_count);
+       if (modems_count == 2)
+               vconf_notify_key_changed(VCONFKEY_TELEPHONY_SIM_SLOT2, on_vconf_sim_slot_state, data);
 
        return TRUE;
 }
 
 static void on_unload(TcorePlugin *p)
 {
-       dbg("Unload");
+       struct nitz_custom_data *data;
+       Server *s;
+       guint modems_count;
+
+       dbg("i'm unload");
+
+       data = tcore_plugin_ref_user_data(p);
+       if (!data)
+               return;
+
+       if (data->plmn)
+               g_free(data->plmn);
+
+       if (data->mcctable_hash)
+               g_hash_table_destroy(data->mcctable_hash);
+
+       s = tcore_plugin_ref_server(p);
+       tcore_server_remove_notification_hook(s, on_hook_network);
+       tcore_server_remove_notification_hook(s, on_hook_network_regist);
+       tcore_server_remove_notification_hook(s, on_hook_network_timeinfo);
+
+       vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SIM_SLOT, on_vconf_sim_slot_state);
+       modems_count = tcore_server_get_modems_count(s);
+       dbg("get modems count - %d", modems_count);
+       if (modems_count == 2)
+               vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SIM_SLOT2, on_vconf_sim_slot_state);
+
+       free(data);
 }
 
-EXPORT_API struct tcore_plugin_define_desc plugin_define_desc =
-{
+EXPORT_API struct tcore_plugin_define_desc plugin_define_desc = {
        .name = "NITZ",
        .priority = TCORE_PLUGIN_PRIORITY_MID,
        .version = PLUGIN_VERSION,
index 29d1438..faf8ce4 100644 (file)
 #include <glib.h>
 #include <vconf.h>
 #include <tcore.h>
-#include <dd-deviced.h>
+#include <alarm.h>
+#include <device/power.h>
+
 #include "common.h"
 #include "time_update.h"
-#include "citylist.h"
 
 #define BUF_SIZE 255
 #define PATH_LOCALTIME "/opt/etc/localtime"
 #define PATH_ZONEINFO  "/usr/share/zoneinfo"
+#define VCONFKEY_TELEPHONY_NITZ_ISO "db/private/telephony/nitz_iso"
+
+gboolean nitz_is_auto_timezone(void)
+{
+       gboolean auto_timezone;
+       vconf_get_bool(VCONFKEY_SETAPPL_STATE_AUTOMATIC_TIME_UPDATE_BOOL, &auto_timezone);
+       if (auto_timezone == FALSE) {
+               dbg("Manual time update mode.");
+               return FALSE;
+       } else {
+               dbg("Automatic time update mode.");
+               return TRUE;
+       }
+}
+
+static int nitz_get_uptime(void)
+{
+       struct sysinfo sys_info;
+
+       if (sysinfo(&sys_info) == 0) {
+               info("uptime: %ld secs", sys_info.uptime);
+               return sys_info.uptime;
+       }
+
+       return 0;
+}
+
+gboolean nitz_set_time(time_t new_time)
+{
+       int ret = 0;
+
+       vconf_set_int(VCONFKEY_TELEPHONY_NITZ_GMT, new_time);
+       vconf_set_int(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, nitz_get_uptime());
+
+       if (!nitz_is_auto_timezone()) {
+               info("[TIMESTAMP] Automatic time update was disabled. We don't need to set time");
+               return FALSE;
+       }
+
+       /*
+        *  - Apply system time(GMT)
+        */
+       info("[TIMESTAMP][Before] NITZ GMT Time = %ld", new_time);
+
+       /* Acquire lock */
+       ret = device_power_request_lock(POWER_LOCK_CPU, 0);
+       if (ret < 0)
+               err("ret : (0x%x)", ret);
 
-int nitz_apply_tzfile(const char *tzfilename, gboolean mode_auto)
+       ret = alarmmgr_set_systime(new_time);
+       if (ret < 0)
+               info("[TIMESTAMP] alarmmgr_set_systime fail. (ret=%d)", ret);
+       else
+               info("[TIMESTAMP][After] alarm_set_time(%ld) success", new_time);
+
+       /* Release lock */
+       ret = device_power_release_lock(POWER_LOCK_CPU);
+       if (ret < 0)
+               err("ret : (0x%x)", ret);
+       return TRUE;
+}
+
+gboolean nitz_apply_tzfile(const char *tzfilename)
 {
        char buf[BUF_SIZE] = {0, };
-       int ret;
+       char current_tz[BUF_SIZE] = {0, };
+       int ret = -1;
+       ssize_t len;
 
-       vconf_set_str(VCONFKEY_TELEPHONY_NITZ_ZONE, tzfilename);
+       if (!tzfilename) {
+               err("tzfilename is NULL");
+               return FALSE;
+       }
 
-       if (mode_auto == FALSE)
-               return 0;
+       if (!nitz_is_auto_timezone()) {
+               info("[TIMESTAMP] Automatic time update was disabled. We don't need to set time");
+               return FALSE;
+       }
 
        snprintf(buf, BUF_SIZE, "%s/%s", PATH_ZONEINFO, tzfilename);
 
-       ret = deviced_set_timezone(buf);
-       filelog("set (%s) timezone file. ret=%d", buf, ret);
+       len = readlink(PATH_LOCALTIME, current_tz, BUF_SIZE-1);
+       if (len < 0) {
+               err("Fail to get Current Zone Info");
+       } else {
+               if (g_strcmp0(current_tz, buf) == 0) {
+                       info("[TIMESTAMP] We don't need to set timezone again (Already applied)");
+                       return FALSE;
+               } else {
+                       info("Current TZ:[%s] New TZ:[%s]", current_tz, buf);
+               }
+       }
+
+       filelog("[TIMESTAMP][Before] timezone will be set");
+
+       /* Acquire lock */
+       ret = device_power_request_lock(POWER_LOCK_CPU, 0);
+       if (ret < 0)
+               err("ret : (0x%x)", ret);
+
+       ret = alarmmgr_set_timezone(buf);
+
+       /* Release lock */
+       device_power_release_lock(POWER_LOCK_CPU);
+       if (ret < 0)
+               err("ret : (0x%x)", ret);
+
+       filelog("set (%s) alarmmgr_set_timezone ret=%d", buf, ret);
 
        sync();
        tzset();
 
-       filelog("+- Result: tzname=[%s, %s], timezone=%ld, daylight=%d",
-                               tzname[0], tzname[1], timezone, daylight);
+       filelog("[TIMESTAMP][After] tzname=[%s, %s], timezone=%ld, daylight=%d",
+                       tzname[0], tzname[1], timezone, daylight);
 
-       return ret;
+       if (ret != 0)
+               return FALSE;
+       else
+               return TRUE;
 }
 
-long nitz_get_uptime()
+static gboolean __update_timezone_by_offset(const struct tnoti_network_timeinfo *ti, char *iso)
 {
-       struct sysinfo info;
+       char *timezone_name = NULL;
+       GList *tz_list = NULL;
+       int tz_count = 0;
+       gboolean ret = FALSE;
+       gboolean found = FALSE;
 
-       if (sysinfo(&info) == 0) {
-               dbg("uptime: %ld secs", info.uptime);
-               return info.uptime;
+       tz_list = nitz_get_tzlist(iso, ti);
+       tz_count = g_list_length(tz_list);
+       if (tz_count == 1) {
+               timezone_name = tz_list ? tz_list->data : NULL;
+               found = timezone_name ? TRUE : FALSE;
+               info("Single timezone(%s)", timezone_name);
+       } else {
+               UChar utf16_timezone[NITZ_TIMEZONE_MAX_LEN] = { 0 };
+               UCalendar *cal = NULL;
+               gboolean in_dst = FALSE;
+               UErrorCode ec = U_ZERO_ERROR;
+               GList *list = NULL;
+
+               info("Multi timezone. # of TZ : [%d]", tz_count);
+               for (list = tz_list; list != NULL; list = g_list_next(list)) {
+                       timezone_name = list->data;
+                       if (strlen(timezone_name) > 0) {
+                               u_uastrncpy(utf16_timezone, timezone_name, NITZ_TIMEZONE_MAX_LEN);
+                               cal = ucal_open(utf16_timezone, u_strlen(utf16_timezone), uloc_getDefault(), UCAL_TRADITIONAL, &ec);
+                               if (cal == NULL) {
+                                       err("ucal_open returns NULL");
+                                       break;
+                               }
+                               in_dst = ucal_inDaylightTime(cal, &ec);
+                               dbg("TZ DST:[%d] WANTED DST:[%d][%d]", in_dst, ti->isdst, ti->dstoff);
+                               if (ti->dstoff == (int)in_dst) {
+                                       found = TRUE;
+                                       info("(%s) was selected", timezone_name);
+                                       ucal_close(cal);
+                                       break;
+                               }
+                               ucal_close(cal);
+                       }
+               }
        }
 
-       return 0;
+       if (found)
+               ret = nitz_apply_tzfile(timezone_name);
+       else
+               info("[TIMESTAMP] Fail to find timezone");
+
+       g_list_free_full(tz_list, g_free);
+       return ret;
 }
 
-static gboolean update_time(const struct tnoti_network_timeinfo *ti,
-                                                       gboolean mode_auto)
+static gboolean __update_time(const struct tnoti_network_timeinfo *ti,
+       struct nitz_custom_data *data, gint delay)
 {
        struct tm tm_time;
        time_t tt_gmt_nitz;
-       int ret;
 
        memset(&tm_time, 0, sizeof(struct tm));
        tm_time.tm_year = ti->year - 1900 + 2000;
@@ -93,74 +230,101 @@ static gboolean update_time(const struct tnoti_network_timeinfo *ti,
        tm_time.tm_wday = ti->wday;
        tm_time.tm_isdst = ti->dstoff;
 
-       tt_gmt_nitz = timegm(&tm_time);
-       tt_gmt_nitz -= ti->gmtoff * 60;
-       dbg("NITZ GMT Time = %ld", tt_gmt_nitz);
-
-       vconf_set_int(VCONFKEY_TELEPHONY_NITZ_GMT, tt_gmt_nitz);
-       vconf_set_int(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, nitz_get_uptime());
-
-       if (mode_auto == FALSE) {
-               return FALSE;
-       }
-
+       tt_gmt_nitz = timegm(&tm_time)+delay;
+#ifdef TIZEN_FEATURE_NEED_RESTORED_GMT
        /*
-        *  - Apply system time (GMT)
+        * Need to set GMT+0 time.
+        * but, in case of IMC-modem, CP send the time applied GMT.(e.g., GMT+9 in Korea)
+        * so, restore GMT+0 time.
         */
-       ret = deviced_set_datetime(tt_gmt_nitz);
-       if (ret < 0) {
-               filelog("deviced_set_datetime(%ld) failed. ret = %d",
-                                                       tt_gmt_nitz, ret);
-               return FALSE;
-       } else {
-               filelog("deviced_set_datetime(%ld) success. ret = %d",
-                                                       tt_gmt_nitz, ret);
-       }
+       tt_gmt_nitz -= ti->gmtoff * 60;
+#endif
 
-       return TRUE;
+       return nitz_set_time(tt_gmt_nitz);
 }
 
-static gboolean update_timezone(const struct tnoti_network_timeinfo *ti,
-                                                       gboolean mode_auto)
+static gboolean __update_timezone(const struct tnoti_network_timeinfo *ti, struct nitz_custom_data *data)
 {
-       int mcc;
-       char mcc_str[4];
-       NITZ_MCC_TZFILE_MAP *m;
+       int mcc = -1;
+       char mcc_str[4] = {0,};
        gboolean ret = FALSE;
 
-       snprintf(mcc_str, 4, "%s", ti->plmn);
+       memcpy(mcc_str, ti->plmn, 3);
        mcc = atoi(mcc_str);
-       dbg("MCC: [%d]", mcc);
 
        if (mcc >= 0) {
-               m = nitz_find_tzinfo(mcc, ti->gmtoff, ti->dstoff, ti->isdst);
-               if (m) {
-                       dbg("Country: [%s] (ISO 3166)", m->country);
-                       dbg("City: [%s]", m->city);
-                       nitz_apply_tzfile(m->city, mode_auto);
-                       ret = TRUE;
-               } else {
-                       dbg("No search result");
-               }
+               char *iso = __nitz_get_country_code_for_mcc(mcc_str, data);
+               ret = __update_timezone_by_offset(ti, iso);
+               g_free(iso);
        }
 
        return ret;
 }
 
+GList *nitz_get_tzlist(char *iso, const struct tnoti_network_timeinfo *ti)
+{
+       char *timezone_name = 0;
+       UEnumeration *enum_tz = 0;
+       UErrorCode ec = U_ZERO_ERROR;
+       const UChar *timezone_id = 0;
+       int timezone_id_len = 0;
+       int offset = 0;
+       GList *tz_list = NULL;
+
+       if (ti) {
+               offset = ti->gmtoff * 60 * 1000;
+               if (ti->isdst)
+                       offset -= ti->dstoff * 60 * 60 * 1000;
+               dbg("offset = %d", offset);
+               enum_tz = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, iso, &offset, &ec);
+       } else {
+               enum_tz = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, iso, NULL, &ec);
+       }
+
+       while (1) {
+               if (enum_tz == NULL)
+                       break;
+
+               timezone_id = uenum_unext(enum_tz, &timezone_id_len, &ec);
+               if (timezone_id == NULL)
+                       break;
+
+               timezone_name = (char *)g_malloc0(NITZ_TIMEZONE_MAX_LEN);
+               u_UCharsToChars(timezone_id, timezone_name, NITZ_TIMEZONE_MAX_LEN);
+               tz_list = g_list_append(tz_list, timezone_name);
+               info("[TIMESTAMP] ISO:[%s] offset:[%d], Available TZ:[%s]", iso, offset, timezone_name);
+       }
+       uenum_close(enum_tz);
+       return tz_list;
+}
+
 gboolean nitz_time_update(const struct tnoti_network_timeinfo *time_info,
-                                                       gboolean mode_auto)
+       struct nitz_custom_data *data, gint delay)
 {
+       gboolean ret_time, ret_tz;
+
        if (time_info->year == 0
                        && time_info->month == 0
                        && time_info->day == 0
                        && time_info->hour == 0
                        && time_info->minute == 0
                        && time_info->second == 0) {
-               /* Timezone only */
-               return update_timezone(time_info, mode_auto);
+               /*
+                * Update Timezone only
+                */
+               return __update_timezone(time_info, data);
        }
 
-       update_time(time_info, mode_auto);
+       /*
+        * Update (in order) -
+        *      1. Time
+        *      2. Timezone
+        */
+       ret_time = __update_time(time_info, data, delay);
+       ret_tz = __update_timezone(time_info, data);
 
-       return update_timezone(time_info, mode_auto);
+       if (ret_time || ret_tz)
+               return TRUE;
+       else
+               return FALSE;
 }