home *** CD-ROM | disk | FTP | other *** search
- /**
- * File: modules/Timezone.ycp
- * Package: Country settings
- * Summary: Timezone related stuff
- * Authors: Klaus Kaempf <kkaempf@suse.de>
- * Thomas Roelz <tom@suse.de>
- *
- * $Id: Timezone.ycp 34195 2006-11-09 11:41:43Z jsuchome $
- */
-
- {
-
- module "Timezone";
- textdomain "country";
-
- import "Arch";
- import "Language";
- import "Misc";
- import "Mode";
- import "Stage";
- import "String";
- import "ProductFeatures";
-
- // --------------------------------------------------------------
- // START: Globally defined data to be accessed via Timezone::<variable>
- // --------------------------------------------------------------
-
- global string timezone = ""; // e.g. "Europe/Berlin"
-
- // hwclock parameter
- // possible values:
- // "" dont change timezone
- // "-u" system clock runs UTC
- // "--localtime" system clock runs localtime
- global string hwclock = "";
-
- // The default timezone if set.
- //
- global string default_timezone = "";
-
- // Flag indicating if the user has chosen a timezone.
- // To be set from outside.
- //
- global boolean user_decision = false;
- global boolean user_hwclock = false;
-
- global integer diff = 0;
-
- /**
- * if anyuthing was modified (currently for auto client only)
- */
- global boolean modified = false;
-
- /**
- * If there is windows partition, assume that local time is used
- */
- global boolean windows_partition = false;
-
- // internal map used to store initial data
- map push = $[];
-
- // ------------------------------------------------------------------
- // END: Globally defined data to be accessed via Timezone::<variable>
- // ------------------------------------------------------------------
-
-
-
- // ------------------------------------------------------------------
- // START: Locally defined data
- // ------------------------------------------------------------------
-
- string name = "";
-
- list < map < string, any> > zonemap = [];
-
- // 'language --> default timezone' conversion map
- map<string, string> lang2tz = $[];
-
- // ------------------------------------------------------------------
- // END: Locally defined data
- // ------------------------------------------------------------------
-
-
- // ---------------------------------------------------------------------------------------
- // START: Globally defined functions
- // ---------------------------------------------------------------------------------------
-
- /**
- * get_lang2tz()
- *
- * Get the language --> timezone conversion map.
- *
- * @return conversion map
- *
- * @see get_zonemap()
- */
-
- define map<string, string> get_lang2tz () {
-
- if (size (lang2tz) == 0)
- {
- map base_lang2tz = (map) SCR::Read (.target.yast2, "lang2tz.ycp");
- if (base_lang2tz == nil) base_lang2tz = $[];
-
- lang2tz = (map<string,string>) union (
- base_lang2tz,
- Language::GetLang2TimezoneMap ()
- );
- }
- return lang2tz;
- }
-
- /**
- * get_zonemap()
- *
- * Get the timezone database.
- *
- * @return timezone DB (map)
- *
- * @see get_lang2tz()
- */
-
- global define list<map<string,any> > get_zonemap() {
-
- if (size(zonemap) == 0)
- {
- zonemap = (list<map<string,any> >)
- eval (SCR::Read (.target.yast2, "timezone_raw.ycp"));
- if( zonemap == nil ) zonemap = [];
- }
- return zonemap;
- }
-
- // ------------------------------------------------------------------
- // END: Locally defined functions
- // ------------------------------------------------------------------
- /**
- * Set()
- *
- * Set system to selected timezone.
- *
- * @param string timezone to select, e.g. "Europe/Berlin"
- *
- * @return the number of the region that contains the timezone
- *
- */
- global define integer Set (string zone, boolean really) {
-
- list <map <string, any> > zmap = get_zonemap();
-
- // Set the new timezone internally
- timezone = zone;
-
- integer sel = 0;
- while (sel<size (zmap) && !haskey (zmap[sel,"entries"]:$[], zone))
- {
- sel = sel + 1;
- }
-
- name = zmap [sel,"name"]:"" + " / " + zmap[sel,"entries",zone]:zone;
-
- // Adjust system to the new timezone.
- //
- if (!Mode::config () && really )
- {
- string cmd = "/usr/sbin/zic -l " + timezone;
- y2milestone( "Set cmd %1", cmd );
- y2milestone( "Set ret %1", SCR::Execute( .target.bash_output, cmd ));
- if (!Arch::s390 ())
- {
- cmd = "/sbin/hwclock --hctosys " + hwclock;
- y2milestone( "Set cmd %1", cmd );
- y2milestone( "Set ret %1", SCR::Execute(.target.bash_output, cmd ));
- }
- }
-
- // On first assignment store default timezone.
- //
- if (default_timezone == "")
- {
- default_timezone = timezone;
- y2milestone( "Set default timezone: <%1>", timezone );
- }
-
- y2milestone( "Set timezone:%1 sel:%2 name:%3", timezone, sel, name );
- return sel;
- }
-
- /**
- * Convert the duplicated timezone to the only one supported
- * Temporary solution - a result of discussion of bug #47472
- * @param tmz current timezone
- */
- global define string UpdateTimezone (string tmz) {
-
- string updated_tmz = tmz;
-
- map tmz_duplicates = $[
- "Australia/Adelaide" : "Australia/South",
- "Australia/Darwin" : "Australia/North",
- "Australia/Sydney" : "Australia/NSW",
- "Australia/Canberra" : "Australia/ACT",
- "Australia/Brisbane" : "Australia/Queensland",
- "Australia/Hobart" : "Australia/Tasmania",
- "Australia/Perth" : "Australia/West",
- // etc.
- "America/Los_Angeles" : "US/Pacific",
- ];
-
- if (haskey (tmz_duplicates, tmz))
- {
- updated_tmz = tmz_duplicates[tmz]:tmz;
- y2milestone ("updating timezone from %1 to %2", tmz, updated_tmz);
- // TODO if still not present, search file in /usr/share/zoneinfo
- }
-
- return updated_tmz;
- }
-
-
- /**
- * Read timezone settings from sysconfig
- */
- global define void Read () {
-
- hwclock = Misc::SysconfigRead(.sysconfig.clock.HWCLOCK, hwclock);
- timezone = Misc::SysconfigRead (.sysconfig.clock.TIMEZONE, timezone);
- default_timezone =
- Misc::SysconfigRead(.sysconfig.clock.DEFAULT_TIMEZONE, default_timezone);
-
- // get name for cloning purposes
- if (Mode::config ())
- {
- list <map <string, any> > zmap = get_zonemap();
- integer sel = 0;
- while (sel<size (zmap) && !haskey (zmap[sel,"entries"]:$[], timezone))
- {
- sel = sel + 1;
- }
- name = zmap [sel,"name"]:"" + " / " + zmap[sel,"entries",timezone]:timezone;
- }
- }
-
- /**
- * Timezone()
- *
- * The module constructor.
- * Sets the proprietary module data defined globally for public access.
- * This is done only once (and automatically) when the module is loaded for the first time.
- * Calls Set() in initial mode.
- * Reads current timezone from sysconfig in normal mode.
- *
- * @see Set()
- */
- global define void Timezone() {
-
- // Set default values.
- //
- hwclock = "-u";
- if (Stage::initial ())
- {
- // language --> timezone database, e.g. "de_DE" : "Europe/Berlin"
- map<string, string> lang2tz = get_lang2tz();
-
- string new_timezone = lang2tz[Language::language]:"";
- y2milestone( "Timezone new_timezone %1", new_timezone );
-
- if (new_timezone != "")
- {
- Set (new_timezone, true);
- }
- }
- else if (!Mode::config ())
- {
- Read ();
- }
- return;
- }
-
- /**
- * Set the new time and date given by user
- */
- global define void SetTime (string year, string month, string day,
- string hour, string minute, string second ) {
- if (!Arch::s390 ())
- {
- string date = sformat( " --date=\"%1/%2/%3 %4:%5:%6\" ", month, day,
- year, hour, minute, second );
- string cmd = "";
- if (size (timezone) >0 && hwclock != "--localtime")
- {
- cmd = "TZ=" + timezone + " ";
- }
- cmd = cmd + "/sbin/hwclock --set " + hwclock + date;
- y2milestone( "SetTime cmd %1", cmd );
- SCR::Execute(.target.bash, cmd );
- cmd = "/sbin/hwclock --hctosys " + hwclock;
- y2milestone( "SetTime cmd %1", cmd );
- SCR::Execute(.target.bash, cmd );
- }
- };
-
- /**
- * GetTimezoneForLanguage()
- *
- * Get the timezone for the given system language.
- *
- * @param System language code, e.g. "en_US".
- * Default timezone to be returned if nothing found.
- *
- * @return The timezone for this language, e.g. "US/Eastern"
- * or the default value if nothing found.
- *
- * @see -
- */
- global define string GetTimezoneForLanguage (string sys_language,
- string default_timezone)
- {
- // The system_language --> timezone conversion map.
- //
- map<string, string> lang2timezone = get_lang2tz();
- string ret = lang2timezone[sys_language]:default_timezone;
-
- y2milestone ("language %1 default timezone %2 returned timezone %3",
- sys_language, default_timezone, ret);
- return ret;
- }
-
- /**
- * Set the timezone for the given system language.
- * @param System language code, e.g. "en_US".
- * @return the number of the region that contains the timezone
- */
- global define void SetTimezoneForLanguage (string sys_language) {
-
- string tmz = GetTimezoneForLanguage (sys_language, "US/Eastern");
- y2debug ("language %1 proposed timezone %2", sys_language, tmz);
- if (tmz != "")
- {
- Set (tmz, true);
- }
- }
-
- /**
- * Return the language code for given timezone (by reverse searching the
- * "language -> timezone" map)
- * @param timezone, if empty the current one is used
- */
- global define string GetLanguageForTimezone (string tz)
- {
- if (tz == "" || tz == nil)
- tz = timezone;
-
- string lang = "";
- foreach (string code, string tmz, get_lang2tz(), {
- if (tmz == tz && (lang == "" || !issubstring (lang, "_")))
- lang = code;
- });
- return lang;
- }
-
- /**
- * Return the country part of language code for given timezone
- * @param timezone, if empty the current one is used
- */
- global define string GetCountryForTimezone (string tz)
- {
- return Language::GetGivenLanguageCountry (GetLanguageForTimezone(tz));
- }
-
- /**
- * Return translated country name of given timezone
- * @param timezone value (as saved in sysconfig/clock)
- */
- global define string GetTimezoneCountry (string zone) {
-
- list zmap = (list) eval (SCR::Read (.target.yast2, "timezone_raw.ycp"));
-
- integer sel = 0;
- while (sel<size (zmap) && !haskey (zmap[sel,"entries"]:$[], zone))
- {
- sel = sel + 1;
- }
- return zmap [sel,"name"]:"" + " / " + zmap[sel,"entries",zone]:zone;
- }
-
- /**
- * GetDateTime()
- *
- * Get the output of date "+%H:%M:%S - %Y-%m-%d" or in locale defined format
- *
- * @param flag if to get real system time or if to simulate changed
- * timezone settings with TZ=
- * @param if the date and time should be returned in locale defined format
- *
- * @return The string output.
- *
- * @see -
- */
- global define string GetDateTime (boolean real_time, boolean locale_format) {
-
- string cmd = "";
-
- string date_format = (locale_format && Mode::normal ())
- ? "+%c" : "+%H:%M:%S - %Y-%m-%d";
-
- y2milestone( "GetDateTime hwclock %1 real:%2", hwclock, real_time );
- if (!real_time && !Mode::config ())
- {
- integer ds = 0;
- if (diff!=0)
- {
- map out = (map) SCR::Execute (.target.bash_output, "date +%z");
- string tzd = out["stdout"]:"";
- y2milestone( "GetDateTime tcd=%1", tzd );
- integer t = tointeger( String::CutZeros( substring( tzd, 1, 2 )));
- if (t != nil)
- {
- ds = ds + t * 3600;
- t = tointeger( String::CutZeros( substring( tzd, 3, 2 )));
- ds = ds + t * 60;
- if (substring (tzd, 0, 1) == "-")
- ds = -ds;
- y2milestone( "GetDateTime ds %1 diff %2", ds, diff );
- }
- }
- cmd = "";
- if (hwclock != "--localtime")
- {
- cmd = sformat( "TZ=%1 ", timezone );
- }
- cmd = cmd + sformat( "/bin/date \"%1\" \"--date=now %2sec\"",
- date_format, ds*diff );
- }
- else
- {
- cmd = sformat( "/bin/date \"%1\"", date_format );
- }
- y2milestone( "GetDateTime cmd=%1", cmd );
- map out = (map) SCR::Execute (.target.bash_output, cmd);
- string local_date = out["stdout"]:"";
-
- y2milestone( "GetDateTime local_date=%1", local_date );
-
- return( local_date );
- }
-
- global define void ResetZonemap()
- ``{
- zonemap = [];
- }
-
- /**
- * Return true if localtime should be proposed as default
- * Based on current hardware configuration:
- * Win partitions present or 32bit Mac
- */
- global define boolean ProposeLocaltime () {
-
- return windows_partition || (Arch::board_mac() && Arch::ppc32());
- }
-
- /**
- * MakeProposal()
- *
- * Return proposal string and set system timezone.
- *
- * @param boolean force_reset
- * boolean language_changed
- *
- * @return string user readable description.
- * If force_reset is true reset the module to the timezone
- * stored in default_timezone.
- */
-
- global define string MakeProposal (boolean force_reset,
- boolean language_changed )
- {
- y2milestone ("force_reset: %1", force_reset);
- y2milestone ("language_changed: %1 user_decision %2 user_hwclock %3",
- language_changed, user_decision, user_hwclock);
-
- if (language_changed)
- ResetZonemap();
-
- if (!user_hwclock || force_reset)
- {
- hwclock = "-u";
- if (ProposeLocaltime ())
- {
- hwclock = "--localtime";
- }
- }
- if (force_reset)
- {
- // If user wants to reset do it if a default is available.
- //
- if( default_timezone != "" )
- {
- Set( default_timezone, true ); // reset
- }
-
- // Reset user_decision flag.
- //
- user_decision = false;
- }
- else // no reset
- {
- // Only follow the language if the user has never actively chosen
- // a timezone. The indicator for this is user_decision which is
- // set from outside the module.
- //
- if (user_decision || Mode::autoinst () ||
- ProductFeatures::GetStringFeature ("globals", "timezone") != "")
- {
- if( language_changed )
- {
- y2milestone("User has chosen a timezone; not following language - only retranslation.");
-
- Set( timezone, true );
- }
- }
- else
- {
- // User has not yet chosen a timezone ==> follow language.
- //
- string local_timezone =
- GetTimezoneForLanguage( Language::language, "US/Eastern");
-
- if( local_timezone != "" )
- {
- Set( local_timezone, true );
- default_timezone = local_timezone;
- }
- else
- {
- if( language_changed )
- {
- y2error("Can't follow language - only retranslation");
-
- Set( timezone, true );
- }
- }
- }
- }
-
- // label text (Clock setting)
- string clock_setting = _("UTC");
-
- if (hwclock == "--localtime")
- // label text, Clock setting: local time (not UTC)
- clock_setting = _("Local Time");
-
- // label text
- clock_setting = _("Hardware Clock Set To") + " " + clock_setting;
-
- string date = GetDateTime (true, true);
-
- y2milestone( "MakeProposal hwclock %1", hwclock );
-
- return name + " - " + clock_setting + " " + date;
- }
-
- /**
- * Selection()
- *
- * Return a map of ids and names to build up a selection list
- * for the user. The key is used later in the Set function
- * to select this timezone. The name is a translated string.
- *
- * @param -
- *
- * @return map map for timezones
- * 'timezone_id' is used internally in Set and Probe
- * functions. 'timezone_name' is a user-readable string.
- * Uses Language::language for translation.
- * @see Set()
- */
-
- global define list Selection (integer num) {
-
- list<map<string,any> > zmap = get_zonemap();
-
- list<list<string> > trl = maplist (
- string key, string name, zmap[num,"entries"]:$[], ``([ name, key ]));
-
- trl = sort (list<string> a, list<string> b, trl, {
- list lsorted = lsort ([a[0]:"", b[0]:""]);
- return (lsorted[0]:"" == a[0]:"" && a[0]:"" != b[0]:"");
- });
- y2debug ("trl = %1", trl);
-
- return maplist (list e, trl, ``(`item (`id(e[1]:""), e[0]:"", false)));
- }
-
- /**
- * Return list of regions for timezone selection list
- */
- global define list Region() {
-
- integer num = -1;
- return maplist (map entry, get_zonemap (), {
- num = num + 1;
- return (`item (`id(num), entry["name"]:"", false ));
- });
- }
-
-
- /**
- * Save()
- *
- * Save timezone to target sysconfig.
- *
- * @param -
- *
- * @return -
- */
- global define void Save() {
-
- if ( Mode::update () )
- {
- return;
- }
-
- SCR::Write(.sysconfig.clock.TIMEZONE, timezone);
- SCR::Write(.sysconfig.clock.DEFAULT_TIMEZONE, default_timezone);
- SCR::Write(.sysconfig.clock.HWCLOCK, hwclock);
-
- SCR::Write(.sysconfig.clock, nil); // flush
-
- y2milestone( "Save Saved data for timezone: <%1>", timezone );
-
- return;
- }
-
-
- /**
- * Return current date and time in the map
- */
- global define map GetDateTimeMap() {
-
- map ret = $[];
- list dparts = filter (
- string v,splitstring (GetDateTime (false,false), " -:" ),``(size(v)>0));
-
- ret["hour"] = dparts[0]:"";
- ret["minute"] = dparts[1]:"";
- ret["second"] = dparts[2]:"";
- ret["year"] = dparts[3]:"";
- ret["month"] = dparts[4]:"";
- ret["day"] = deletechars (dparts[5]:"", "\n");
- y2milestone( "GetDateTimeMap dparts %1 ret %2", dparts, ret );
- return( ret );
- }
-
- global define boolean CheckTime( string hour, string minute, string second )
- ``{
- boolean ret = true;
- integer tmp = tointeger( String::CutZeros(hour) );
- if (tmp == nil) return false;
- ret = ret && tmp>=0 && tmp<24;
- tmp = tointeger( String::CutZeros(minute) );
- if (tmp == nil) return false;
- ret = ret && tmp>=0 && tmp<60;
- tmp = tointeger( String::CutZeros(second) );
- if (tmp == nil) return false;
- ret = ret && tmp>=0 && tmp<60;
- return( ret );
- }
-
- global define boolean CheckDate( string day, string month, string year )
- ``{
- list mdays = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
- boolean ret = true;
- integer yea = tointeger( String::CutZeros(year) );
- integer mon = tointeger( String::CutZeros(month) );
- integer da = tointeger( String::CutZeros(day) );
- if (yea == nil || mon == nil || da == nil)
- return false;
- ret = ret && mon>=1 && mon<=12;
- if( yea%4==0 && (yea%100!=0 || yea%400==0))
- {
- mdays[1] = 29;
- }
- ret = ret && da>=1 && da<=mdays[mon-1]:0;
- ret = ret && yea>=1970 && yea<2032;
- return( ret );
- }
-
- // does the hwclock run on UTC only ? -> skip asking
- global define boolean utc_only () {
-
- y2milestone( "Arch::sparc () %1 Arch::board_iseries () %2 Arch::board_chrp () %3 Arch::board_prep () %4", Arch::sparc (), Arch::board_iseries (), Arch::board_chrp (), Arch::board_prep () );
-
- return (Arch::sparc () || Arch::board_iseries () ||
- Arch::board_chrp () || Arch::board_prep ());
- }
-
- /**
- * save the initial data
- */
- global define void PushVal () {
-
- push = $[ "hwclock" : hwclock, "timezone" : timezone ];
- y2milestone ( "PushVal map %1", push );
- }
-
- /**
- * restore the original data from internal map
- */
- global define void PopVal() {
-
- y2milestone ("before Pop: timezone %1 hwclock %2", timezone, hwclock );
- if ( haskey( push, "hwclock" ))
- hwclock = push["hwclock"]:hwclock;
- if( haskey( push, "timezone" ))
- timezone = push["timezone"]:timezone;
- push = $[];
- y2milestone ("after Pop: timezone %1 hwclock %2", timezone, hwclock );
- }
-
- /**
- * was anything modified?
- */
- global define boolean Modified () {
-
- return modified ||
- timezone != push["timezone"]:timezone || hwclock != push["hwclock"]:hwclock;
- }
-
- /**
- * AutoYaST interface function: Get the Timezone configuration from a map.
- * @param settings imported map
- * @return success
- */
- global define boolean Import (map settings) {
-
- // Read was not called -> do the init
- if (push == $[])
- PushVal ();
-
- if (haskey (settings, "hwclock"))
- {
- hwclock = settings["hwclock"]:"UTC" == "UTC" ? "-u" : "--localtime";
- user_hwclock = true;
- }
- Set (settings["timezone"]:timezone, true);
- return true;
- }
-
- /**
- * AutoYaST interface function: Return the Timezone configuration as a map.
- * @return map with the settings
- */
- global define map Export () {
-
- map ret = $[
- "timezone" : timezone,
- "hwclock" : hwclock == "-u" ? "UTC" : "localtime",
- ];
- return ret;
- }
-
- /**
- * AutoYaST interface function: Return the summary of Timezone configuration as a map.
- * @return summary string (html)
- */
- global define string Summary () {
-
- import "HTML";
-
- string clock_setting = _("UTC");
-
- if (hwclock == "--localtime")
- // label text, Clock setting: local time (not UTC)
- clock_setting = _("Local Time");
-
- // label text
- clock_setting = _("Hardware Clock Set To") + " " + clock_setting;
-
- list<string> ret = [
- // summary label
- sformat (_("Current Time Zone: %1"), name),
- clock_setting
- ];
- return HTML::List (ret);
- }
-
-
- } // -EOF-
-