#!/usr/bin/env python
#Licence: GPLv3.0
#Copyright: Krasimir S. Stefanov

import locale
import sys
import ConfigParser
import os
import os.path
import gettext
import pygtk
import time
import gtk
import gtk.glade
import gobject
import platform
import shutil
import re
import asubprocess
import urllib
import signal
try:
    import libtorrent
    LIBTORRENT_AVAILABLE = True
except:
    LIBTORRENT_AVAILABLE = False
    
import tempfile
import statvfs
from threading import Thread
import hashlib
if platform.system() == "Windows":
    import pywintypes
    import win32com.client
    import wmi
    import win32file
    import win32api
    import win32pipe
    from win32file import ReadFile, WriteFile
    from win32pipe import PeekNamedPipe
    import msvcrt
else:
    import dbus

APP = "live-usb-install"
APP_VERSION = "2.2.10"
DEFAULT_DISTRO = "7.0 - Desktop - amd64"

locale.setlocale(locale.LC_ALL, '')
if platform.system() == "Windows":
    DIR = "locale"
    os.environ['LANG'] = locale.getdefaultlocale()[0]
else:
    if os.path.exists('./locale'):
        DIR = os.path.join(os.path.dirname(sys.argv[0]),"locale")
    else:
        DIR = os.path.join(sys.prefix, 'share', 'locale')

(lang_code, encoding) = locale.getlocale()
gettext.bindtextdomain(APP, DIR)
gettext.textdomain(APP)
gettext.install(APP, localedir=DIR)
gtk.glade.bindtextdomain(APP, DIR)
gtk.glade.textdomain(APP)
_ = gettext.gettext

gobject.threads_init()

class appgui:
    def __init__(self):
        self.glade_dir = os.path.dirname(sys.argv[0])
        self.gladefile = os.path.join(self.glade_dir, "live-usb-install.glade")
        self.md5sum_thread = None
        windowname = "window1"    
        self.widgets = gtk.glade.XML(self.gladefile,windowname,APP)

        dic = { "on_button1_clicked" : self.on_button1_clicked,
                "on_button2_clicked" : self.on_button2_clicked,
                "on_button3_clicked" : self.on_button3_clicked,
                "on_button4_clicked" : self.on_button4_clicked,
                "on_button5_clicked" : self.on_button5_clicked,
                "on_button6_clicked" : self.on_button6_clicked,
                "on_button7_clicked" : self.on_button7_clicked,
                "on_button8_clicked" : self.on_button8_clicked,
                "on_button9_clicked" : self.on_button9_clicked,
                "on_button10_clicked" : self.on_button10_clicked,
                "on_button11_clicked": self.on_button11_clicked,
                "on_combobox1_changed" : self.on_combobox1_changed,
                "on_combobox2_changed" : self.on_combobox2_changed,
                "on_combobox6_changed" : self.on_combobox6_changed,
                "on_radiobutton1_toggled" : self.on_radiobutton1_toggled,
                "on_radiobutton2_toggled" : self.on_radiobutton2_toggled,
                "on_checkbutton1_toggled" : self.on_checkbutton1_toggled,
                "on_filechooserbutton2_file_set" : self.on_filechooserbutton2_file_set,
                "on_checkbutton2_toggled" : self.on_checkbutton2_toggled,
                "on_window1_delete_event" : self.on_button3_clicked}
        self.widgets.signal_autoconnect (dic)
        
        splash = gtk.Window() 
        vbox = gtk.VBox(False, 10)
        vbox.set_border_width(10)
        
        label = gtk.Label()
        label.set_markup('<span size="large" weight="bold">%s</span>' % _("Loading, please wait..."))
        
        label1 = gtk.Label()
        label1.set_markup('<span size="large" weight="bold">%s %s</span>' % (_("LiveUSB Install"), APP_VERSION))
        
        splash.set_position(gtk.WIN_POS_CENTER_ALWAYS)
        
        image = gtk.Image()
        image.set_from_file(os.path.join(os.path.abspath(self.glade_dir),"logo.png"))
        
        vbox.add(label1)
        vbox.add(image)
        vbox.add(label)
        splash.add(vbox)

        splash.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_SPLASHSCREEN)
        splash.set_decorated(False)
        splash.show_all()

        while gtk.events_pending():
            gtk.main_iteration_do()
        
        #setup versions ComboBox
        liststore = gtk.ListStore(gobject.TYPE_STRING)
        self.widgets.get_widget("combobox2").set_model(liststore)
        cell = gtk.CellRendererText()
        self.widgets.get_widget("combobox2").pack_start(cell, True)
        self.widgets.get_widget("combobox2").add_attribute(cell, 'text', 0)  

        # list distributions
        liststore_distributions = gtk.ListStore(gobject.TYPE_STRING)
        self.widgets.get_widget("combobox1").set_model(liststore_distributions)
        cell = gtk.CellRendererText()
        self.widgets.get_widget("combobox1").pack_start(cell, True)
        self.widgets.get_widget("combobox1").add_attribute(cell, 'text', 0)  
        
        self.presets_dir = os.path.join(os.path.abspath(self.glade_dir),"presets")
        self.presets = os.listdir(self.presets_dir)
                
        self.list_distributions()
        self.list_distribution_versions()
        self.combobox_select(self.widgets.get_widget("combobox1"),"USU",0)
        self.combobox_select(self.widgets.get_widget("combobox2"), DEFAULT_DISTRO,0)
        
        self.widgets.get_widget("combobox1").get_model().set_sort_column_id(0,gtk.SORT_ASCENDING)
        #self.widgets.get_widget("combobox2").get_model().set_sort_column_id(0,gtk.SORT_ASCENDING)
        
        # setup cd drives combobox
        liststore_drives = gtk.ListStore(gtk.gdk.Pixbuf, gobject.TYPE_STRING,gobject.TYPE_STRING)
        self.widgets.get_widget("combobox3").set_model(liststore_drives)
        
        cell_icon = gtk.CellRendererPixbuf()
        cell0 = gtk.CellRendererText()
        cell1 = gtk.CellRendererText()

        self.widgets.get_widget("combobox3").pack_start(cell_icon, False)
        self.widgets.get_widget("combobox3").pack_start(cell0, False)
        self.widgets.get_widget("combobox3").pack_start(cell1, True)

        self.widgets.get_widget("combobox3").add_attribute(cell_icon, 'pixbuf', 0)  
        self.widgets.get_widget("combobox3").add_attribute(cell0, 'text', 1)  
        self.widgets.get_widget("combobox3").add_attribute(cell1, 'text', 2)  
        
        #list cd drives
        self.on_button5_clicked(self.widgets.get_widget("button5"))
        
        # setup removable drives combobox
        liststore_drives1 = gtk.ListStore(gtk.gdk.Pixbuf, gobject.TYPE_STRING, \
            gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_INT, \
            gobject.TYPE_STRING)
        self.widgets.get_widget("combobox4").set_model(liststore_drives1)
        
        cell0 = gtk.CellRendererPixbuf()
        cell1 = gtk.CellRendererText()
        cell2 = gtk.CellRendererText()
        cell3 = gtk.CellRendererText()
        
        cell4 = gtk.CellRendererProgress()
        cell4.set_property("pulse", -1)
        cell4.set_property("orientation", gtk.PROGRESS_LEFT_TO_RIGHT)
        cell4.set_property("width", 180)
        
        cell5 = gtk.CellRendererText()
        cell5.set_property("visible",0)
        
        self.widgets.get_widget("combobox4").pack_start(cell0, False)
        self.widgets.get_widget("combobox4").pack_start(cell1, False)
        self.widgets.get_widget("combobox4").pack_start(cell2, False)
        self.widgets.get_widget("combobox4").pack_start(cell3, True)
        self.widgets.get_widget("combobox4").pack_start(cell4, False)
        self.widgets.get_widget("combobox4").pack_start(cell5, False)
        
        self.widgets.get_widget("combobox4").add_attribute(cell0, 'pixbuf', 0)  
        self.widgets.get_widget("combobox4").add_attribute(cell1, 'text', 1)  
        self.widgets.get_widget("combobox4").add_attribute(cell2, 'text', 2)  
        self.widgets.get_widget("combobox4").add_attribute(cell3, 'text', 3)  
        
        self.widgets.get_widget("combobox4").add_attribute(cell4, 'value', 4)  
        self.widgets.get_widget("combobox4").add_attribute(cell4, 'text', 5)

        # list removable disk drives
        self.on_button4_clicked(self.widgets.get_widget("button4"))
        self.widgets.get_widget("radiobutton8").set_active(True)
        
        splash.destroy()
        self.widgets.get_widget("combobox6").set_active(0)
        
        self.widgets.get_widget("filechooserbutton2").set_current_folder((os.getenv('HOME') or os.getenv('USERPROFILE')) \
            if platform.system() == "Windows" else ('/media' if os.path.exists('/media') else '/mnt'))
        self.widgets.get_widget("filechooserbutton1").set_current_folder((os.getenv('HOME') or os.getenv('USERPROFILE')) \
            if platform.system() == "Windows" else ('/media' if os.path.exists('/media') else '/mnt'))
        self.widgets.get_widget("window1").show()
        
        UpdaterThread(self.vercheck_done).start()
        return
    
    def vercheck_done(self, result):
        self.msg_info(_("A new version of this program is available - %(version)s!\nDownload it from: %(url)s") % {'version': result[0], 'url': result[1]})

    def list_removable_drives(self):
        """ Detect all removable USB storage devices using HAL via D-Bus """
        self.drives = {}
        if platform.system() == "Windows":
            c = wmi.WMI ()
            for disk in c.query("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'"):
                for partition in c.query("SELECT * FROM Win32_DiskPartition WHERE DiskIndex='" + str(disk.Index) + "'"):
                    for partition_1 in c.query("SELECT * FROM Win32_LogicalDiskToPartition"):
                        if partition.DeviceID == partition_1.Antecedent.DeviceID:
                            try:
                                info = win32api.GetVolumeInformation(partition_1.Dependent.DeviceID)
                                drive = partition_1.Dependent.DeviceID
                                self.drives[drive] = {
                                        'label': info[0],
                                        'mount': drive,
                                        'uuid': self._get_device_uuid(drive),
                                        'free': self.get_free_bytes(drive),
                                        'fstype': info[-1],
                                        'device': drive,
                                        'fsversion': info[-1],
                                        'size': self._get_device_size(drive)
                                }
                            except:
                                pass
        else:
            try:
                import pyudev
                context = pyudev.Context()
                enumerator = pyudev.Enumerator(context)
                enumerator.match(subsystem="block", ID_FS_USAGE="filesystem", ID_TYPE="disk", ID_BUS="usb")
                for device in enumerator:
                    if 'DEVTYPE' in device \
                        and 'ID_FS_UUID' in device \
                        and 'ID_FS_USAGE' in device \
                        and 'ID_TYPE' in device \
                        and 'ID_FS_TYPE' in device \
                        and 'ID_BUS' in device:
                        if device['ID_BUS'] == 'usb' and device['ID_FS_USAGE'] == 'filesystem':
                            mountpoint = os.popen('mount | grep %s | cut -d" " -f3' % device['DEVNAME']).read().strip()
                            size = os.popen("df -B 1 %s | head -n2 | tail -1 | awk '{ print $2 }'" % device['DEVNAME']).read().strip()
                            if 'ID_FS_VERSION' in device:
                                ID_FS_VERSION = device['ID_FS_VERSION']
                            else:
                                ID_FS_VERSION = ''
                            if 'ID_FS_LABEL' in device:
                                ID_FS_LABEL = device['ID_FS_LABEL']
                            else:
                                ID_FS_LABEL = ''
                            if mountpoint:
                                self.drives[device['DEVNAME']] = {
                                    'label'   : ID_FS_LABEL,
                                    'fstype'  : device['ID_FS_TYPE'],
                                    'fsversion': ID_FS_VERSION,
                                    'uuid'    : device['ID_FS_UUID'],
                                    'mount'   : mountpoint,
                                    'udi'     : None,
                                    'unmount' : False,
                                    'free'    : mountpoint and int(self.get_free_bytes(mountpoint)) or None,
                                    'size': int(size),
                                    'device'  : device['DEVNAME'],
                                    'parent'  : self.get_parent_device(device['DEVNAME'])
                                }
            except:
                import dbus
                self.drives = {}
                self.bus = dbus.SystemBus()
                hal_obj = self.bus.get_object("org.freedesktop.Hal","/org/freedesktop/Hal/Manager")
                self.hal = dbus.Interface(hal_obj, "org.freedesktop.Hal.Manager")
                devices = []
                devices = self.hal.FindDeviceByCapability("storage")
                for device in devices:
                    dev = self._get_device(device)
                    if self._storage_bus(dev) == "usb":
                        if self._block_is_volume(dev):
                            self._add_device(dev)
                            continue
                        else: # iterate over children looking for a volume
                            children = self.hal.FindDeviceStringMatch("info.parent",device)
                            for child in children:
                                child = self._get_device(child)
                                if self._block_is_volume(child):
                                    self._add_device(child, parent=dev)
                                    #break      # don't break, allow all partitions
                                    
        return self.drives
    
    def list_distributions(self):
        self.widgets.get_widget("combobox1").get_model().clear()
        if self.presets:
            for preset in self.presets:
                self.widgets.get_widget("combobox1").append_text(preset)
                self.widgets.get_widget("combobox1").set_active(0)
    
    def list_distribution_versions(self):
        self.widgets.get_widget("combobox2").get_model().clear()
        path = os.path.join(self.presets_dir, \
            self.widgets.get_widget("combobox1").get_active_text())
        presets = os.listdir(path)
        
        sort_nicely(presets)
        
        for preset in presets:
            if os.path.isdir(path + "/" + preset) == True:
                self.widgets.get_widget("combobox2").append_text(preset)

        return

    def _get_device(self, udi):
        """ Return a dbus Interface to a specific HAL device UDI """
        import dbus
        dev_obj = self.bus.get_object("org.freedesktop.Hal", udi)
        return dbus.Interface(dev_obj, "org.freedesktop.Hal.Device")

    def _storage_bus(self, dev):
        storage_bus = None
        try:
            storage_bus = dev.GetProperty('storage.bus')
        except:
            return
        return storage_bus

    def _block_is_volume(self, dev):
        is_volume = False
        try:
            is_volume = dev.GetProperty("block.is_volume")
        except:
            return
        return is_volume
        
    def _add_device(self, dev, parent=None):
        mount = str(dev.GetProperty('volume.mount_point'))
        device = str(dev.GetProperty('block.device'))
        if parent:
            parent = parent.GetProperty('block.device')
        if mount:
            self.drives[device] = {
                'label'   : str(dev.GetProperty('volume.label')).replace(' ', '_'),
                'fstype'  : str(dev.GetProperty('volume.fstype')),
                'fsversion': str(dev.GetProperty('volume.fsversion')),
                'uuid'    : str(dev.GetProperty('volume.uuid')),
                'mount'   : mount,
                'udi'     : dev,
                'unmount' : False,
                'free'    : mount and self.get_free_bytes(mount) or None,
                'size': self._get_device_size(dev),
                'device'  : device,
                'parent'  : parent
            }
    
    def get_free_bytes(self, device=None):
        """ Return the number of free bytes on our selected drive """
        if platform.system() == "Windows":
            import win32file
            device = device and device or self.drive['device']
            try:
                (spc, bps, fc, tc) = win32file.GetDiskFreeSpace(device)
            except:
                return 0
            return fc * (spc * bps) # free-clusters * bytes per-cluster    
        else:
            import statvfs
            device = device and device or self.dest
            stat = os.statvfs(device)
            return stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL]
        

    def _get_device_uuid(self, drive):
        """ Return the UUID of our selected drive (win32)"""
        #print "_get_device_uuid(%s)" % drive
        uuid = None
        try:
            uuid = self._get_win32_logicaldisk(drive).VolumeSerialNumber
            if uuid in (None, 'None', ''):
                uuid = None
            else:
                uuid = uuid[:4] + '-' + uuid[4:]
        except:
            return None
        return uuid
        
    # Cache these, because they are fairly expensive
    _win32_logicaldisk = {}
    def _get_win32_logicaldisk(self, drive):
        #print "_get_win32_logicaldisk(%s)" % drive
        """ Return the Win32_LogicalDisk object for the given drive """
        import win32com.client
        cache = self._win32_logicaldisk.get('drive')
        if cache:
            return cache
        obj = None
        try:
            obj = win32com.client.Dispatch("WbemScripting.SWbemLocator") \
                         .ConnectServer(".", "root\cimv2") \
                         .ExecQuery("Select * from Win32_LogicalDisk where Name = '%s'" %    drive)
            if obj:
                obj = obj[0]
                self._win32_logicaldisk[drive] = obj
        except:
            return None
        return obj
        
    def _get_device_size(self, drive):
        """ Return the size of the given drive """
        size = None
        try:
            if platform.system() == "Windows":
                size = int(self._get_win32_logicaldisk(drive).Size)
            else:
                size = drive.GetProperty('volume.size')
        except:
            return None
        return size
    
    def download_torrent(self, torrent, target_dir, http_referrer = None):
        print "download_torrent", torrent, target_dir, http_referrer
        local_torrent = os.path.join(tempfile.gettempdir(), 'live-usb-install', \
            self.widgets.get_widget("combobox1").get_active_text() + ' - ' \
            + self.widgets.get_widget("combobox2").get_active_text() + '.torrent')
        if http_referrer:
            print 'wget --referer="%s" "%s" -O"%s"' % (http_referrer, torrent, local_torrent)
            download_result = os.system('wget --no-check-certificate --referer="%s" "%s" -O"%s"' \
                % (http_referrer, torrent, local_torrent))
        else:
            download_result = os.system('wget --no-check-certificate "%s" -O"%s"' \
                % (torrent, local_torrent))
        
        if download_result != 0:
            self.msg_error(_("Error while downloading torrent file! Installation aborted."))
            self.widgets.get_widget("window1").show()
            return 1

        try:
            e = libtorrent.bdecode(open(local_torrent, 'rb').read())
            info = libtorrent.torrent_info(e)
        except:
            return 1
        ns = Namespace()
        ns.kill_process = False

        def cancel_process(widget, other = None):
            ns.kill_process = True
            return True
        
        window = gtk.glade.XML(self.gladefile,"window2" ,APP)
        gtk.glade.bindtextdomain(APP,DIR)
        dic = {
            "on_window2_delete_event" : (cancel_process),
            "on_button1_clicked" : (cancel_process)
        }
        window.signal_autoconnect (dic)

        window.get_widget('image1').set_from_icon_name('application-x-bittorrent',64)
        window.get_widget('label1').set_markup('<span size="large" weight="bold">%s</span>' \
            % _("Downloading torrent..."))
        window.get_widget('label3').set_text(torrent)
        
        ses = libtorrent.session()
        ses.listen_on(6881, 6891)
        h = ses.add_torrent(info, target_dir, storage_mode=libtorrent.storage_mode_t.storage_mode_sparse)

        window.get_widget('label3').set_text(torrent)
        window.get_widget('label11').set_text(target_dir)
        
        window.get_widget('label14').show()
        window.get_widget('label15').show()
        
        while (not h.is_seed()):
            if ns.kill_process:
                self.widgets.get_widget("window1").show()
                while gtk.events_pending():
                    gtk.main_iteration_do()            
                ses.remove_torrent(h)
                ses.pause()
                break
            s = h.status()
            state_str = [_('queued'), _('checking'), _('downloading metadata'), \
                _('downloading'), _('finished'), _('seeding'), _('allocating')]

            window.get_widget('label5').set_text(_('%(sizemb).2fMB (%(sizeb)d bytes)') \
                % {'sizemb': s.total_wanted / 1024.0**2, 'sizeb': s.total_wanted})
            window.get_widget('label7').set_text(_('%(sizemb).2fMB (%(sizeb)d bytes)') \
                % {'sizemb': s.total_download / 1024.0**2, 'sizeb': s.total_download})
            window.get_widget('label9').set_text(_('%.1fkB/s') \
                % (s.download_rate / 1024))
            window.get_widget('label15').set_text(str(s.num_peers))
            
            if s.state == 3 or s.state == 1:
                window.get_widget("progressbar1").set_fraction(s.progress)
                window.get_widget("progressbar1").set_text('%s %.2f%%' \
                    % (state_str[s.state],s.progress*100))
            else:
                window.get_widget("progressbar1").pulse()
                try:
                    window.get_widget("progressbar1").set_text('%s %.2f%%' \
                        % (state_str[s.state],s.progress*100))
                except:
                    pass
                        
            time.sleep(0.05)
            while gtk.events_pending():
                gtk.main_iteration_do()            
                
        window.get_widget("window2").destroy()
        while gtk.events_pending():
            gtk.main_iteration_do()            
        if ns.kill_process:
            return 1
        else:
            return 0
    
    def mkfs(self, location, label):
        print "format_casper_rw", location
        ns = Namespace()
        
        def cancel_process(widget, other = None):
            ns.kill_process = True
            return False
            
            
        window = gtk.glade.XML(self.gladefile,"window5" ,APP)
        gtk.glade.bindtextdomain(APP,DIR)
        dic = {
            "progress_cancel" : (cancel_process),
        }
        
        window.signal_autoconnect (dic)

        window.get_widget('image1').set_from_icon_name('drive-harddisk',64)
        window.get_widget('window5').set_title(_('live-usb-install') + ' - ' + \
            (_('Formatting %s') % label))
        window.get_widget('label1').set_markup('<span size="large" weight="bold">%s</span>' \
            % (_('Formatting %s') % label))

        while gtk.events_pending():
            gtk.main_iteration_do()
        
        if platform.system() == "Windows":
            argv = ['mke2fs.exe', '-F', '-L', label, location]    
        else:
            argv = ['mkfs.ext2', '-F', '-L', label, location]
            
        #print ' '.join(argv)
        info = None
        if platform.system() == "Windows":
            info = asubprocess.STARTUPINFO()
            info.dwFlags |= asubprocess.STARTF_USESHOWWINDOW
            info.wShowWindow = asubprocess.SW_HIDE
        
        ns.process = asubprocess.Popen(argv, startupinfo=info)

        ns.kill_process = False        
        while ns.process.poll() == None:
            if ns.kill_process:
                if platform.system() == "Windows":
                    os.system("taskkill /PID %d /F" % ns.process.pid)
                else:
                    os.kill(ns.process.pid, signal.SIGKILL)
                ns.process.wait()
                window.get_widget("window5").destroy()
                return ns.process.returncode
                
            else:
                window.get_widget("progressbar1").pulse()

            while gtk.events_pending():
                gtk.main_iteration_do()
            time.sleep(0.05)
                
        window.get_widget("window5").destroy()
        return ns.process.returncode    
    
    
    def write_img(self, fileFrom, fileTo, title = _('Writing disk image file'), bs = '16M', count = None):
        print "write_img", fileFrom, fileTo, title, bs, count
        ns = Namespace()
        
        def cancel_process(widget, other = None):
            ns.kill_process = True
            return False
            
            
        window = gtk.glade.XML(self.gladefile,"window5" ,APP)
        gtk.glade.bindtextdomain(APP,DIR)
        dic = {
            "progress_cancel" : (cancel_process),
        }
        
        window.signal_autoconnect (dic)

        window.get_widget('image1').set_from_icon_name('drive-harddisk',64)
        window.get_widget('window5').set_title(_('live-usb-install') + ' - ' + title)
        window.get_widget('label1').set_markup('<span size="large" weight="bold">%s</span>' % title)
        while gtk.events_pending():
            gtk.main_iteration_do()
        
        if platform.system() == "Windows":
            argv = ['dd','if=%s' % fileFrom.encode(sys.getfilesystemencoding(), 'replace'), 'of=\\\.\%s' % fileTo, '--progress', 'bs=%s' % bs]    
        else:
            argv = ['dd','if=%s' % fileFrom.encode(sys.getfilesystemencoding(), 'replace'),'of=%s' % fileTo, 'bs=%s' % bs]        
            
        if count:
            argv.append('count=%d' % count)    
            
        info = None
        if platform.system() == "Windows":
            info = asubprocess.STARTUPINFO()
            info.dwFlags |= asubprocess.STARTF_USESHOWWINDOW
            info.wShowWindow = asubprocess.SW_HIDE

        ns.process = asubprocess.Popen(argv, startupinfo=info)

        ns.kill_process = False        
        while ns.process.poll() == None:
            if ns.kill_process:
                if platform.system() == "Windows":
                    os.system("taskkill /PID %d /F" % ns.process.pid)
                else:
                    os.kill(ns.process.pid, signal.SIGKILL)
                ns.process.wait()
                window.get_widget("window5").destroy()
                return ns.process.returncode
                
            else:
                window.get_widget("progressbar1").pulse()

            while gtk.events_pending():
                gtk.main_iteration_do()
            time.sleep(0.05)
                
        window.get_widget("window5").destroy()
        return ns.process.returncode
        
        
    def copy_file(self, fileFrom, fileTo):
        print "copy_file", fileFrom, fileTo
        ns = Namespace()
        
        def cancel_process(widget, other = None):
            ns.kill_process = True
            return False
            
            
        window = gtk.glade.XML(self.gladefile,"window5" ,APP)
        gtk.glade.bindtextdomain(APP,DIR)
        dic = {
            "progress_cancel" : (cancel_process),
        }
        
        window.signal_autoconnect (dic)

        window.get_widget('image1').set_from_icon_name('drive-harddisk',64)
        window.get_widget('window5').set_title(_('live-usb-install')+' - ' + _('Copying files...'))
        window.get_widget('label1').set_markup('<span size="large" weight="bold">%s</span>' % _('Copying files...'))
        
        while gtk.events_pending():
            gtk.main_iteration_do()
        
        if platform.system() == "Windows":
            argv = ['xcopy',fileFrom.encode(sys.getfilesystemencoding(), 'replace'),fileTo.encode(sys.getfilesystemencoding(), 'replace'),'/H','/R','/Y','/i']    
        else:
            argv = ['rsync','-v','--progress', fileFrom.encode(sys.getfilesystemencoding(), 'replace'),fileTo.encode(sys.getfilesystemencoding(), 'replace')]        
        
        info = None
        if platform.system() == "Windows":
            info = asubprocess.STARTUPINFO()
            info.dwFlags |= asubprocess.STARTF_USESHOWWINDOW
            info.wShowWindow = asubprocess.SW_HIDE

        ns.process = asubprocess.Popen(argv, startupinfo=info)

        ns.kill_process = False        
        while ns.process.poll() == None:
            if ns.kill_process:
                if platform.system() == "Windows":
                    os.system("taskkill /PID %d /F" % ns.process.pid)
                else:
                    os.kill(ns.process.pid, signal.SIGKILL)
                ns.process.wait()
                window.get_widget("window5").destroy()
                return ns.process.returncode
                
            else:
                window.get_widget("progressbar1").pulse()

            while gtk.events_pending():
                gtk.main_iteration_do()
            time.sleep(0.05)
                
        window.get_widget("window5").destroy()
        return ns.process.returncode

    
    def uncompress(self, archive, target_dir):
        print "uncompress", archive, target_dir
        ns = Namespace()
        def cancel_process(widget, other = None):
            ns.kill_process = True
            return False
        
        window = gtk.glade.XML(self.gladefile,"window5" ,APP)
        gtk.glade.bindtextdomain(APP,DIR)
        dic = {
            "progress_cancel" : (cancel_process),
        }
        window.signal_autoconnect (dic)

        window.get_widget('window5').set_title(_('live-usb-install') + ' - ' + _('Extracting files...'))
        window.get_widget('label1').set_markup('<span size="large" weight="bold">%s</span>' % _('Extracting files...'))


        while gtk.events_pending():
            gtk.main_iteration_do()

        argv = ['7z','x','-y',('-o'+target_dir).encode(sys.getfilesystemencoding(), 'replace'),archive.encode(sys.getfilesystemencoding(), 'replace')]        
        info = None
        if platform.system() == "Windows":
            info = asubprocess.STARTUPINFO()
            info.dwFlags |= asubprocess.STARTF_USESHOWWINDOW
            info.wShowWindow = asubprocess.SW_HIDE

        ns.process = asubprocess.Popen(argv, startupinfo=info)
        ns.kill_process = False        
        
        while ns.process.poll() == None:
            if ns.kill_process:
                if platform.system() == "Windows":
                    os.system("taskkill /PID %d /F" % ns.process.pid)
                else:
                    os.kill(ns.process.pid, signal.SIGKILL)
                ns.process.wait()
                window.get_widget("window5").destroy()
                return ns.process.returncode
                
            else:
                window.get_widget("progressbar1").pulse()

            while gtk.events_pending():
                gtk.main_iteration_do()
            time.sleep(0.05)
                
        window.get_widget("window5").destroy()
        return ns.process.returncode
    
    
    
    def copy_from_cd(self, dirFrom, dirTo):
        print "copy_from_cd", dirFrom, dirTo
        ns = Namespace()

        def cancel_process(widget, other = None):
            ns.kill_process = True
            return False
            
            
        window = gtk.glade.XML(self.gladefile,"window5" ,APP)
        gtk.glade.bindtextdomain(APP,DIR)
        dic = {
            "progress_cancel" : (cancel_process),
        }
        window.signal_autoconnect (dic)
        
        window.get_widget('image1').set_from_icon_name('media-optical',64)
        window.get_widget('window5').set_title(_('live-usb-install') + ' - ' + _('Copying files from CD/DVD...'))
        window.get_widget('label1').set_markup('<span size="large" weight="bold">%s</span>' % _('Copying files from CD/DVD...'))

        while gtk.events_pending():
            gtk.main_iteration_do()
        
        if platform.system() == "Windows":
            argv = ['xcopy',(dirFrom+'*.*').encode(sys.getfilesystemencoding(), 'replace'),(dirTo+'*.*').encode(sys.getfilesystemencoding(), 'replace'),'/H','/E','/R','/Y']    
        else:
            argv = ['rsync','-rv','--include=".*"','--include=".*/"', '--progress', (dirFrom+'/').encode(sys.getfilesystemencoding(), 'replace'),dirTo.encode(sys.getfilesystemencoding(), 'replace')]        
                
        info = None
        if platform.system() == "Windows":
            info = asubprocess.STARTUPINFO()
            info.dwFlags |= asubprocess.STARTF_USESHOWWINDOW
            info.wShowWindow = asubprocess.SW_HIDE

        ns.process = asubprocess.Popen(argv, startupinfo=info)
        ns.kill_process = False    
        
        while ns.process.poll() == None:
            if ns.kill_process:
                if platform.system() == "Windows":
                    os.system("taskkill /PID %d /F" % ns.process.pid)
                else:
                    os.kill(ns.process.pid, signal.SIGKILL)
                ns.process.wait()
                window.get_widget("window5").destroy()
                return ns.process.returncode
                
            else:
                window.get_widget("progressbar1").pulse()

            while gtk.events_pending():
                gtk.main_iteration_do()
            time.sleep(0.05)
                
        window.get_widget("window5").destroy()
        return ns.process.returncode
        
        
    def uncompress_iso(self, archive, filename, target_dir, archive_type):
        print "uncompress_iso", archive, filename, target_dir, archive_type
        ns = Namespace()

        def cancel_process(widget, other = None):
            ns.kill_process = True
            return False
            
            
        window = gtk.glade.XML(self.gladefile,"window5" ,APP)
        gtk.glade.bindtextdomain(APP,DIR)
        dic = {
            "progress_cancel" : (cancel_process),
        }
        window.signal_autoconnect (dic)
        window.get_widget('window5').set_title(_('live-usb-install') + ' - ' + _('Extracting ISO image from downloaded archive...'))
        window.get_widget('label1').set_markup('<span size="large" weight="bold">%s</span>' % _('Extracting ISO image from downloaded archive...'))

        while gtk.events_pending():
            gtk.main_iteration_do()
        
        if archive_type == 'rar':
            argv = ['unrar','e',archive.encode(sys.getfilesystemencoding(), 'replace'),filename.encode(sys.getfilesystemencoding(), 'replace'),target_dir.encode(sys.getfilesystemencoding(), 'replace')]
        else:
            argv = ['7z','e','-y','-o'+target_dir.encode(sys.getfilesystemencoding(), 'replace'),archive.encode(sys.getfilesystemencoding(), 'replace'),filename.encode(sys.getfilesystemencoding(), 'replace')]        
                
        info = None
        if platform.system() == "Windows":
            info = asubprocess.STARTUPINFO()
            info.dwFlags |= asubprocess.STARTF_USESHOWWINDOW
            info.wShowWindow = asubprocess.SW_HIDE

        ns.process = asubprocess.Popen(argv, startupinfo=info)
        ns.kill_process = False    
        
        while ns.process.poll() == None:
            if ns.kill_process:

                
                if platform.system() == "Windows":
                    os.system("taskkill /PID %d /F" % ns.process.pid)
                else:
                    os.kill(ns.process.pid, signal.SIGKILL)
                ns.process.wait()
                window.get_widget("window5").destroy()
                return ns.process.returncode
                
            else:
                window.get_widget("progressbar1").pulse()

            while gtk.events_pending():
                gtk.main_iteration_do()
            time.sleep(0.05)
                
        window.get_widget("window5").destroy()
        return ns.process.returncode
        
    def extract_iso(self, iso_location, extract_to):
        print "extract_iso", iso_location, extract_to
        ns = Namespace()

        def cancel_process(widget, other = None):
            ns.kill_process = True
            return False

        window = gtk.glade.XML(self.gladefile,"window5" ,APP)
        gtk.glade.bindtextdomain(APP,DIR)
        dic = {
            "progress_cancel" : (cancel_process),
        }
        window.signal_autoconnect (dic)
        window.get_widget('window5').set_title(_('live-usb-install') + ' - ' + _('Extracting files from ISO image...'))
        window.get_widget('label1').set_markup('<span size="large" weight="bold">%s</span>' % _('Extracting files from ISO image...'))

        while gtk.events_pending():
            gtk.main_iteration_do()
        
        argv = ['7z','x',iso_location.encode(sys.getfilesystemencoding(), 'replace'),'-x![BOOT]','-y',('-o%s' % extract_to).encode(sys.getfilesystemencoding(), 'replace')]
        info = None
        if platform.system() == "Windows":
            info = asubprocess.STARTUPINFO()
            info.dwFlags |= asubprocess.STARTF_USESHOWWINDOW
            info.wShowWindow = asubprocess.SW_HIDE

        ns.process = asubprocess.Popen(argv, startupinfo=info)
        ns.kill_process = False    
        
        while ns.process.poll() == None:
            if ns.kill_process:
                if platform.system() == "Windows":
                    os.system("taskkill /PID %d /F" % ns.process.pid)
                else:
                    os.kill(ns.process.pid, signal.SIGKILL)
                ns.process.wait()
                window.get_widget("window5").destroy()
                return ns.process.returncode
                
            else:
                window.get_widget("progressbar1").pulse()

            while gtk.events_pending():
                gtk.main_iteration_do()
            time.sleep(0.05)

        window.get_widget("window5").destroy()
        return ns.process.returncode
        
    def download_file(self, remote, local, http_referrer = None):
        if not remote:
            self.msg_error(_("The download link is invalid!"))
            return 1
        ns = Namespace()
        
        def cancel_process(widget, other = None):
            ns.kill_process = True
            return False

        window = gtk.glade.XML(self.gladefile,"window2" ,APP)
        gtk.glade.bindtextdomain(APP,DIR)
        dic = {
            "on_button1_clicked" : (cancel_process),
            "on_window2_delete_event" : (cancel_process)
        }
        window.signal_autoconnect (dic)

        window.get_widget('label3').set_text(remote)
        window.get_widget("label11").set_text(local)

        while gtk.events_pending():
            gtk.main_iteration_do()
            
        if http_referrer:
            argv = ['wget','--no-check-certificate','--referer="%s"' % http_referrer,'-S','-c',remote,'-O',local.encode(sys.getfilesystemencoding(), 'replace')]
        else:
            argv = ['wget','--no-check-certificate','-S','-c',remote,'-O',local.encode(sys.getfilesystemencoding(), 'replace')]
            
        info = None
        if platform.system() == "Windows":
            info = asubprocess.STARTUPINFO()
            info.dwFlags |= asubprocess.STARTF_USESHOWWINDOW
            info.wShowWindow = asubprocess.SW_HIDE

        ns.process = asubprocess.Popen(argv, stdout=asubprocess.PIPE, stderr=asubprocess.PIPE, startupinfo=info)
        ns.kill_process = False
        
        while ns.process.poll() == None:
            if ns.kill_process:
                if platform.system() == "Windows":
                    os.system("taskkill /PID %d /F" % ns.process.pid)
                else:
                    os.kill(ns.process.pid, signal.SIGKILL)
                ns.process.wait()
                window.get_widget("window2").destroy()
                return ns.process.returncode
            else:
                line = ns.process.stderr.readline()
                while gtk.events_pending():
                    gtk.main_iteration_do()
                
                m = re.search('Content-Range: bytes \d+-\d+/(\d+)', line)
                if m:
                    window.get_widget("label5").set_text(_("%s bytes") % m.group(1))
                    
                m = re.search('Content-Length: (\d+)', line)
                if m:
                    window.get_widget("label5").set_text(_("%s bytes") % m.group(1))
                                
                m = re.search('(\d+[KMG]).*?(\d+)%.*?(\d+,?\d*[KMG]).*?((\d+[yhms])+)',line)
                if m:
                    window.get_widget("progressbar1").set_fraction(float(float(m.group(2))/100.0))
                    window.get_widget("label7").set_text(m.group(1))
                    window.get_widget("label9").set_text(m.group(3))
                    window.get_widget("label13").set_text(m.group(4))
        
        window.get_widget("window2").destroy()
        return ns.process.returncode
    
    #####CALLLBACKS
    def on_destroy_info(self,widget,other):
        widget.destroy()
        return
        
    def on_destroy_drive_info(self,widget,other):
        widget.destroy()
        return
    
    def on_button7_clicked(self,widget):
        self.info_window_widgets = gtk.glade.XML(self.gladefile,"window3" ,APP)
        self.info_window = self.info_window_widgets.get_widget("window3")
        gtk.glade.bindtextdomain(APP,DIR)
        dic = {
            "on_window3_delete_event" : self.on_destroy_info
        }
        self.info_window_widgets.signal_autoconnect (dic)    
        
        if self.widgets.get_widget("combobox2").get_active_iter():
            screenshot_file = os.path.join(self.presets_dir,self.widgets.get_widget("combobox1").get_active_text(),self.widgets.get_widget("combobox2").get_active_text(),"screenshot.jpg")
            if os.path.isfile(screenshot_file) == True:
                self.info_window_widgets.get_widget("image1").set_from_file(screenshot_file)
                self.info_window_widgets.get_widget("image1").show()
            else:
                self.info_window_widgets.get_widget("image1").hide()
            
            path = os.path.join(self.presets_dir,self.widgets.get_widget("combobox1").get_active_text())
            config = CustomConfig()
            config.readfp(open(os.path.join(path,self.widgets.get_widget("combobox2").get_active_text(),"info.txt")))
            self.info_window_widgets.get_widget("textview1").get_buffer().set_text(_(config.getvalue('liveusb', 'description')))
            self.info_window_widgets.get_widget("label1").set_markup('<span size="large" weight="bold">%s</span>' % self.widgets.get_widget("combobox1").get_active_text())
            self.info_window_widgets.get_widget("label5").set_text(_('%.2f MB') % (float(config.getvalue('liveusb', 'iso_size', '0'))/1024/1024))
            self.info_window_widgets.get_widget("label6").set_text(config.getvalue('liveusb', 'md5'))
            self.info_window_widgets.get_widget("label7").set_text(config.getvalue('liveusb', 'iso_location'))
            self.info_window_widgets.get_widget("window3").show()
        return
        
    def on_button8_clicked(self,widget):
        self.drive_info_window_widgets = gtk.glade.XML(self.gladefile,"window4" ,APP)
        self.drive_info_window = self.drive_info_window_widgets.get_widget("window4")
        gtk.glade.bindtextdomain(APP,DIR)
        dic = {
            "on_window4_delete_event" : self.on_destroy_drive_info
        }
        self.drive_info_window_widgets.signal_autoconnect (dic)    
        
        if self.widgets.get_widget("combobox4").get_active_iter():
            removable_drive_iter = self.widgets.get_widget("combobox4").get_active_iter()
            if platform.system() == "Windows":
                removable_drive_path = self.widgets.get_widget("combobox4").get_model().get_value(removable_drive_iter,1)
                removable_drive_device = removable_drive_path.replace("\\","")
            else:
                removable_drive_device = self.widgets.get_widget("combobox4").get_model().get_value(removable_drive_iter,1)
                            
            self.drive_info_window_widgets.get_widget("label8").set_markup('<b>'+removable_drive_device+'</b>')
            self.drive_info_window_widgets.get_widget("label9").set_markup('<b>'+self.drives[removable_drive_device]['label']+'</b>')
            self.drive_info_window_widgets.get_widget("label10").set_markup('<b>'+self.drives[removable_drive_device]['mount']+'</b>')
            self.drive_info_window_widgets.get_widget("label11").set_markup('<b>'+self.drives[removable_drive_device]['uuid']+'</b>')
            self.drive_info_window_widgets.get_widget("label12").set_markup('<b>'+(_('%.2f MB') % (self.drives[removable_drive_device]['size']/1024/1024))+'</b>')
            self.drive_info_window_widgets.get_widget("label13").set_markup('<b>'+(_('%.2f MB') % (self.drives[removable_drive_device]['free']/1024/1024))+'</b>')
            self.drive_info_window_widgets.get_widget("label14").set_markup('<b>'+self.drives[removable_drive_device]['fstype']+'</b>')
            self.drive_info_window_widgets.get_widget("label16").set_markup('<b>'+self.drives[removable_drive_device]['fsversion']+'</b>')
        return    
        
    
    def on_button9_clicked(self,widget):
        removable_drive_iter = self.widgets.get_widget("combobox4").get_active_iter()
        if removable_drive_iter:
            if platform.system() == "Windows":
                removable_drive_path = self.widgets.get_widget("combobox4").get_model().get_value(removable_drive_iter,1)
                os.system('start explorer.exe "%s"' % removable_drive_path)
            else:
                removable_drive_path = self.widgets.get_widget("combobox4").get_model().get_value(removable_drive_iter,2)
                if 'SUDO_USER' in os.environ:
                    os.system('sudo -u %s xdg-open "%s" &' % (os.environ['SUDO_USER'], removable_drive_path))
                else:
                    os.system('xdg-open %s &' % removable_drive_path)
        return

    def on_button6_clicked(self,widget):    
        dialog = gtk.MessageDialog(self.widgets.get_widget("window1"),gtk.DIALOG_MODAL,gtk.MESSAGE_WARNING,gtk.BUTTONS_YES_NO, 
            _("WARNING! This will destroy all data on the selected drive!!! Are you sure?"))
        dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS)
        response = dialog.run()
        dialog.destroy()
        if response == gtk.RESPONSE_YES:
            self.widgets.get_widget("window1").hide()
            while gtk.events_pending():
                gtk.main_iteration_do()
            removable_drive_iter = self.widgets.get_widget("combobox4").get_active_iter()
            if platform.system() == "Windows":
                import win32api, win32file
                removable_drive_path = self.widgets.get_widget("combobox4").get_model().get_value(removable_drive_iter,1)
                removable_drive_device = removable_drive_path.replace("\\","")
                removable_drive_iter = self.widgets.get_widget("window1").hide()
                #os.system('start /wait cmd /c format /q /v: '+removable_drive_device)
                os.system('start /wait fat32format.exe '+removable_drive_device)
                dialog = gtk.MessageDialog(self.widgets.get_widget("window1"),gtk.DIALOG_MODAL,gtk.MESSAGE_INFO,gtk.BUTTONS_OK, 
                    _("Formatting complete!"))
                dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS)
                response = dialog.run()
                dialog.destroy()
            else:
                removable_drive_path = self.widgets.get_widget("combobox4").get_model().get_value(removable_drive_iter,2)
                removable_drive_device = self.widgets.get_widget("combobox4").get_model().get_value(removable_drive_iter,1)
                os.system('umount %s' % removable_drive_device)
                if os.path.exists('/usr/lib/gnome-disk-utility/gdu-format-tool'):
                    os.system('/usr/lib/gnome-disk-utility/gdu-format-tool -d %s' % removable_drive_device)
                    dialog = gtk.MessageDialog(self.widgets.get_widget("window1"),gtk.DIALOG_MODAL,gtk.MESSAGE_INFO,gtk.BUTTONS_OK, 
                        _("Formatting complete!"))
                    dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS)
                    response = dialog.run()
                    dialog.destroy()
                else:
                    os.system('xterm -e mkfs.vfat -v %s' % removable_drive_device)
                    dialog = gtk.MessageDialog(self.widgets.get_widget("window1"),gtk.DIALOG_MODAL,gtk.MESSAGE_INFO,gtk.BUTTONS_OK, 
                        _("Formatting complete! Now, you should manually reinsert the removable drive."))
                    dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS)
                    response = dialog.run()
                    dialog.destroy()
            
            self.widgets.get_widget("window1").show()
            self.on_button4_clicked(widget)
        return
        

    def msg_error(self,msg, parent = None):
        if not parent:
            self.widgets.get_widget("window1")
        dialog = gtk.MessageDialog(parent,gtk.DIALOG_MODAL,gtk.MESSAGE_ERROR,gtk.BUTTONS_OK,msg)
        dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS)
        dialog.run()
        dialog.destroy()    

    def msg_info(self,msg, parent = None):
        if not parent:
            self.widgets.get_widget("window1")
        dialog = gtk.MessageDialog(parent,gtk.DIALOG_MODAL,gtk.MESSAGE_INFO,gtk.BUTTONS_OK)
        dialog.set_markup(msg)
        dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS)
        dialog.run()
        dialog.destroy()
        
    def on_button1_clicked(self,widget):
        start = time.time()
        self.widgets.get_widget("window1").hide()
        while gtk.events_pending():
            gtk.main_iteration_do()
            
        removable_drive_iter = self.widgets.get_widget("combobox4").get_active_iter()
        if not removable_drive_iter:
            self.widgets.get_widget("window1").show()    
            self.msg_error(_("No removable drive selected!"))
            return

        if platform.system() == "Windows":
            import win32api, win32file
            removable_drive_path = self.widgets.get_widget("combobox4").get_model().get_value(removable_drive_iter,1)
            removable_drive_device = removable_drive_path.replace("\\","")
        else:
            removable_drive_path = self.widgets.get_widget("combobox4").get_model().get_value(removable_drive_iter,2)
            removable_drive_device = self.widgets.get_widget("combobox4").get_model().get_value(removable_drive_iter,1)
            
        removable_drive_freespace = int(self.drives[removable_drive_device]['free'])
        #=======================================================================================    
        if self.widgets.get_widget("radiobutton7").get_active() == True:  # Install from CD/DVD
            cd_drive_iter = self.widgets.get_widget("combobox3").get_active_iter()
            if not cd_drive_iter:
                self.widgets.get_widget("window1").show()                    
                self.msg_error(_("No CD/DVD drive selected!"))
                return

            if platform.system() == "Windows":
                cd_drive_path = self.widgets.get_widget("combobox3").get_model().get_value(cd_drive_iter,1)
                cd_drive_size = (win32file.GetDiskFreeSpaceEx(cd_drive_path)[1]) # in bytes
            else:
                cd_drive_path = self.widgets.get_widget("combobox3").get_model().get_value(cd_drive_iter,2)
                cd_drive_size = 0
                if os.popen('mount | grep ' + self.widgets.get_widget("combobox3").get_model().get_value(cd_drive_iter,1) + '| cut -d\  -f1').read().strip() == '':
                    self.widgets.get_widget("window1").show()                    
                    self.msg_error(_("No CD/DVD drive mounted!"))
                    return            

            if cd_drive_size > removable_drive_freespace:
                required_space = cd_drive_size - removable_drive_freespace
                self.widgets.get_widget("window1").show()
                self.msg_error(_("There is not enough free space on the selected removable drive. You must free additional %s MB") % required_space)
                return
            else:
                if self.copy_from_cd(cd_drive_path,removable_drive_path) != 0:
                    self.widgets.get_widget("window1").show()
                    self.msg_error(_("Installation aborted!"))
                    return

        #=======================================================================================    
        elif self.widgets.get_widget("radiobutton8").get_active() == True:  # Install from ISO
            #sys.exit(0)
            if not self.widgets.get_widget("filechooserbutton2").get_filename():
                self.widgets.get_widget("window1").show()
                self.msg_error(_("Please select ISO file!"))
                return

            if self.widgets.get_widget("combobox6").get_active() == 2:
                if self.copy_file(self.widgets.get_widget("filechooserbutton2").get_filename(),removable_drive_path) != 0:
                    self.widgets.get_widget("window1").show()
                    self.msg_error(_("Installation aborted!"))
                    return
            else:
                if self.extract_iso(self.widgets.get_widget("filechooserbutton2").get_filename(),removable_drive_path) != 0:
                    self.widgets.get_widget("window1").show()
                    self.msg_error(_("Installation aborted!"))
                    return
        
        #=======================================================================================    
        elif self.widgets.get_widget("radiobutton9").get_active() == True:  # Install from Internet
            path = os.path.join(self.presets_dir,self.widgets.get_widget("combobox1").get_active_text())
            config = CustomConfig()
            config.readfp(open(os.path.join(path, self.widgets.get_widget("combobox2").get_active_text(),"info.txt")))
            iso_location = config.getvalue('liveusb', 'iso_location')
            iso_size = config.getvalue('liveusb', 'iso_size', '0')
            archive = config.getvalue('liveusb', 'archive')
            iso_extract = config.getvalue('liveusb', 'iso_extract')
            in_torrent = config.getvalue('liveusb', 'in_torrent')
            http_referrer = config.getvalue('liveusb', 'http_referrer')
            if int(iso_size) > removable_drive_freespace:
                required_space = int(iso_size) - removable_drive_freespace
                self.msg_error(_("There is not enough free space on the selected removable drive. You must free additional %s MB") % required_space)
                self.widgets.get_widget("window1").show()
                return
            if not os.path.exists(os.path.join(tempfile.gettempdir(),'live-usb-install')):
                os.mkdir(os.path.join(tempfile.gettempdir(),'live-usb-install'))
            
            if in_torrent and LIBTORRENT_AVAILABLE:
                download_result = self.download_torrent(iso_location, os.path.join(tempfile.gettempdir(),'live-usb-install'), http_referrer)
                if download_result != 0:
                    self.msg_error(_("Torrent invalid or canceled! Installation aborted."))
                    self.widgets.get_widget("window1").show()
                    return            
            if archive:
                if in_torrent:
                    extract_result = self.uncompress_iso(
                        os.path.join(tempfile.gettempdir(),'live-usb-install',in_torrent)
                        , iso_extract
                        , os.path.join(tempfile.gettempdir(),'live-usb-install')
                        , archive)

                    if extract_result != 0:
                        self.widgets.get_widget("window1").show()
                        self.msg_error(_("There was an error while extracting the iso file from the downloaded archive"))
                        return
                    
                    isoName = os.path.basename(iso_extract)
                    isoName_full = os.path.join(tempfile.gettempdir(),'live-usb-install', isoName)
                    
                    if self.extract_iso(isoName_full,removable_drive_path) != 0:
                        self.widgets.get_widget("window1").show()
                        self.msg_error(_("Installation aborted!"))
                        return
                else:
                    isoName = self.widgets.get_widget("combobox1").get_active_text() + ' - ' + self.widgets.get_widget("combobox2").get_active_text() + '.' + archive
                    isoName_full = os.path.join(tempfile.gettempdir(),'live-usb-install',isoName)
                    download_result = self.download_file(iso_location,isoName_full, http_referrer)

                    if download_result != 0:
                        self.widgets.get_widget("window1").show()
                        self.msg_error(_("Installation aborted!"))
                        return
                
                    extract_result = self.uncompress_iso(isoName_full, iso_extract, os.path.join(tempfile.gettempdir(),'live-usb-install'), archive)

                    if extract_result != 0:
                        self.widgets.get_widget("window1").show()
                        self.msg_error(_("There was an error while extracting the iso file from the downloaded archive"))
                        return
                    

                    isoName = os.path.basename(iso_extract)
                    isoName_full = os.path.join(tempfile.gettempdir(),'live-usb-install', isoName)
        
                    if self.extract_iso(isoName_full,removable_drive_path) != 0:
                        self.widgets.get_widget("window1").show()
                        self.msg_error(_("Installation aborted!"))
                        return
            else:
            
                if in_torrent:
                    isoName_full = os.path.join(tempfile.gettempdir(),'live-usb-install', in_torrent)
                else:
                    isoName = self.widgets.get_widget("combobox1").get_active_text() + ' - ' + self.widgets.get_widget("combobox2").get_active_text() + '.iso'
                    while gtk.events_pending():
                        gtk.main_iteration_do()

                    isoName_full = os.path.join(tempfile.gettempdir(),'live-usb-install', isoName)
                    download_result = self.download_file(iso_location,isoName_full, http_referrer)

                    if download_result != 0:
                        self.widgets.get_widget("window1").show()
                        self.msg_error(_("Installation aborted!"))
                        return
                
                if self.extract_iso(isoName_full,removable_drive_path) != 0:
                    self.widgets.get_widget("window1").show()
                    self.msg_error(_("Installation aborted!"))
                    return        
        #=======================================================================================    
        elif self.widgets.get_widget("radiobutton3").get_active() == True:  # Install from IMG file
            img_filename = self.widgets.get_widget("filechooserbutton4").get_filename()
            if not img_filename:
                self.widgets.get_widget("window1").show()
                self.msg_error(_("Please select image file!"))
                return
            
            if platform.system() == "Windows":
                img_write_result =  self.write_img(img_filename, removable_drive_device)
                
                if img_write_result != 0:
                    self.widgets.get_widget("window1").show()
                    self.msg_error(_("Error while transferring image file to %s. Installation aborted!") % removable_drive_device)
                    return
            else:
                parent_dev = self.get_parent_device(removable_drive_device)
                os.system('sync')
                
                if os.system('umount %s' % removable_drive_device)!=0:
                    self.widgets.get_widget("window1").show()
                    self.msg_error(_("The removable drive can not be unmounted. Installation aborted!"))
                    return
                
                img_write_result =  self.write_img(img_filename, parent_dev)
                
                            
                if img_write_result != 0:
                    self.widgets.get_widget("window1").show()
                    self.msg_error(_("Error while transferring image file to %s. Installation aborted!") % parent_dev)
                    return

            self.widgets.get_widget("window1").show()       
            self.msg_info(_("Installation is complete!\nTime taken: %f seconds") % round(time.time() - start))
            StatsThread('MODE:IMG', os.path.basename(img_filename)).start() 
            return # skip the rest!!
        #=======================================================================================    
            
        
        if platform.system() == "Windows":
            shutil.copy2('vesamenu.c32',removable_drive_path)
        else:
            if os.path.isfile('/usr/lib/syslinux/vesamenu.c32'):
                shutil.copy2('/usr/lib/syslinux/vesamenu.c32',removable_drive_path)
            else:
                shutil.copy2('vesamenu.c32',removable_drive_path)
                
        if platform.system() == "Windows":
            os.system('del ' + removable_drive_path+'\\boot\\syslinux\\syslinux.cfg')
            os.system('del ' + removable_drive_path+'\\syslinux\\syslinux.cfg')
            os.system('del ' + removable_drive_path+'\\syslinux.cfg')
        else:
            os.system('rm "' + removable_drive_path+'/boot/syslinux/syslinux.cfg"')
            os.system('rm "' + removable_drive_path+'/syslinux/syslinux.cfg"')
            os.system('rm "' + removable_drive_path+'/syslinux.cfg"')            
            
        if self.widgets.get_widget("combobox6").get_active() == 1:
            syslinux_cfg_f = open("./syslinux-custom.cfg")
            syslinux_cfg = syslinux_cfg_f.read()
            syslinux_cfg_f.close()
            
            # syslinux_cfg = replace(syslinux_cfg,"%MENU_TITLE%",self.widgets.get_widget("entry1").get_text())
            syslinux_cfg = syslinux_cfg.replace("%MENU_LABEL%",self.widgets.get_widget("entry1").get_text())
            syslinux_cfg = syslinux_cfg.replace("%KERNEL%",self.widgets.get_widget("entry2").get_text())
            syslinux_cfg = syslinux_cfg.replace("%APPEND%",self.widgets.get_widget("entry4").get_text())
            
            if self.widgets.get_widget("filechooserbutton1").get_filename():
                shutil.copy2(self.widgets.get_widget("filechooserbutton1").get_filename(),removable_drive_path+'backg.png')
                syslinux_cfg = syslinux_cfg.replace('%MENUBG%','MENU BACKGROUND backg.png')
            else:
                syslinux_cfg = syslinux_cfg.replace('%MENUBG%','')
            
            syslinux_f = open(removable_drive_path+'/syslinux.cfg', 'w+')
            syslinux_f.write(syslinux_cfg)
            syslinux_f.close()
            
        elif self.widgets.get_widget("combobox6").get_active() == 2:
            syslinux_cfg_f = open("./syslinux-wingrub.cfg")
            syslinux_cfg = syslinux_cfg_f.read()
            syslinux_cfg_f.close()
            
            syslinux_cfg = syslinux_cfg.replace("%MENU_LABEL%",self.widgets.get_widget("entry5").get_text())
            print syslinux_cfg

            syslinux_f = open(removable_drive_path+'/syslinux.cfg', 'w+')
            syslinux_f.write(syslinux_cfg)
            syslinux_f.close()
                        
            menu_lst_f = open("./menu.lst")
            menu_lst = menu_lst_f.read()
            menu_lst_f.close()
            menu_lst = menu_lst.replace("%MENU_LABEL%",self.widgets.get_widget("entry5").get_text())
            menu_lst = menu_lst.replace("%ISO%",os.path.basename(self.widgets.get_widget("filechooserbutton2").get_filename()).replace(' ','\ '))

            if self.widgets.get_widget("radiobutton1").get_active():
                menu_lst = menu_lst.replace("%BOOT%","chainloader (hd32)")
            else:
                menu_lst = menu_lst.replace("%BOOT%","kernel "+self.widgets.get_widget("entry6").get_text()+"\n"+"initrd "+self.widgets.get_widget("entry7").get_text())
            print menu_lst
            
            multi = False
            if os.path.isfile(removable_drive_path+'/menu.lst'):
                menu_lst1_f = open(removable_drive_path+'/menu.lst')
                menu_lst1 = menu_lst1_f.read()
                menu_lst1_f.close()                
                if re.search('^#live-usb-install wingrub iso boot', menu_lst1):
                    multi = True
            
            if multi:
                menu_lst_f = open(removable_drive_path+'/menu.lst', 'w+')
                menu_lst_f.write(menu_lst1 + '\n' + menu_lst)    
                menu_lst_f.close()                
            else:
                menu_lst_f = open(removable_drive_path+'/menu.lst', 'w+')
                menu_lst_f.write(menu_lst)        
                menu_lst_f.close()
                
            shutil.copy2("./backg.png",removable_drive_path)            
            shutil.copy2("./grub.exe",removable_drive_path)
            
        else:
            
            shutil.copy2(os.path.join(self.presets_dir,self.widgets.get_widget("combobox1").get_active_text(), self.widgets.get_widget("combobox2").get_active_text(),"syslinux.cfg"),removable_drive_path)

            path = os.path.join(self.presets_dir,self.widgets.get_widget("combobox1").get_active_text())
            config = CustomConfig()
            config.readfp(open(os.path.join(path, self.widgets.get_widget("combobox2").get_active_text(), "info.txt")))
            

            if config.getvalue('liveusb', 'set_uuid').lower() == 'true':
                syslinux_cfg_f = open(os.path.join(removable_drive_path,"syslinux.cfg"))
                syslinux_cfg = syslinux_cfg_f.read()
                syslinux_cfg_f.close()            
                syslinux_cfg = syslinux_cfg.replace("%UUID%",self.drives[removable_drive_device]['uuid'])
                syslinux_cfg_f = open(os.path.join(removable_drive_path, "syslinux.cfg"), 'w+')
                syslinux_cfg_f.write(syslinux_cfg)        
                syslinux_cfg_f.close()

            if config.getvalue('liveusb', 'kiwi_mbrid').lower() == 'true':
                mbrid = self.get_mbrid(removable_drive_device)
                if mbrid == False:
                    self.widgets.get_widget("window1").show()
                    self.msg_error(_("Error while reading Master Boot Record ID! Installation aborted."))
                    return
                if not os.path.exists(os.path.join(removable_drive_path,"boot","grub")):
                    os.makedirs(os.path.join(removable_drive_path,"boot","grub"))
                mbrid_f = open(os.path.join(removable_drive_path,"boot","grub","mbrid"),'w+')
                mbrid_f.write(mbrid)    
                mbrid_f.close()    
            
            
            # set correct locale
            
            if os.path.isfile(os.path.join(removable_drive_path,"menu.lst")):
                cfg_filename = os.path.join(removable_drive_path,"menu.lst")
                cfg_f = open(cfg_filename)
                cfg_txt = cfg_f.read()
                cfg_f.close()
            
                cfg_txt = re.sub(r'(kernel.*?locale=)([a-zA-Z_]+)(.*)', '\\1'+locale.getdefaultlocale()[0]+'\\3', cfg_txt)
                cfg_txt = re.sub(r'(kernel.*?lang=)([a-zA-Z_]+)(.*)', '\\1'+locale.getdefaultlocale()[0].split('_')[0]+'\\3', cfg_txt)

                cfg_f = open(cfg_filename, 'w+')
                cfg_f.write(cfg_txt)    
                cfg_f.close()
            
            if os.path.isfile(os.path.join(removable_drive_path,"syslinux.cfg")):
                cfg_filename = os.path.join(removable_drive_path,"syslinux.cfg")
                cfg_f = open(cfg_filename)
                cfg_txt = cfg_f.read()
                cfg_f.close()
            
                cfg_txt = re.sub(r'(append.*?locale=)([a-zA-Z_]+)(.*)', '\\1'+locale.getdefaultlocale()[0]+'\\3', cfg_txt)
                cfg_txt = re.sub(r'(append.*?lang=)([a-zA-Z_]+)(.*)', '\\1'+locale.getdefaultlocale()[0].split('_')[0]+'\\3', cfg_txt)

                cfg_f = open(cfg_filename, 'w+')
                cfg_f.write(cfg_txt)    
                cfg_f.close()

            
            
            if self.widgets.get_widget("checkbutton1").get_active() == True:
                if config.getvalue('liveusb', 'ubuntu_persistent').lower() == 'true':
                    persistent_file = '%s/casper-rw' % removable_drive_path
                    persistent_label = 'casper-rw'
                elif config.getvalue('liveusb', 'debian_persistent').lower() == 'true':
                    # Debian > 6
                    persistent_file = '%s/live-rw' % removable_drive_path
                    persistent_label = 'live-rw'
                '''
                elif config.getvalue('liveusb', 'sidux_persistent').lower() == 'true':
                    persistent_file = '%s/sidux/sidux-rw' % removable_drive_path
                    persistent_label = 'sidux-rw'
                elif config.getvalue('liveusb', 'aptosid_persistent').lower() == 'true':
                    persistent_file = '%s/aptosid/aptosid-rw' % removable_drive_path
                    persistent_label = 'aptosid-rw'
                #Puppy
                elif config.getvalue('liveusb', 'puppy_persistent').lower() == 'true':
                    persistent_file = '%s/lupusave.2fs' % removable_drive_path
                    persistent_label = 'lupusave'
                '''
                #TODO:
                '''
                #Fedora
                elif config.getvalue('liveusb', 'fedora_persistent').lower() == 'true':
                    persistent_file = ('%s/LiveOS/overlay-'+LABEL.replace(' ','_')+'-'+UUID) % removable_drive_path
                    persistent_label = '' # TODO: correct label?
                    
                    
                '''
                
                #syslinux_cfg_f = open(os.path.join(removable_drive_path,"syslinux.cfg"))
                
                syslinux_cfg_filename = os.path.join(removable_drive_path, "syslinux.cfg")
                syslinux_cfg = open(syslinux_cfg_filename).read().replace("#PERSISTENCE:","")
                syslinux_cfg_f = open(syslinux_cfg_filename, 'w+')
                syslinux_cfg_f.write(syslinux_cfg)    
                syslinux_cfg_f.close()
                
                persistent_size = int(self.widgets.get_widget("combobox5").get_active_text())
                
                dd_result = self.write_img(
                    '/dev/zero'
                    , persistent_file
                    , _("Creating %(file)s %(size)s MB") % {'file': persistent_file, 'size': persistent_size}
                    , '16M'
                    , int(persistent_size / 16)
                )
                
                if dd_result != 0:
                    self.widgets.get_widget("window1").show()        
                    self.msg_error(_('The persistent storage was not created. Installation aborted!'))
                    return
                mkfs_result = self.mkfs(persistent_file, persistent_label)
                if mkfs_result != 0:
                    self.widgets.get_widget("window1").show()        
                    self.msg_error(_('The persistent storage was not formated. Installation aborted!'))
                    return                    
            
            backg_file = os.path.join(self.presets_dir, self.widgets.get_widget("combobox1").get_active_text(), "backg.png")
            if os.path.isfile(backg_file):
                shutil.copy2(backg_file,removable_drive_path)
            else:
                shutil.copy2(os.path.join(self.glade_dir, "backg.png"),removable_drive_path)
                
            support_files = os.path.join(self.presets_dir, self.widgets.get_widget("combobox1").get_active_text(), self.widgets.get_widget("combobox2").get_active_text(), "other.7z")
            if os.path.exists(support_files):
                self.uncompress(support_files,removable_drive_path)
            
            helper_file_path = os.path.join(self.presets_dir, self.widgets.get_widget("combobox1").get_active_text(), self.widgets.get_widget("combobox2").get_active_text(), "helper.py")
            if os.path.exists(helper_file_path):
                helper_file = open(helper_file_path)
                helper_file_contents = helper_file.read()
                helper_file.close()
                exec helper_file_contents
            
        if platform.system() == "Windows":
            os.system("del /F /Q " + os.path.join(removable_drive_path,'ldlinux.sys'))
            if os.system("syslinux -maf " + removable_drive_device) != 0:
                self.widgets.get_widget("window1").show()
                self.msg_error(_("Error while installing syslinux bootloader! Installation aborted."))
                return
            #TODO: mark partition active
        else:
            os.system("rm -f " + os.path.join(removable_drive_path, 'ldlinux.sys'))
            os.system("sync")
            if os.system("umount " + removable_drive_device) != 0:
                self.widgets.get_widget("window1").show()
                self.msg_error(_("The target drive can not be unmounted, and the syslinux bootloader will not be installed! Installation aborted."))
                return

            parent_dev = self.get_parent_device(removable_drive_device)

            m = re.search('(\d+)$', removable_drive_device)
            if m:
                partition_number = m.group(1)
                if os.system("parted %s set %s boot on" % (parent_dev, partition_number)) != 0:
                    self.widgets.get_widget("window1").show()
                    self.msg_error(_("Cant mark partition %s as active! Installation aborted.") % removable_drive_device)
                    return

            if os.system("syslinux -f " + removable_drive_device) != 0:
                if os.system("syslinux -sf " + removable_drive_device) != 0:
                    self.widgets.get_widget("window1").show()
                    self.msg_error(_("Error while installing syslinux bootloader! Installation aborted."))
                    return
            
            #cat /usr/lib/syslinux/mbr.bin > /dev/sdc
            #mark partition bootable: parted /dev/sdc set 1 boot on
            
            if os.system("dd if=%s of=%s" % (os.path.join(self.glade_dir,'syslinux.mbr'), parent_dev)) != 0:
                self.widgets.get_widget("window1").show()
                self.msg_error(_("Error while writing master boot record! Installation aborted."))
                return            
        
        self.widgets.get_widget("window1").show()
        if self.widgets.get_widget("radiobutton9").get_active() == True:
            dialog = gtk.MessageDialog(self.widgets.get_widget("window1"),gtk.DIALOG_MODAL,gtk.MESSAGE_QUESTION,gtk.BUTTONS_YES_NO, _("Installation is complete!\nTime taken: %s\nDo you want to delete the downloaded temporaty files?") % time.strftime('%M min %S sec', time.gmtime(time.time() - start)))
            dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS)
            response = dialog.run()
            dialog.destroy()
            if response == gtk.RESPONSE_YES:
                try:
                    tmp_path = os.path.join(tempfile.gettempdir(),'live-usb-install')
                    if os.path.isdir(tmp_path):
                        shutil.rmtree(tmp_path)
                except:
                    pass        
        else:
            dialog = gtk.MessageDialog(self.widgets.get_widget("window1"),gtk.DIALOG_MODAL,gtk.MESSAGE_INFO,gtk.BUTTONS_OK,_("Installation is complete!\nTime taken: %s") % time.strftime('%M min %S sec', time.gmtime(time.time() - start)))
            dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS)
            dialog.run()
            dialog.destroy()

        if self.widgets.get_widget("combobox6").get_active() == 0:
            StatsThread(self.widgets.get_widget("combobox1").get_active_text(), self.widgets.get_widget("combobox2").get_active_text()).start()

        
        return
        
    def on_button2_clicked(self,widget):
        about = gtk.AboutDialog()
        about.set_position(gtk.WIN_POS_CENTER_ALWAYS)
        about.set_program_name("LiveUSB Install")
        about.set_version(APP_VERSION)
        about.set_authors([_("Krasimir S. Stefanov <lokiisyourmaster@gmail.com>")])
        about.set_website("http://live.learnfree.eu/")
        about.set_translator_credits(_("Bulgarian - Krasimir S. Stefanov <lokiisyourmaster@gmail.com>"))
        about.set_logo(gtk.gdk.pixbuf_new_from_file(os.path.join(self.glade_dir,'logo.png')))
        license = _('''live-usb-install: install linux on a removable drive
Copyright (C) 2010  Krasimir S. Stefanov

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, either version 3 of the License, or
(at your option) any later version.

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/>.''')
        
        about.set_license(license)
        about.run()
        about.hide()
        return
  
    def on_button3_clicked(self, widget, args = None):
        if self.md5sum_thread:
            self.md5sum_thread.canceled = True
        gtk.main_quit()
        return
        
    def on_button4_clicked(self,widget):
        removable_drive_iter = self.widgets.get_widget("combobox4").get_active_iter()
        if removable_drive_iter:
            if platform.system() == "Windows":
                removable_drive_path = self.widgets.get_widget("combobox4").get_model().get_value(removable_drive_iter,1)
                removable_drive_device = removable_drive_path.replace("\\","")
            else:
                removable_drive_device = self.widgets.get_widget("combobox4").get_model().get_value(removable_drive_iter,1)
        else:
            removable_drive_device = ''
            
        #self.msg_error(removable_drive_device)            
        self.widgets.get_widget("combobox4").get_model().clear()
        removable_drives = self.list_removable_drives()

        if len(self.drives) > 0:
            for drive in self.drives:
                list_iter = self.widgets.get_widget("combobox4").get_model().append()
                icon = self.widgets.get_widget("combobox4").render_icon(gtk.STOCK_HARDDISK, gtk.ICON_SIZE_MENU)
                if self.drives[drive]['size'] == None:
                    self.drives[drive]['size'] = 0
                if self.drives[drive]['free'] == None:
                    self.drives[drive]['free'] = 0
                if platform.system() == "Windows":
                    self.widgets.get_widget("combobox4").get_model().set(
                        list_iter
                        , 0, icon
                        , 1, self.drives[drive]['device']
                        , 2, self.drives[drive]['label']
                        , 3, ''
                        , 4, int(float(self.drives[drive]['size'] - self.drives[drive]['free']) / float(self.drives[drive]['size']) * 100.0)
                        , 5, _('%(used).2f / %(size).2f GB (%(fstype)s)') % {
                            'used': float(self.drives[drive]['size'] - self.drives[drive]['free'])/1024.0**3,
                            'size': float(self.drives[drive]['size'])/1024.0**3,
                            'fstype': self.drives[drive]['fsversion'] or self.drives[drive]['fstype']
                        }
                    )
                else:
                    self.widgets.get_widget("combobox4").get_model().set(
                        list_iter
                        , 0, icon
                        , 1, self.drives[drive]['device']
                        , 2, self.drives[drive]['mount']
                        , 3, ''
                        , 4, int(float(self.drives[drive]['size'] - self.drives[drive]['free']) / float(self.drives[drive]['size']) * 100.0)
                        , 5, _('%(used).2f / %(size).2f GB (%(fstype)s)') % {
                            'used': float(self.drives[drive]['size'] - self.drives[drive]['free'])/1024.0**3, 
                            'size': float(self.drives[drive]['size'])/1024.0**3, 
                            'fstype': self.drives[drive]['fsversion'] or self.drives[drive]['fstype']
                        }
                    )
            self.widgets.get_widget("combobox4").set_sensitive(True)
            self.widgets.get_widget("button6").set_sensitive(True)
            self.widgets.get_widget("button8").set_sensitive(True)
            self.widgets.get_widget("button9").set_sensitive(True)
            self.combobox_select(self.widgets.get_widget("combobox4"), removable_drive_device, 1)
        else:
            self.widgets.get_widget("combobox4").set_sensitive(False)
            self.widgets.get_widget("button6").set_sensitive(False)
            self.widgets.get_widget("button8").set_sensitive(False)    
            self.widgets.get_widget("button9").set_sensitive(False)
        #self.widgets.get_widget("combobox4").set_active(0)
        return

    def on_button5_clicked(self,widget):
        self.widgets.get_widget("combobox3").get_model().clear()
        #list cd drives
        self.cd_drives = self.list_cd_drives()
        if len(self.cd_drives) > 0:
            for drive in self.cd_drives:
                list_iter = self.widgets.get_widget("combobox3").get_model().append()
                icon = self.widgets.get_widget("combobox3").render_icon(gtk.STOCK_CDROM, gtk.ICON_SIZE_MENU)
                self.widgets.get_widget("combobox3").get_model().set(list_iter,0, icon, 1,drive[0],2,drive[1])
            self.widgets.get_widget("combobox3").set_active(0)
            self.widgets.get_widget("radiobutton7").set_sensitive(True)
            
        else:
            self.widgets.get_widget("radiobutton7").set_sensitive(False)
            self.widgets.get_widget("radiobutton8").set_active(True)

        return  

            
    def on_combobox6_changed(self,widget):
        active = self.widgets.get_widget("combobox6").get_active()
        
        if active == 0: # cd, iso, internet
            self.widgets.get_widget("frame1").show()
            self.widgets.get_widget("frame5").hide()
            self.widgets.get_widget("frame6").hide()
            
            self.widgets.get_widget("image6").show() # cd
            self.widgets.get_widget("radiobutton7").show() # cd
            self.widgets.get_widget("hbox4").show() # cd
            
            self.widgets.get_widget("image7").show() # iso
            self.widgets.get_widget("radiobutton8").show() # iso
            self.widgets.get_widget("vbox4").show() # iso
            self.widgets.get_widget("checkbutton2").show() # md5check
            
            
            self.widgets.get_widget("image8").show() # internet
            self.widgets.get_widget("hbox5").show() # internet

            self.widgets.get_widget("image1").hide() # img
            self.widgets.get_widget("radiobutton3").hide() # img
            self.widgets.get_widget("filechooserbutton4").hide() # img
            self.widgets.get_widget("hbox2").show()
        elif active == 1: # cd, iso
            self.widgets.get_widget("frame1").hide()
            self.widgets.get_widget("frame5").show()
            self.widgets.get_widget("frame6").hide()
            if self.widgets.get_widget("radiobutton3").get_active() or self.widgets.get_widget("radiobutton9").get_active():
                self.widgets.get_widget("radiobutton8").set_active(True)
            self.widgets.get_widget("checkbutton1").set_active(False)    
            
            self.widgets.get_widget("image6").show() # cd
            self.widgets.get_widget("radiobutton7").show() # cd
            self.widgets.get_widget("hbox4").show() # cd
            
            self.widgets.get_widget("image7").show() # iso
            self.widgets.get_widget("radiobutton8").show() # iso
            self.widgets.get_widget("vbox4").show() # iso
            self.widgets.get_widget("checkbutton2").hide() # md5check
            self.widgets.get_widget("checkbutton2").set_active(False) # md5check
            
            self.widgets.get_widget("image8").hide() # internet
            self.widgets.get_widget("hbox5").hide() # internet

            self.widgets.get_widget("image1").hide() # img
            self.widgets.get_widget("radiobutton3").hide() # img
            self.widgets.get_widget("filechooserbutton4").hide() # img
            self.widgets.get_widget("hbox2").hide()
        elif active == 2: #  iso
            self.widgets.get_widget("frame1").hide()
            self.widgets.get_widget("frame5").hide()
            self.widgets.get_widget("frame6").show()
            if self.widgets.get_widget("radiobutton3").get_active() or self.widgets.get_widget("radiobutton9").get_active():
                self.widgets.get_widget("radiobutton8").set_active(True)
                            
            self.widgets.get_widget("image6").hide() # cd
            self.widgets.get_widget("radiobutton7").hide() # cd
            self.widgets.get_widget("hbox4").hide() # cd
            
            self.widgets.get_widget("image7").show() # iso
            self.widgets.get_widget("radiobutton8").show() # iso
            self.widgets.get_widget("vbox4").show() # iso
            self.widgets.get_widget("checkbutton2").hide() # md5check
            self.widgets.get_widget("checkbutton2").set_active(False) # md5check
            
            self.widgets.get_widget("image8").hide() # internet
            self.widgets.get_widget("hbox5").hide() # internet

            self.widgets.get_widget("image1").hide() # img
            self.widgets.get_widget("radiobutton3").hide() # img
            self.widgets.get_widget("filechooserbutton4").hide() # img
            self.widgets.get_widget("hbox2").hide()
            
            dialog = gtk.MessageDialog(self.widgets.get_widget("window1"),gtk.DIALOG_MODAL,gtk.MESSAGE_INFO,gtk.BUTTONS_OK,_("Please note: your removable drive must be empty or defragmented, otherwise it may not boot properly the ISO file!"))
            dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS)
            dialog.run()
            dialog.destroy()        
        elif active == 3: # img
            self.widgets.get_widget("frame1").hide()
            self.widgets.get_widget("frame5").hide()
            self.widgets.get_widget("frame6").hide()
            self.widgets.get_widget("radiobutton3").set_active(True)
            self.widgets.get_widget("checkbutton1").set_active(False)
            
            self.widgets.get_widget("image6").hide() # cd
            self.widgets.get_widget("radiobutton7").hide() # cd
            self.widgets.get_widget("hbox4").hide() # cd    
            
            self.widgets.get_widget("image7").hide() # iso
            self.widgets.get_widget("radiobutton8").hide() # iso
            self.widgets.get_widget("vbox4").hide() # iso
            self.widgets.get_widget("checkbutton2").hide() # md5check
            self.widgets.get_widget("checkbutton2").set_active(False) # md5check
            
            self.widgets.get_widget("image8").hide() # internet
            self.widgets.get_widget("hbox5").hide() # internet

            self.widgets.get_widget("image1").show() # img
            self.widgets.get_widget("radiobutton3").show() # img
            self.widgets.get_widget("filechooserbutton4").show() # img
            self.widgets.get_widget("hbox2").hide()
            
            dialog = gtk.MessageDialog(self.widgets.get_widget("window1"),gtk.DIALOG_MODAL,gtk.MESSAGE_WARNING,gtk.BUTTONS_OK,_("WARNING! This will erase ALL data in all partitions on the selected removable drive! Be very, very carefull!"))
            dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS)
            dialog.run()
            dialog.destroy()

        self.on_combobox2_changed(self.widgets.get_widget("combobox2"))        
        return
        
    def on_combobox1_changed(self,widget):
        self.list_distribution_versions()
        self.widgets.get_widget("combobox2").set_active(0)
        return

    def on_combobox2_changed(self,widget):
        if self.widgets.get_widget("combobox2").get_active_iter():
            path = os.path.join(self.presets_dir, self.widgets.get_widget("combobox1").get_active_text())
            config = CustomConfig()
            config.readfp(open(os.path.join(path, self.widgets.get_widget("combobox2").get_active_text(), "info.txt")))
            # self.widgets.get_widget("textview1").get_buffer().set_text(_(config.getvalue('liveusb', 'description')))
            
            if config.getvalue('liveusb', 'ubuntu_persistent') or config.getvalue('liveusb', 'debian_persistent'):
                self.widgets.get_widget("combobox5").set_active(0)
                self.widgets.get_widget("hbox2").set_sensitive(True)
            else:
                self.widgets.get_widget("hbox2").set_sensitive(False)
                self.widgets.get_widget("checkbutton1").set_active(False)
            
            if not config.getvalue('liveusb', 'iso_location'):
                self.widgets.get_widget("image8").set_sensitive(False)            
                self.widgets.get_widget("radiobutton9").set_sensitive(False)
                self.widgets.get_widget("label17").set_sensitive(False)
                self.widgets.get_widget("label17").set_text(_('Download unavailable!'))
            else:
                if config.getvalue('liveusb', 'in_torrent') and LIBTORRENT_AVAILABLE == False:
                    self.widgets.get_widget("image8").set_sensitive(False)            
                    self.widgets.get_widget("radiobutton9").set_sensitive(False)
                    self.widgets.get_widget("label17").set_sensitive(False)
                    self.widgets.get_widget("label17").set_text(_('Please install libtorrent!'))
                else:
                    self.widgets.get_widget("image8").set_sensitive(True)
                    self.widgets.get_widget("radiobutton9").set_sensitive(True)
                    self.widgets.get_widget("label17").set_sensitive(True)
                    self.widgets.get_widget("label17").set_text(_("(Download size: %.2f MB)") % (float(config.getvalue('liveusb', 'iso_size', '0.0'))/1024/1024))
            
            if config.getvalue('liveusb', 'dd_only') and self.widgets.get_widget("combobox6").get_active() == 0:
                self.msg_info(_("The selected distribution can only be installed in \"IMG Write\" mode! Please select it from the combobox above, and from the \"IMG File\" select your ISO file."))
        return
            
    def on_radiobutton1_toggled(self,widget):    
        if widget.get_active() == True:
            self.widgets.get_widget("label22").hide()
            self.widgets.get_widget("entry6").hide()
            self.widgets.get_widget("label15").hide()
            self.widgets.get_widget("entry7").hide()
        return
        
    def on_radiobutton2_toggled(self,widget):    
        if widget.get_active() == True:
            self.widgets.get_widget("label22").show()
            self.widgets.get_widget("entry6").show()
            self.widgets.get_widget("label15").show()
            self.widgets.get_widget("entry7").show()
        return
                
    def on_checkbutton1_toggled(self,widget):
        if widget.get_active() == True:
            self.widgets.get_widget("combobox5").show()
            self.widgets.get_widget("label3").show()
        else:
            self.widgets.get_widget("combobox5").hide()
            self.widgets.get_widget("label3").hide()

    def on_checkbutton2_toggled(self,widget):
        if self.widgets.get_widget("checkbutton2").get_active() == True:
            self.detect_distribution()

    def on_button11_clicked(self ,widget):
        ns = Namespace()
        
        def cancel(widget, other = None):
            ns.window.get_widget("window6").destroy()

        def send(widget, other = None):
            startiter = ns.window.get_widget("textview1").get_buffer().get_start_iter()
            enditer = ns.window.get_widget("textview1").get_buffer().get_end_iter()
            description = ns.window.get_widget("textview1").get_buffer().get_text(startiter, enditer, True)
            params = urllib.urlencode({
                'name': ns.window.get_widget("entry3").get_text()
                , 'version': ns.window.get_widget("entry4").get_text()
                , 'arch': ns.window.get_widget("entry5").get_text()
                , 'description': description
                , 'url': ns.window.get_widget("entry6").get_text()
                , 'size': ns.window.get_widget("entry7").get_text()
                , 'md5': ns.window.get_widget("entry8").get_text()

            })
            f = urllib.urlopen("http://live.learnfree.eu/suggest-distribution.php?%s" % params)
            try:
                result = f.read()
                print 'RESPONSE:',result
                if result == 'OK':
                    ns.window.get_widget("window6").destroy()
                    self.msg_info(_("Your suggestion has been sent! Thank you for your support!"), ns.window.get_widget("window6"))
                elif result == 'REQ':
                    self.msg_error(_("Please fill in all the required fields."), ns.window.get_widget("window6"))
                else:
                    self.msg_error(_("There was an error while sending the data! Please try again."), ns.window.get_widget("window6"))
            except:
                self.msg_error(_("There was an error while sending the data! Make sure you have active Internet connection."), ns.window.get_widget("window6"))
                
        ns.window = gtk.glade.XML(self.gladefile,"window6" ,APP)
        gtk.glade.bindtextdomain(APP,DIR)
        dic = {
            "on_button1_clicked" : (cancel),
            "on_button2_clicked" : (send),
            "on_window6_delete_event" : (cancel)
        }
        ns.window.signal_autoconnect (dic)

        #window.get_widget('label3').set_text(remote)
        ns.window.get_widget("window6").show()
                
    def on_button10_clicked(self ,widget):
        if self.md5sum_thread:
            self.md5sum_thread.canceled = True
    
    def md5sum_cancel(self):
        self.widgets.get_widget("frame1").set_sensitive(True)
        self.widgets.get_widget("button1").set_sensitive(True)
        self.widgets.get_widget("combobox6").set_sensitive(True)
        self.widgets.get_widget("hbox6").hide()
        self.widgets.get_widget("filechooserbutton2").show()
        self.md5sum_thread = None
        
    def md5sum_done(self, value):
        #print value
        #self.msg_error(value)
        distributions = os.listdir(self.presets_dir)
        detected = False
        if distributions:
            for distribution in distributions:
                versions = os.listdir(os.path.join(self.presets_dir, distribution))
                if versions:
                    for version in versions:
                        if os.path.isdir(os.path.join(self.presets_dir,distribution, version)):
                            config = CustomConfig()
                            distro_info = os.path.join(self.presets_dir,distribution, version,"info.txt")
                            config.readfp(open(distro_info))
                            if config.getvalue('liveusb', 'md5') == value:
                                self.msg_info(_("Detected supported distribution: <b>%(distribution)s (%(version)s)</b>") % {
                                    'distribution': distribution, 'version': version
                                })
                                detected = True
                                self.combobox_select(self.widgets.get_widget("combobox1"), distribution, 0)
                                self.combobox_select(self.widgets.get_widget("combobox2"), version, 0)
        if not detected:
            self.msg_info(_("It looks like that this distribution is unsupported."))
        self.widgets.get_widget("frame1").set_sensitive(True)
        self.widgets.get_widget("button1").set_sensitive(True)
        self.widgets.get_widget("combobox6").set_sensitive(True)
        self.widgets.get_widget("hbox6").hide()
        self.widgets.get_widget("filechooserbutton2").show()
        
        self.md5sum_thread = None
            
    def md5sum_progress(self, filename, bytes_done, bytes_total, percent):
        self.widgets.get_widget("progressbar1").set_text(_('Calculating MD5 Sum... %d%%') % int(percent))
        self.widgets.get_widget("progressbar1").set_fraction(percent/100)
    
    def detect_distribution(self):
        isoName_full = self.widgets.get_widget("filechooserbutton2").get_filename()
        if isoName_full:
            self.widgets.get_widget("frame1").set_sensitive(False)
            self.widgets.get_widget("button1").set_sensitive(False)
            self.widgets.get_widget("combobox6").set_sensitive(False)
            self.widgets.get_widget("filechooserbutton2").hide()
            self.widgets.get_widget("hbox6").show()
        
            self.md5sum_thread = Md5SumThread(isoName_full, self.md5sum_progress, self.md5sum_done, self.md5sum_cancel)
            self.md5sum_thread.start()
                    
    def on_filechooserbutton2_file_set(self,widget):
        isoName_full = self.widgets.get_widget("filechooserbutton2").get_filename()
        if isoName_full:
            self.widgets.get_widget("radiobutton8").set_active(True)    
            self.widgets.get_widget("entry5").set_text(os.path.basename(isoName_full))    

            if self.widgets.get_widget("combobox6").get_active() == 0 and self.widgets.get_widget("checkbutton2").get_active():
                self.detect_distribution()

    #### Other functions

    def list_cd_drives(self):
        drives = []
        if platform.system() == "Windows":
            import win32api
            import win32file
            all_drives = (drive for drive in win32api.GetLogicalDriveStrings ().split ("\000") if drive)
            for drive in all_drives:
                try:
                    info = win32api.GetVolumeInformation(drive)
                
                    if win32file.GetDriveType(drive) == 5:
                        drives.append([drive,info[0],''])
                except:
                    pass
        else:
            try:
                import pyudev
                context = pyudev.Context()
                enumerator = pyudev.Enumerator(context)
                enumerator.match(ID_TYPE="cd")
                for device in enumerator:
                    mountpoint = os.popen('mount | grep %s | cut -d" " -f3' % device['DEVNAME']).read().strip()
                    drives.append([device['DEVNAME'], mountpoint])
                return drives
            except:
                storages = os.popen('hal-find-by-capability --capability storage').read().split()
                for udi in storages:
                    try:
                        udi = udi.strip()
                        isRemovable = os.popen('hal-get-property --udi ' + udi + ' --key storage.drive_type').read()
                        if isRemovable.find("cdrom") > -1: # and size > 0:
                            device = os.popen('hal-get-property --udi ' + udi + ' --key block.device').read().strip()
                            parent_udi = os.popen('hal-find-by-property --key block.storage_device --string ' + udi).read().split ("\n")[0]
                            mount_point = os.popen('hal-get-property --udi ' + parent_udi + ' --key volume.mount_point').read().strip()
                            drives.append([device, mount_point])
                    except:
                        pass
        return drives
    
    def combobox_select(self, cb, text, col = 0):
        cb.set_active(0)
        model = cb.get_model()
        iter = model.get_iter_first()
        while iter:
            if model.get_value(iter,col) == text:
                cb.set_active_iter(iter)
                return        
            iter = model.iter_next(iter)
            
    def get_parent_device(self, dev):
        m = re.search('(.*\/sd[a-z])\d?', dev)
        if m != None:
            return m.group(1)
        else:
            return dev
        
    def get_mbrid(self, dev):
        if platform.system() == "Windows":
            mbr_signature = False
            c = wmi.WMI ()
            for disk in c.query("SELECT * FROM Win32_DiskDrive WHERE InterfaceType='USB'"):
                for partition in c.query("SELECT * FROM Win32_DiskPartition WHERE DiskIndex='" + str(disk.Index) + "'"):
                    for partition_1 in c.query("SELECT * FROM Win32_LogicalDiskToPartition"):
                        if partition_1.Dependent.DeviceID == dev.upper():
                            mbr_signature = hex(disk.Signature)

            return mbr_signature
        else:
            p = os.popen('dd if=%s bs=1 count=4 skip=440 | hexdump -n4 -e \'"0x%%x"\'' % self.get_parent_device(dev))
            if p:
                return p.read().strip()
            else:
                return False
    
class Md5SumThread(Thread):
    def __init__ (self, filename, callback_progress = None, callback_done = None, callback_canceled = None):
        #Thread.__init__(self)
        super(Md5SumThread, self).__init__()

        self.filename = filename.encode(sys.getfilesystemencoding(), 'replace')
        self.callback_progress = callback_progress
        self.callback_done = callback_done
        self.callback_canceled = callback_canceled
        self.canceled = False
        
    def run(self):
        bytes_total = os.path.getsize(self.filename)
        bytes_done = 0
        m = hashlib.md5()
        f = open(self.filename, "rb")
        while 1:
            data = f.read(1024*1024)
            if not data or self.canceled:
                break
            m.update(data)
            bytes_done += len(data)
            if self.callback_progress:
                gobject.idle_add(self.callback_progress, self.filename, bytes_done, bytes_total, 100.0 * float(bytes_done) / bytes_total)
                #self.callback_progress(self.filename, bytes_done, bytes_total, 100.0 * float(bytes_done) / bytes_total)

        f.close()
        
        if self.canceled == True:
            if self.callback_canceled:
                gobject.idle_add(self.callback_canceled)
        else:
            self.md5sum = m.hexdigest()
            if self.callback_done:
                gobject.idle_add(self.callback_done, self.md5sum)
            #self.callback_done(self.md5sum)

class Namespace: pass

class CustomConfig( ConfigParser.ConfigParser ):
    def getvalue(self, section, name, default = ''):
        try:
            value = self.get(section, name).strip()
            if value == '':
                return default
        except:
            value = default
        return value
    

def getText(title, message, label, default = ''):
    def responseToDialog( entry, dialog, response):
        dialog.response(response)

    dialog = gtk.MessageDialog(
        None,
        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
        gtk.MESSAGE_QUESTION,
        gtk.BUTTONS_OK_CANCEL,
        None
    )
    dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS)
    dialog.set_markup(message)
    dialog.set_title(title)

    entry = gtk.Entry()
    entry.set_text(default)
    entry.connect("activate", responseToDialog, dialog, gtk.RESPONSE_OK)
    hbox = gtk.HBox()
    hbox.pack_start(gtk.Label(label), False, 5, 5)
    hbox.pack_end(entry)
    dialog.vbox.pack_end(hbox, True, True, 0)
    dialog.show_all()
    response = dialog.run()
    text = entry.get_text()
    dialog.destroy()
    
    if response == gtk.RESPONSE_OK:
        return text
    else:
        return None

def check_version():
    try:
        html = urllib.urlopen('http://live.learnfree.eu/version.txt').read()
    except:
        return []
    
    try:
        NEW_APP_VERSION = re.search('APP_VERSION=(.*)', html).group(1)
        DOWNLOAD_URL = re.search('DOWNLOAD_URL=(.*)', html).group(1)
    except:
        return []
        
    if NEW_APP_VERSION > APP_VERSION:
        return [NEW_APP_VERSION, DOWNLOAD_URL]
    else:
        return []

class UpdaterThread(Thread):
    def __init__ (self, callback_done):
        super(UpdaterThread, self).__init__()
        self.callback_done = callback_done
        
    def run(self):
        result = check_version()
        if result != []:
            gobject.idle_add(self.callback_done, result)

class StatsThread(Thread):
    def __init__ (self, distribution, version):
        super(StatsThread, self).__init__()
        self.distribution = distribution
        self.version = version
        
    def run(self):
        params = urllib.urlencode({
            'distribution': self.distribution
            , 'version': self.version
        })
        f = urllib.urlopen("http://live.learnfree.eu/report-stats.php?%s" % params)
           
def tryint(s):
    try:
        return int(s)
    except:
        return s
    
def alphanum_key(s):
    """ Turn a string into a list of string and number chunks.
        "z23a" -> ["z", 23, "a"]
    """
    return [ tryint(c) for c in re.split('([0-9]+)', s) ]

def sort_nicely(l):
    """ Sort the given list in the way that humans expect.
    """
    l.sort(key=alphanum_key)

if platform.system() == "Windows":
    app = appgui()
    gtk.main()
else:
    if os.popen('whoami').read().strip() != 'root':
        if os.system('which gksu')==0:
            starter = os.path.join(os.path.dirname(sys.argv[0]),"live-usb-install.desktop")
            os.system('gksu -D %s ./live-usb-install.py' % '/usr/share/applications/live-usb-install.desktop' if os.path.exists('/usr/share/applications/live-usb-install.desktop') else _('live-usb-install'))
        elif os.system('which kdesudo')==0:
            os.system('kdesudo ./live-usb-install.py')
        elif os.system('which sudo')==0:
            password = getText('Enter your password','Password:','Password')
            if password:
                os.popen('sudo -S ./live-usb-install.py','w').write(password)
        else:
            dialog = gtk.MessageDialog(
                None,
                gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                gtk.MESSAGE_ERROR,
                gtk.BUTTONS_OK,
                None
            )
            dialog.set_position(gtk.WIN_POS_CENTER_ALWAYS)
            dialog.set_markup(_("You need to install sudo, gksu or kdesudo!"))
            response = dialog.run()
            dialog.destroy()
    else:
        app = appgui()
        gtk.main()



