#!/usr/bin/python
# -*- Mode: Python; indent-tabs-mode: nil; tab-width: 4 -*-
#
# Copyright 2010 Canonical Ltd
# Authors:
#   Michael Terry <michael.terry@canonical.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os, re, subprocess, time, sys
from xml.dom import minidom

def regget(path, key):
    regline = subprocess.Popen(["reglookup", "-H", "-p", key, path], stdout=subprocess.PIPE).communicate()[0]
    if not regline:
        return None
    fields = regline.split(',')
    if len(fields) < 3:
        return None
    return fields[2]

def setvar(path, var, val):
    try:
        f = open(path, 'r')
        s = f.read()
        f.close()
    except:
        s = ''

    match = re.match('(^|\n)%s="(.*)"' % var, s)
    if match:
        if match.group(2) == val:
            return False
        s, num = re.subn('(^|\n)%s=".*"' % var, '\\1%s="%s"' % (var, val), s)
    else:
        s += '\n%s="%s"' % (var, val)

    f = open(path, 'w')
    f.write(s)
    f.close()
    return True

# Import locale
# References:
#  http://msdn.microsoft.com/en-us/goglobal/bb896001.aspx
#  /usr/share/i18n/SUPPORTED

def issupportedlocale(locale):
    issupported = False
    try:
        f = open('/usr/share/i18n/SUPPORTED')
        text = f.read()
        f.close()
        if re.search('^%s\\s' % re.escape(locale), text, re.MULTILINE):
            issupported = True
    except:
        pass
    return issupported

def getfallbacklocale(lang, country):
    try:
        f = open('/usr/share/localechooser/languagelist')
        text = f.read()
        f.close()
        match = re.search('^%s_%s;.*;(.*);' % (lang, country), text, re.MULTILINE)
        if not match:
            match = re.search('^%s;.*;(.*);' % lang, text, re.MULTILINE)
        if not match:
            f = open('/usr/share/i18n/SUPPORTED')
            text = f.read()
            f.close()
            match = re.search('^%s_?(.*)\\.UTF-8 ' % lang, text, re.MULTILINE)
        if not match:
            return 'en_US.UTF-8'
        elif match.group(1):
            fallback = '%s_%s.UTF-8' % (lang, match.group(1))
        else:
            fallback = '%s.UTF-8' % lang
        if issupportedlocale(fallback):
            return fallback
        else:
            return 'en_US.UTF-8'
    except:
        return 'en_US.UTF-8'

def importLocale(winuser):
    winlocale = regget('/media/private/windows/Users/%s/NTUSER.DAT' % winuser, '/Control Panel/Desktop/PreferredUILanguages')
    if winlocale:
       winlocale = winlocale.split('|')[0]
    else:
       winlocale = regget('/media/private/windows/Users/%s/NTUSER.DAT' % winuser, '/Control Panel/International/LocaleName')
    ubulocale = None
    if winlocale:
        winlocalesplit = winlocale.split('-')
        ll = winlocalesplit[0]
        if len(winlocalesplit) > 1:
            cc = winlocalesplit[-1]
        else:
            cc = None
        ubulocale = ll + ('_' + cc if cc else '') + '.UTF-8'
        
        # Now check if locale is supported in Ubuntu
        issupported = issupportedlocale(ubulocale)
        if not issupported:
            ubulocale = getfallbacklocale(ll, cc)

        ubulocalesplit = ubulocale.split('_')
        ull = ubulocalesplit[0]

        coreLanguages = ['zh', 'nl', 'en', 'fr', 'de', 'it', 'es']
        if ('firstboot' in sys.argv) or (ull in coreLanguages):
            setvar('/etc/default/locale', 'LANG', ubulocale)

# Import keyboard

# Windows->Linux keyboard mapping
# References:
#  http://support.microsoft.com/kb/139177
#  http://msdn.microsoft.com/en-us/library/dd318716%28VS.85%29.aspx
#  http://msdn.microsoft.com/en-us/library/dd318693%28VS.85%29.aspx
#  http://msdn.microsoft.com/en-us/goglobal/bb964651.aspx
#  A Windows 7 Registry
#  /usr/share/X11/xkb/rules/xorg.lst
#  Running System->Preferences->Keyboard->Layout->Add and looking at keyboard maps
keymap = {
    '0401': ['ara', { # Arabic (101)
             '0001': 'ara', # Arabic (102)
             '0002': 'ara:azerty', # Arabic (102) AZERTY
             }],
    '0813': ['be'], # Belgian Dutch FIXME not sure about this one
    '080C': ['be:nodeadkeys'], # Belgian French
    '0416': ['br'], # Brazilian (ABNT)
    '0402': ['bg'], # Bulgarian
    '1009': ['ca', { # Canadian French (sometimes called Canadian English)
             '0001': 'ca:multix', # Canadian Multilingual Standard
             }],
    '0C0C': ['ca:fr-legacy', { # Canadian French (Legacy)
             '0001': 'ca', # Canadian French (Multilingual) FIXME not sure
             }],
    '0404': ['cn'], # Chinese
    '0804': ['cn'], # Chinese
    '0C04': ['cn'], # Chinese
    '1004': ['cn'], # Chinese
    '1404': ['cn'], # Chinese
    '041A': ['hr'], # Croatian
    '0405': ['cz'], # Czech
    '0406': ['dk'], # Danish
    '0413': ['nl'], # Dutch
    '040B': ['fi'], # Finnish
    '040C': ['fr'], # French
    '0407': ['de'], # German
    '0408': ['gr', { # Greek
             '0001': 'gr', # Greek (220) FIXME not available
             '0002': 'gr', # Greek (319) FIXME not available
             '0003': 'gr', # Greek (220) Latin FIXME not available
             '0004': 'gr', # Greek (319) Latin FIXME not available
             }],
    '040D': ['il'], # Hebrew
    '0439': ['in:bolnagri'], # Hindi Traditional
    '040E': ['hu', { # Hungarian
             '0001': 'hu:101_qwerty_comma_nodead', # Hungarian 101-key
             }],
    '040F': ['is'], # Icelandic
    '0410': ['it', { # Italian
             '0001': 'it', # Italian (142) FIXME ?
             }],
    '0411': ['jp:kana'], # Japanese
    '0412': ['kr'], # Korean
    '080A': ['latam'], # Latin American
    '0414': ['no'], # Norwegian
    '0415': ['pl:qwertz', { # Polish (214)
             '0001': 'pl', # Polish (Programmers)
             }],
    '0816': ['pt'], # Portuguese
    '0418': ['ro'], # Romanian
    '0419': ['ru'], # Russian
    '0C1A': ['rs'], # Serbian (Cyrillic)
    '1C1A': ['rs'], # Serbian (Cyrillic)
    '281A': ['rs'], # Serbian (Cyrillic)
    '301A': ['rs'], # Serbian (Cyrillic)
    '081A': ['rs:latin'], # Serbian (Latin)
    '181A': ['rs:latin'], # Serbian (Latin)
    '241A': ['rs:latin'], # Serbian (Latin)
    '2C1A': ['rs:latin'], # Serbian (Latin)
    '041B': ['sk'], # Slovak
    '0424': ['si'], # Slovenian
    '040A': ['es', { # Spanish
             '0001': 'es', # Spanish variation FIXME not available
             }],
    '041D': ['se'], # Swedish
    '100C': ['ch:fr'], # Swiss French
    '0807': ['ch:de_nodeadkeys'], # Swiss German
    '041E': ['th', { # Thai Kedmanee
             '0001': 'th', # Thai Kedmanee (non-ShiftLock)
             '0002': 'th:pat', # Thai Pattachote
             '0003': 'th:pat', # Thai Pattachote (non-ShiftLock)
             }],
    '041F': ['tr', { # Turkish Q
             '0001': 'tr:f', # Turkish F
             }],
    '0809': ['gb'], # United Kingdom
    '0409': ['us', { # US
             '0001': 'us:dvorak', # US-Dvorak
             '0002': 'us:intl', # US-International
             '0003': 'us:dvorak-l', # US-Dvorak for left hand
             '0004': 'us:dvorak-r', # US-Dvorak for right hand
             }],
}

def importKeyboard(winuser):
    winkbdcode = regget('/media/private/windows/Users/%s/NTUSER.DAT' % winuser, '/Keyboard Layout/Preload/1')
    if winkbdcode:
        winkbdLL = winkbdcode[4:] # language family
        if winkbdLL in keymap:
            winkbdVV = winkbdcode[0:4] # variant
            model = 'pc105'
            layout = 'us'
            variant = ''
            kbdspec = ''
            kbdlist = keymap[winkbdLL]
            if len(kbdlist) > 1 and winkbdVV in kbdlist[1]:
                kbdspec = kbdlist[1][winkbdVV]
            else:
                kbdspec = kbdlist[0]
            kbdspecparts = kbdspec.split(':')
            layout = kbdspecparts[0]
            if len(kbdspecparts) > 1:
                variant = kbdspecparts[1]

            #setvar('/etc/default/console-setup', 'XKBMODEL', model)
            setlayout = setvar('/etc/default/console-setup', 'XKBLAYOUT', layout)
            setvariant = setvar('/etc/default/console-setup', 'XKBVARIANT', variant)
            if setlayout or setvariant:
                os.system('udevadm trigger --action=change --subsystem-match=input')

# Import wifi

def getChild(node, name):
    if type(name) == str:
        for c in node.childNodes:
            if c.localName == name:
                return c
        return None
    else:
        for subname in name:
            node = getChild(node, subname)
            if not node:
                return None
        return node

def getText(node, name):
    node = getChild(node, name)
    if not node or not node.firstChild:
        return None
    else:
        return node.firstChild.data

def convertWifi(path):
    # http://msdn.microsoft.com/en-us/library/ms706965%28VS.85%29.aspx
    # http://live.gnome.org/NetworkManagerConfiguration
    dom = minidom.parse(path)
    root = dom.documentElement

    nameNode = getText(root, 'name')
    linFileName = nameNode if nameNode else 'Windows Wifi'

    modeNode = getText(root, 'connectionMode')
    isAuto = modeNode == 'auto' if modeNode else True

    typeNode = getText(root, 'connectionType')
    isInfra = typeNode == 'ESS' if typeNode else False
    if not isInfra: return

    hexStr = getText(root, ['SSIDConfig', 'SSID', 'hex'])
    if not hexStr: return
    linSSID = ''
    if len(hexStr) % 2 != 0:
        hexStr = '0' + hexStr
    for i in range(len(hexStr)/2):
        snip = hexStr[i*2:i*2+2]
        decimal = str(int(snip, 16))
        linSSID += decimal + ';'

    # Don't do security bits yet, until we can decipher Windows's encryption
    #securityNode = getText(root, ['MSM', 'security'])

    linContent = '''
[connection]
id=%s
type=802-11-wireless
autoconnect=%s
timestamp=%s

[802-11-wireless]
ssid=%s
mode=%s
''' % (linFileName, 'true' if isAuto else 'false', int(time.time()), linSSID,
       'infrastructure' if isInfra else 'adhoc')

    f = open('/etc/NetworkManager/system-connections/%s' % linFileName, 'w')
    f.write(linContent)
    f.close()
    os.system('chmod go-r /etc/NetworkManager/system-connections/%s' % linFileName)

def importWifi():
    ifacedir = '/media/private/windows/ProgramData/Microsoft/Wlansvc/Profiles/Interfaces'
    allifaces = os.listdir(ifacedir)
    for iface in allifaces:
        xmlpath = os.path.join(ifacedir, iface)
        allxml = os.listdir(xmlpath)
        for xml in allxml:
            try:
                convertWifi(os.path.join(xmlpath, xml))
            except:
                pass

# Import timezone

# This table was created by grabbing all the keys in a Windows 7 registry like:
# '/Microsoft/Windows NT/CurrentVersion/Time Zones' and noting the values for MUI_Std.
# This gives us numeric-ID to Windows name.
idToWinNameTable = {
    '462': 'Afghanistan Standard Time',
    '222': 'Alaskan Standard Time',
    '392': 'Arab Standard Time',
    '442': 'Arabian Standard Time',
    '402': 'Arabic Standard Time',
    '842': 'Argentina Standard Time',
    '82': 'Atlantic Standard Time',
    '652': 'AUS Central Standard Time',
    '672': 'AUS Eastern Standard Time',
    '449': 'Azerbaijan Standard Time',
    '12': 'Azores Standard Time',
    '142': 'Canada Central Standard Time',
    '22': 'Cape Verde Standard Time',
    '452': 'Caucasus Standard Time',
    '662': 'Cen. Australia Standard Time',
    '152': 'Central America Standard Time',
    '512': 'Central Asia Standard Time',
    '105': 'Central Brazilian Standard Time',
    '282': 'Central Europe Standard Time',
    '292': 'Central European Standard Time',
    '722': 'Central Pacific Standard Time',
    '162': 'Central Standard Time',
    '172': 'Central Standard Time (Mexico)',
    '572': 'China Standard Time',
    '252': 'Dateline Standard Time',
    '412': 'E. Africa Standard Time',
    '682': 'E. Australia Standard Time',
    '332': 'E. Europe Standard Time',
    '42': 'E. South America Standard Time',
    '112': 'Eastern Standard Time',
    '342': 'Egypt Standard Time',
    '472': 'Ekaterinburg Standard Time',
    '732': 'Fiji Standard Time',
    '352': 'FLE Standard Time',
    '435': 'Georgian Standard Time',
    '262': 'GMT Standard Time',
    '52': 'Greenland Standard Time',
    '272': 'Greenwich Standard Time',
    '362': 'GTB Standard Time',
    '232': 'Hawaiian Standard Time',
    '492': 'India Standard Time',
    '432': 'Iran Standard Time',
    '372': 'Israel Standard Time',
    '335': 'Jordan Standard Time',
    '982': 'Kamchatka Standard Time',
    '622': 'Korea Standard Time',
    '912': 'Mauritius Standard Time',
    '32': 'Mid-Atlantic Standard Time',
    '365': 'Middle East Standard Time',
    '772': 'Montevideo Standard Time',
    '892': 'Morocco Standard Time',
    '192': 'Mountain Standard Time',
    '182': 'Mountain Standard Time (Mexico)',
    '542': 'Myanmar Standard Time',
    '522': 'N. Central Asia Standard Time',
    '385': 'Namibia Standard Time',
    '502': 'Nepal Standard Time',
    '742': 'New Zealand Standard Time',
    '72': 'Newfoundland Standard Time',
    '582': 'North Asia East Standard Time',
    '552': 'North Asia Standard Time',
    '92': 'Pacific SA Standard Time',
    '212': 'Pacific Standard Time',
    '215': 'Pacific Standard Time (Mexico)',
    '872': 'Pakistan Standard Time',
    '962': 'Paraguay Standard Time',
    '302': 'Romance Standard Time',
    '422': 'Russian Standard Time',
    '832': 'SA Eastern Standard Time',
    '122': 'SA Pacific Standard Time',
    '792': 'SA Western Standard Time',
    '242': 'Samoa Standard Time',
    '562': 'SE Asia Standard Time',
    '592': 'Singapore Standard Time',
    '382': 'South Africa Standard Time',
    '532': 'Sri Lanka Standard Time',
    '602': 'Taipei Standard Time',
    '692': 'Tasmania Standard Time',
    '632': 'Tokyo Standard Time',
    '752': 'Tonga Standard Time',
    '132': 'US Eastern Standard Time',
    '202': 'US Mountain Standard Time',
    '932': 'UTC',
    '812': 'Venezuela Standard Time',
    '702': 'Vladivostok Standard Time',
    '612': 'W. Australia Standard Time',
    '312': 'W. Central Africa Standard Time',
    '322': 'W. Europe Standard Time',
    '482': 'West Asia Standard Time',
    '712': 'West Pacific Standard Time',
    '642': 'Yakutsk Standard Time',
}

# This table was created from unicode.org's windowsZones.xml
# http://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml
# That data has the following copyright:
# Copyright 1991-2009 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
winNameToLinuxName = {
    'AUS Central Standard Time': 'Australia/Darwin', # S (GMT+09:30) Darwin
    'AUS Eastern Standard Time': 'Australia/Sydney', # D (GMT+10:00) Canberra, Melbourne, Sydney
    'Afghanistan Standard Time': 'Asia/Kabul', # S (GMT+04:30) Kabul
    'Alaskan Standard Time': 'America/Anchorage', # D (GMT-09:00) Alaska
    'Arab Standard Time': 'Asia/Riyadh', # S (GMT+03:00) Kuwait, Riyadh
    'Arabian Standard Time': 'Asia/Dubai', # S (GMT+04:00) Abu Dhabi, Muscat
    'Arabic Standard Time': 'Asia/Baghdad', # S (GMT+03:00) Baghdad
    'Argentina Standard Time': 'America/Buenos_Aires', # D (GMT-03:00) Buenos Aires
    'Armenian Standard Time': 'Asia/Yerevan', # D [XP] (GMT+04:00) Yerevan
    'Atlantic Standard Time': 'America/Halifax', # D (GMT-04:00) Atlantic Time (Canada)
    'Azerbaijan Standard Time': 'Asia/Baku', # D (GMT+04:00) Baku
    'Azores Standard Time': 'Atlantic/Azores', # D (GMT-01:00) Azores
    'Bangladesh Standard Time': 'Asia/Dhaka', # D (GMT+06:00) Dhaka
    'Canada Central Standard Time': 'America/Regina', # S (GMT-06:00) Saskatchewan
    'Cape Verde Standard Time': 'Atlantic/Cape_Verde', # S (GMT-01:00) Cape Verde Is.
    'Caucasus Standard Time': 'Asia/Yerevan', # D (GMT+04:00) Yerevan / S [XP] (GMT+04:00) Caucasus Standard Time
    'Cen. Australia Standard Time': 'Australia/Adelaide', # D (GMT+09:30) Adelaide
    'Central America Standard Time': 'America/Guatemala', # S (GMT-06:00) Central America
    'Central Asia Standard Time': 'Asia/Almaty', # S (GMT+06:00) Astana
    'Central Brazilian Standard Time': 'America/Campo_Grande', # D (GMT-04:00) Manaus
    'Central Europe Standard Time': 'Europe/Budapest', # D (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague
    'Central European Standard Time': 'Europe/Warsaw', # D (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb
    'Central Pacific Standard Time': 'Pacific/Guadalcanal', # S (GMT+11:00) Magadan, Solomon Is., New Caledonia
    'Central Standard Time': 'America/Chicago', # D (GMT-06:00) Central Time (US & Canada)
    'Central Standard Time (Mexico)': 'America/Mexico_City', # D (GMT-06:00) Guadalajara, Mexico City, Monterrey
    'China Standard Time': 'Asia/Shanghai', # S (GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi
    'Dateline Standard Time': 'Etc/GMT+12', # S (GMT-12:00) International Date Line West
    'E. Africa Standard Time': 'Africa/Nairobi', # S (GMT+03:00) Nairobi
    'E. Australia Standard Time': 'Australia/Brisbane', # S (GMT+10:00) Brisbane
    'E. Europe Standard Time': 'Europe/Minsk', # D (GMT+02:00) Minsk
    'E. South America Standard Time': 'America/Sao_Paulo', # D (GMT-03:00) Brasilia
    'Eastern Standard Time': 'America/New_York', # D (GMT-05:00) Eastern Time (US & Canada)
    'Egypt Standard Time': 'Africa/Cairo', # D (GMT+02:00) Cairo
    'Ekaterinburg Standard Time': 'Asia/Yekaterinburg', # D (GMT+05:00) Ekaterinburg
    'FLE Standard Time': 'Europe/Kiev', # D (GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius
    'Fiji Standard Time': 'Pacific/Fiji', # D (GMT+12:00) Fiji, Marshall Is.
    'GMT Standard Time': 'Europe/London', # D (GMT) Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London
    'GTB Standard Time': 'Europe/Istanbul', # D (GMT+02:00) Athens, Bucharest, Istanbul
    'Georgian Standard Time': 'Etc/GMT-3', # S (GMT+03:00) Tbilisi
    'Greenland Standard Time': 'America/Godthab', # D (GMT-03:00) Greenland
    'Greenwich Standard Time': 'Atlantic/Reykjavik', # S (GMT) Monrovia, Reykjavik
    'Hawaiian Standard Time': 'Pacific/Honolulu', # S (GMT-10:00) Hawaii
    'India Standard Time': 'Asia/Calcutta', # S (GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi
    'Iran Standard Time': 'Asia/Tehran', # D (GMT+03:30) Tehran
    'Israel Standard Time': 'Asia/Jerusalem', # D (GMT+02:00) Jerusalem
    'Jordan Standard Time': 'Asia/Amman', # D (GMT+02:00) Amman
    'Kamchatka Standard Time': 'Asia/Kamchatka', # D (GMT+12:00) Petropavlovsk-Kamchatsky
    'Korea Standard Time': 'Asia/Seoul', # S (GMT+09:00) Seoul
    'Mauritius Standard Time': 'Indian/Mauritius', # D (GMT+04:00) Port Louis
    'Mexico Standard Time': 'America/Mexico_City', # D [XP] (GMT-06:00) Guadalajara, Mexico City, Monterrey - Old
    'Mexico Standard Time 2': 'America/Chihuahua', # D [XP] (GMT-07:00) Chihuahua, La Paz, Mazatlan - Old
    'Mid-Atlantic Standard Time': 'Etc/GMT+2', # D (GMT-02:00) Mid-Atlantic
    'Middle East Standard Time': 'Asia/Beirut', # D (GMT+02:00) Beirut
    'Montevideo Standard Time': 'America/Montevideo', # D (GMT-03:00) Montevideo
    'Morocco Standard Time': 'Africa/Casablanca', # D (GMT) Casablanca
    'Mountain Standard Time': 'America/Denver', # D (GMT-07:00) Mountain Time (US & Canada)
    'Mountain Standard Time (Mexico)': 'America/Chihuahua', # (GMT-07:00) Chihuahua, La Paz, Mazatlan
    'Myanmar Standard Time': 'Asia/Rangoon', # S (GMT+06:30) Yangon (Rangoon)
    'N. Central Asia Standard Time': 'Asia/Novosibirsk', # D (GMT+06:00) Novosibirsk
    'Namibia Standard Time': 'Africa/Windhoek', # D (GMT+02:00) Windhoek
    'Nepal Standard Time': 'Asia/Katmandu', # S (GMT+05:45) Kathmandu
    'New Zealand Standard Time': 'Pacific/Auckland', # D (GMT+12:00) Auckland, Wellington
    'Newfoundland Standard Time': 'America/St_Johns', # D (GMT-03:30) Newfoundland
    'North Asia East Standard Time': 'Asia/Irkutsk', # D (GMT+08:00) Irkutsk
    'North Asia Standard Time': 'Asia/Krasnoyarsk', # D (GMT+07:00) Krasnoyarsk
    'Pacific SA Standard Time': 'America/Santiago', # D (GMT-04:00) Santiago
    'Pacific Standard Time': 'America/Los_Angeles', # D (GMT-08:00) Pacific Time (US & Canada)
    'Pacific Standard Time (Mexico)': 'America/Tijuana', # D (GMT-08:00) Tijuana, Baja California
    'Pakistan Standard Time': 'Asia/Karachi', # D (GMT+05:00) Islamabad, Karachi
    'Paraguay Standard Time': 'America/Asuncion', # (GMT-04:00) Asuncion
    'Romance Standard Time': 'Europe/Paris', # D (GMT+01:00) Brussels, Copenhagen, Madrid, Paris
    'Russian Standard Time': 'Europe/Moscow', # D (GMT+03:00) Moscow, St. Petersburg, Volgograd
    'SA Eastern Standard Time': 'America/Cayenne', # S (GMT-03:00) Cayenne
    'SA Pacific Standard Time': 'America/Bogota', # S (GMT-05:00) Bogota, Lima, Quito
    'SA Western Standard Time': 'America/La_Paz', # S (GMT-04:00) Georgetown, La Paz, San Juan
    'SE Asia Standard Time': 'Asia/Bangkok', # S (GMT+07:00) Bangkok, Hanoi, Jakarta
    'Samoa Standard Time': 'Pacific/Apia', # S (GMT-11:00) Midway Island, Samoa
    'Singapore Standard Time': 'Asia/Singapore', # S (GMT+08:00) Kuala Lumpur, Singapore
    'South Africa Standard Time': 'Africa/Johannesburg', # S (GMT+02:00) Harare, Pretoria
    'Sri Lanka Standard Time': 'Asia/Colombo', # S (GMT+05:30) Sri Jayawardenepura
    'Taipei Standard Time': 'Asia/Taipei', # S (GMT+08:00) Taipei
    'Tasmania Standard Time': 'Australia/Hobart', # D (GMT+10:00) Hobart
    'Tokyo Standard Time': 'Asia/Tokyo', # S (GMT+09:00) Osaka, Sapporo, Tokyo
    'Tonga Standard Time': 'Pacific/Tongatapu', # S (GMT+13:00) Nuku'alofa
    'US Eastern Standard Time': 'Etc/GMT+5', # S (GMT-05:00) Indiana (East)
    'US Mountain Standard Time': 'America/Phoenix', # S (GMT-07:00) Arizona
    'UTC': 'Etc/GMT', # S (GMT) Coordinated Universal Time
    'Ulaanbaatar Standard Time': 'Asia/Ulaanbaatar', # (GMT+08:00) Ulaanbaatar
    'Venezuela Standard Time': 'America/Caracas', # S (GMT-04:30) Caracas
    'Vladivostok Standard Time': 'Asia/Vladivostok', # D (GMT+10:00) Vladivostok
    'W. Australia Standard Time': 'Australia/Perth', # D (GMT+08:00) Perth
    'W. Central Africa Standard Time': 'Africa/Lagos', # S (GMT+01:00) West Central Africa
    'W. Europe Standard Time': 'Europe/Berlin', # D (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
    'West Asia Standard Time': 'Asia/Tashkent', # S (GMT+05:00) Tashkent
    'West Pacific Standard Time': 'Pacific/Port_Moresby', # S (GMT+10:00) Guam, Port Moresby
    'Yakutsk Standard Time': 'Asia/Yakutsk', # D (GMT+09:00) Yakutsk
}

def disableFsckMountChecks():
    p1 = subprocess.Popen(['mount'], stdout=subprocess.PIPE)
    if not p1:
        return
    
    p2 = subprocess.Popen(['grep', 'on / '], stdin=p1.stdout, stdout=subprocess.PIPE)
    if not p2:
        return
    
    device = subprocess.Popen(['cut', '--delimiter= ', '-f1'], stdin=p2.stdout, stdout=subprocess.PIPE).communicate()[0].strip()
    if not device:
        return
    
    # run tune2fs and set max_mounts_count to 0
    print 'calling /sbin/tune2fs -c 0 ' + device
    os.system('/sbin/tune2fs -c 0 ' + device)


def importTimeZone():
    wintzname = regget('/media/private/windows/Windows/System32/config/SYSTEM', '/ControlSet001/Control/TimeZoneInformation/StandardName')
    if not wintzname:
        # Try with all caps for the windows folder
        wintzname = regget('/media/private/windows/WINDOWS/System32/config/SYSTEM', '/ControlSet001/Control/TimeZoneInformation/StandardName')
    if wintzname:
        wintzcode = wintzname.rsplit('-', 1)[-1]
        
        if wintzcode in idToWinNameTable:
            wintz = idToWinNameTable[wintzcode]
            if wintz in winNameToLinuxName:
                linuxtz = winNameToLinuxName[wintz]
                if os.system('cp /usr/share/zoneinfo/%s /etc/localtime' % linuxtz) == 0:
                    os.system('echo %s > /etc/timezone' % linuxtz)

# Create linux user

def importUser():
    winuser = subprocess.Popen(['sh', '-c', '. /media/private/windows/webnow.sh; echo -n $WEBNOW_WINDOWS_USER'], stdout=subprocess.PIPE).communicate()[0].strip()
    if not winuser:
        return None

    winfullname = subprocess.Popen(['sh', '-c', '. /media/private/windows/webnow.sh; echo -n $WEBNOW_WINDOWS_FULLNAME'], stdout=subprocess.PIPE).communicate()[0].strip()
    if not winfullname:
        winfullname = winuser

    pwline = subprocess.Popen(["getent", "passwd", "1000"], stdout=subprocess.PIPE).communicate()[0].strip()
    if pwline:
        linuser = pwline.split(':')[0]
        os.system("usermod -l %s -d /home/%s -m %s" % (winuser, winuser, linuser)) # change user's name

        # Now get user's name again, in case something went wrong with our usermod call above
        pwline = subprocess.Popen(["getent", "passwd", "1000"], stdout=subprocess.PIPE).communicate()[0].strip()
        if pwline:
            linuser = pwline.split(':')[0]
        else:
            linuser = winuser # assume everything worked

        os.system('chfn -f "%s" %s' % (winfullname, linuser)) # change user's full name
        os.system("usermod -p '*' %s" % linuser) # delete any password

    # Let user sudo some apps without a password at all.
    # Reboot and Synatpic for Update Manager.
    os.system("echo '%s	ALL=NOPASSWD: /sbin/reboot, /usr/sbin/synaptic, /usr/bin/winboot-reboot, /usr/bin/language-installer' >> /etc/sudoers" % linuser)

    # save winuser as linuser too since they are the same now
    os.system('mkdir -p /var/lib/omsk')
    os.system('echo "%s" > /var/lib/omsk/winuser' % winuser)
    os.system('echo "%s" > /var/lib/omsk/linuser' % linuser)
    os.system('chmod o-r /var/lib/omsk/winuser')
    os.system('chmod o-r /var/lib/omsk/linuser')

    return winuser

winuser = None

if 'firstboot' in sys.argv:
    #try:    importWifi()
    #except: pass
    try:                 importTimeZone()
    except Exception, e: print >> sys.stderr, 'Could not import timezone:', e
    try:                 winuser = importUser()
    except Exception, e: print >> sys.stderr, 'Could not import user:', e
    os.system('mkdir -p /var/lib/omsk')
    os.system('touch /var/lib/omsk/imported')
    disableFsckMountChecks()
else:
    winuser = subprocess.Popen(['cat', '/var/lib/omsk/winuser'], stdout=subprocess.PIPE).communicate()[0].strip()

if winuser:
    try:                 importLocale(winuser)
    except Exception, e: print >> sys.stderr, 'Could not import locale:', e
    try:                 importKeyboard(winuser)
    except Exception, e: print >> sys.stderr, 'Could not import keyboard:', e
