pax_global_header00006660000000000000000000000064135664760550014533gustar00rootroot0000000000000052 comment=e1b8e117e16f130c5ed8c42b89ebe1fb832f5983 live-clone-1.5.1/000077500000000000000000000000001356647605500135745ustar00rootroot00000000000000live-clone-1.5.1/.gitignore000066400000000000000000000001521356647605500155620ustar00rootroot00000000000000# emacs stuff *~ # generated python files ui_*.py *_rc.py __pycache__/ *.pyc ## generated l10n files *.qm live-clone-1.5.1/HelpAbout.md000066400000000000000000000004571356647605500160070ustar00rootroot00000000000000© 2019 Georges Khaznadar This program is free, it is licensed under GPL-3+. Live-Clone has been developed to allow users of [live Freeduc sticks](https://usb.freeduc.org/jbart-en.html) to get an auto-clone system, which makes easier to make them more secure and to spread them. live-clone-1.5.1/HelpTab.md000066400000000000000000000156441356647605500154470ustar00rootroot00000000000000 # The toolbar ![toolbar](./img/toolbar.png) # * ![Help button](./img/help.png) The first button on the left of the toolbar provides a window "about" this application, and pulls this document on the top. * Then, the tools button ![Tools button](./img/gnome-run.png) gives access to maintenance tools for Freeduc disks: to reinitialize them if somebody made them inconsistent, and also backup of persistence data. * The run button, as it can be guessed, ![Run button](./img/computer.png), allows one to launch the system of the Freeduc disk in a virtual machine (provided the package qemu-kvm is installed). * The central application is cloning USB Freeduc disks, ![Clone button](./img/jumping-gnu-48x48.png) which can be triggered with the button or by a click one the title nearby. * The last rightmost button, allows one to quit the application. ![Quit button](./img/application-exit.png) One can interrupt the application even when there is an ongoing command and monitors are displaying its details. # Details of a cloning action # In the display just underneath the toolbar, one can see details about all detected USB disks, which are currently plugged to the computer. With GNU-Linux, their identification is ``/dev/sdX`` where ``X`` is some alphabetic character; those characters are generally distributed depending on the plug-in sequence. When one starts a cloning action ![Clone button](./img/jumping-gnu-48x48.png), one can select multiple disks by checking their boxes; depending on the quality level of the computer, its USB ports, and of the USB sticks, one can have some advantage to clone many of them simultaneously. When the disk(s) are selected, one must decide which Freeduc image is to burn into them. When the application is run *from a Freeduc system* the default option is **AUTOCLONE**, which means cloning the USB stick itself onto target USB sticks. One can also select, in either case, an ISO disk image, which must exist somewhere in the file system. When all the choices are made, the cloning action can begin. It takes some minutes, and one can watch its progress in as many monitors as cloned disks. The longest operation is the copy of the system's core, which will feature booting a Linux kernel, and some hundreds of programs, provided by a compressed read-only filesystem. When this operation is finished, a *persistence* partition is created; this one will contain every modification to the disk during its lifetime: data visible by the user, as well as a load of hidden files, like configurations, ans also every program one wants to install additionally. When the cloning operation is finished, one can save the monitors' messages, for further use. # Logics of the maintenance tools # Unplug a USB stick while the computer is running is easier than doing the same with the hard disk inside it : such a mistake is not uncommon, it can happen to everyone. So, the *persistence* file system may happen to become inconsistent. In most cases, the inconsistent parts are repaired during the next boot. However, the USB stick can become unusable if some inconsistency is really serious. On the other hand, those USB disks are made to teach computer science on free operating systems, to beginners. Yet *all the permissions* can be granted to the newbie user. If one has got the idea to erase some important file for the computer's features, he can. Fortunately, the core is read-only; when one thinks to erase a core file, one writes actually a code into the persistence, which means "this file is erased"; however the file remains in the core, which is read-only; this explains the magics of the reinitialization. ## Reinitialization of the live USB stick ## As a matter of fact, to reinitialize the USB stick, it is necessary and sufficient to erase two directories in the persistence partition. Of course, doing so entails the loss all previous work and every configuration made by the user from the begin of the stick's history. That is why maintenance tools are organized in a *cautious* fashion. ## First cautious step: keep the list of additional packages ## The USB stick comes with hundreds of preinstalled software pieces, but one may want more. Thanks to the software packages of the Debian system, nothing is easier! the ``apt`` commands allow one to do it freely (like in freedom). When the persistence is erased, it is a good idea to keep the list of every additional package, to reinstall them over the core system's packages later. ## Second cautious step: backup user data ## During the stick history, most of the files which interest the user are inside the directory ``/home/user``; one can make a complete backup thereof, or a selective backup. The tools' interface provides a tree view of this directory, where it is possible to check parts to backup: * backup everything ... simply check the directory ``user`` * backup selectively, for example contents of the desktop, the downloads, and a project inside the directory ``/home/user/projects/projetc1``: *do not check* the directory ``user``, check the directories ``user/Desktop``, ``user/Downloads``, ``user/projects/project1``; please notice than if two nodes in the file system are checked, the nearest node from the root may *hide* the other one, if it is part of a sub-directory of the previous one: the chosen backup is always the widest one. The backup is in format ``tar.gz``, also known as ``tgz``; all good archive managers can deal with this format. If one tries to maintain a new USB stick, there are no personal data, so this step is shortened. ## Last step: reinitialize the persistence ## This step, as all the previous, can be escaped; one just needs to use the escape button, available everytime. As the reinitialization entails a loss of data, one must confirm twice than one really wants to do it. This operation is fast, and cannot be reversed. After the reinitialization, the USB stick is ready to behave like at its first boot: so it will boot as slowly as it did during its first usage, because many initializations must be done (a *first* boot is one, two or three minutes longer than the next ones). # Running the system in a virtual machine # As long as one is using this application, one can test the restored USB stick in a virtual machine, on the same computer, without stopping it. This is possible if the processor is enabled to support virtualization (which is not the case for all processors). The ``qemu-kvm`` package is needed to be able to take advantage of this feature. It is not installed by default in the distribution Freeduc, but one can add it. Please notice that working in a virtual machine is one of the seldom means to get screenshots of the system during its boot step or during its shutdown, when the system is enable to manage the screenshot by itself. live-clone-1.5.1/Makefile000066400000000000000000000035031356647605500152350ustar00rootroot00000000000000DESTDIR = UISOURCES = $(shell ls ui_*.ui) RCSOURCES = $(shell ls *.qrc) UIFILES = $(patsubst ui_%.ui, ui_%.py, $(UISOURCES)) RCFILES =$(patsubst %.qrc, %_rc.py, $(RCSOURCES)) LANGSOURCES = $(shell ls lang/*.ts) LANGFILES = $(patsubst %.ts, %.qm, $(LANGSOURCES)) all: $(RCFILES) $(UIFILES) $(LANGFILES) $(UIFILES): $(UISOURCES) $(RCFILES): $(RCSOURCES) $(LANGFILES): $(LANGSOURCES) ui_%.py: ui_%.ui pyuic5 $< -o $@ %_rc.py: %.qrc # lauch pyrcc5 to make reproducible builds export QT_HASH_SEED=0; pyrcc5 $< -o $@ %.qm: %.ts live_clone.pro lrelease -qt=5 live_clone.pro clean: rm -rf *~ $(RCFILES) $(UIFILES) $(LANGFILES) install: install -d $(DESTDIR)/usr/bin install -d $(DESTDIR)/usr/lib/python3/dist-packages/live_clone install -d $(DESTDIR)/usr/lib/python3/dist-packages/live_clone/lang install -d $(DESTDIR)/usr/lib/python3/dist-packages/live_clone/img install -d $(DESTDIR)/usr/share/applications install -d $(DESTDIR)/usr/share/icons install -d $(DESTDIR)/usr/share/polkit-1/actions install -m 755 live-clone $(DESTDIR)/usr/bin install -m 644 *.py *.md $(DESTDIR)/usr/lib/python3/dist-packages/live_clone install -m 644 lang/*.md $(DESTDIR)/usr/lib/python3/dist-packages/live_clone/lang install -m 644 lang/*.qm $(DESTDIR)/usr/lib/python3/dist-packages/live_clone/lang install -m 644 img/* $(DESTDIR)/usr/lib/python3/dist-packages/live_clone/img install -m 755 live_clone.desktop $(DESTDIR)/usr/share/applications install -m 644 img/live_clone.png $(DESTDIR)/usr/share/icons # replace the relative paths ./ by absolute paths for f in $$(find $(DESTDIR) -name "*.md"); do \ sed -i 's%\./%/usr/lib/python3/dist-packages/live_clone/%' $$f; \ done install -m 644 *.policy $(DESTDIR)/usr/share/polkit-1/actions $(LANGSOURCES): *.py $(UIFILES) live_clone.pro pylupdate5 live_clone.pro .PHONY: all clean install lang live-clone-1.5.1/README.md000066400000000000000000000016571356647605500150640ustar00rootroot00000000000000LIVE-CLONE ========== This GUI application allows on to clone Debian-Live USB sticks. It has been developped to speed up cloning USB stickd of the project **Freeduc** (Free Education), see https://usb.freeduc.org/jbart.html Dependencies ------------ * **Python3:** python3-markdown * **PyQt5:** python3-pyqt5 * **GI:** Gio, GLib, UDisks, gir1.2-udisks-2.0 Screenshot ---------- Here is the window of the application, while one live USB disk is plugged in the machine (``/dev/sdd``). Actions are available by the toolbar buttons, and the help/user manual is fairly visible. ![screenshot of the main window](img/screen01.png) Supported languages ------------------- Currently supported languages are EN, FR. Translations are welcome : most of the translatable strings are under the ``lang/`` subdirectory : ``*.md`` and ``*.ts`` files, and a few of them are in files ``live_clone.desktop`` and ``org.freedesktop.live-clone.policy``. live-clone-1.5.1/__init__.py000066400000000000000000000302241356647605500157060ustar00rootroot00000000000000#! /usr/bin/python3 import sys, os # allow local modules like ressource_rc sys.path.append(os.path.dirname(__file__)) from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog, \ QAbstractScrollArea, QPushButton from PyQt5.QtCore import QTranslator, QLocale, Qt, pyqtSignal, QLibraryInfo from ui_live_clone import Ui_MainWindow from ui_about import Ui_Dialog as Ui_AboutDialog from ui_packageEditor import Ui_PackageEditor from dbus.mainloop.glib import DBusGMainLoop, threads_init import gi gi.require_version('UDisks', '2.0') import usbDisk2 from tools import Tool, MountPoint, FileTreeSelectorModel, MyItem from wizards import ToolWizard, CloneWizard, RunWizard from monitor import Monitor from subprocess import Popen, PIPE from markdown import markdownFromFile from datetime import datetime import io from subprocess import call class MyMain(QMainWindow): keysChanged = pyqtSignal(str) # means that some USB stick has changed newmonitor = pyqtSignal(Monitor) endmonitor = pyqtSignal(Monitor) closemonitor = pyqtSignal(Monitor) def __init__(self, lesCles, owndisk, parent=None): """ Main window for the application @param lesCles an instance of usbDisk2.Available @param owndisk an empty string or something like "sdc" @param parent parent window, defaults to None """ QMainWindow.__init__(self, parent) self.lesCles=lesCles self.owndisk=owndisk self.wd=os.path.abspath(os.path.dirname(__file__)) self.monitors={} self.ui=Ui_MainWindow() self.ui.setupUi(self) self.initTable() self.initTab() self.initHelpTab() self.about=QDialog() self.about.ui=Ui_AboutDialog() self.about.ui.setupUi(self.about) self.initAbout() self.ui.helpButton.clicked.connect(self.showHelp) self.ui.quitButton.clicked.connect(self.close) self.ui.toolsButton.clicked.connect(self.toolAction) self.ui.cloneButton.clicked.connect(self.cloneAction) self.ui.cloneButton1.clicked.connect(self.cloneAction) self.ui.runButton.clicked.connect(self.runAction) self.keysChanged.connect(self.update_keys) self.newmonitor.connect(self.new_monitor) self.endmonitor.connect(self.monitor_finished) self.closemonitor.connect(self.monitor_closed) self.update_keys() # check already connected USB sticks return def runAction(self): """ Run one drive in a virtual machine provided by qemu-kvm """ devices=self.not_self_keys(format="udev") wiz=RunWizard(self, devices, self.lesCles) is_ok = wiz.exec_() disks=wiz.field("disks") result={} if is_ok: for d in disks.split(","): result[d]=Tool().runDisk(d, self) return result def cloneAction(self, event): """ callback for self.ui.toolsButtoncloneButton """ wiz=CloneWizard(self) wiz.exec_() return def toolAction(self, event): """ callback for self.ui.toolsButton """ wiz=ToolWizard(self) wiz.exec_() return def showHelp(self): self.about.show() self.ui.tabWidget.setCurrentIndex(0) # ensure the help tab is visible return def rindexFromDev(self, dev): """ @para dev a device @return the index of the row of the table widget which contains the device, or None if it is not found """ t=self.ui.tableWidget rindex=0 found=False for rindex in range(t.rowCount()): if t.item(rindex,0).data(0) == dev: found=True break if not found: return None return rindex def mdToEdit(self, path, edit): """ Feeds a QTextEdit instance with a Markdown file @param path the path to the .md file, relative to this file @param edit a QTextEdit instance """ path=os.path.join(self.wd, path) html=io.BytesIO() markdownFromFile(input=path, output=html) html.seek(0) edit.setHtml(html.read().decode("utf-8")) return def initAbout(self): """ Feeds the Dialog with a localized text """ self.mdToEdit(self.tr("HelpAbout.md"), self.about.ui.textEdit) return def initHelpTab(self): """ converts the Markdown help file and writes it into the help tab """ self.mdToEdit(self.tr("HelpTab.md"), self.ui.textEdit) return def monitor_finished(self, monitor): """ callback triggered when a monitor finished its job """ t=self.ui.tableWidget t.setItem(monitor.rindex,2, MyItem(self.tr("Clone ready ... Tab #{0}").format(monitor.index))) t.resizeColumnsToContents() return def new_monitor(self, monitor): """ callback triggered when a new monitor is ready @param monitor a Monitor instance """ self.update_monitored_row(monitor) return def monitor_closed(self, monitor): """ callback triggered when a monitor is closed @param monitor a Monitor instance """ device = self.monitors.pop(monitor) w=self.ui.tabWidget.widget(monitor.index) self.ui.tabWidget.removeTab(monitor.index) if w: w.close() t=self.ui.tableWidget t.setItem(monitor.rindex,2, MyItem(self.tr("Tab closed."))) t.resizeColumnsToContents() return def makeRow(self, rindex, disk, already): """ Makes a row in the table view for a disk @param index of a row @param disk the disk instance @param already is True when the first colums is already correct, and the row already exists @param dic a dictionary disk => partitions @return a new value for the index, increased when a row is created """ def description(partition_ud): dev=os.path.basename(partition_ud.path) label=partition_ud.label label1=label.split(" ")[0] if len(label) > 11: label=label1[:8]+"..." if partition_ud.label: return "{}({})".format(dev, label) else: return dev t=self.ui.tableWidget dic=self.lesCles.disksDict() nextIndex=rindex shortDisk=os.path.join("/dev",os.path.basename(disk)) shortParts=self.lesCles.parts_summary(disk) if not already: t.insertRow(rindex) t.setItem(rindex,0,MyItem(shortDisk)) nextIndex=rindex+1 # create the button if it is not already there button=QPushButton(self.tr("Clone to {}").format(shortDisk)) b_function=lambda:self.clonage("/dev/{}".format(shortDisk), button, rindex) button.clicked.connect(b_function) t.setCellWidget(rindex,3,button) t.setItem(rindex,1,MyItem(", ".join(shortParts))) ## check whether there is still a Monitor with a process for this device for m, devicepath in self.monitors.items(): if shortDisk == os.path.basename(devicepath): self.update_monitored_row(m, button) return nextIndex def update_monitored_row(self, m): """ Some things to run to update a row table if it is already related to some monitor @param m an instance of Monitor """ t=self.ui.tableWidget r=m.rindex i=m.index t.setItem( r, 2, MyItem(self.tr("{} ... Tab #{}").format(m.actionMessage, i)) ) t.resizeColumnsToContents() return def not_self_keys(self, format=None): """ @param format if this is "udev", will return udev paths rather than uDisks2 paths @return a list of USB paths, except the own disk which was booted as a freeduc system """ if format=="udev": return [os.path.join("/dev", os.path.basename(d)) \ for d in sorted(self.lesCles.disksDict()) \ if not self.owndisk or self.owndisk not in d] # return the uDisks path by default return [d for d in sorted(self.lesCles.disksDict()) \ if not self.owndisk or self.owndisk not in d] def update_keys(self): """ callback function used when a USB stick is plugged in or off or when its partitins are modified. """ # builds the list of USB sticks, except the stick enventually # used to boot the system disks=self.not_self_keys() t=self.ui.tableWidget rindex=0 ## first, delete rows with disk references which are no longer valid for rindex in list(range(t.rowCount()))[::-1]: if t.item(rindex,0).data(0) not in disks: t.removeRow(rindex) ## then, add new disks and update existing ones if disks: self.statusBar().showMessage(self.tr("Current USB disks: {}").format(", ".join([os.path.basename(d) for d in disks]))) else: self.statusBar().showMessage(self.tr("No USB stick. Please plug a USB flash disk.")) for disk in disks: devDisk=os.path.join("/dev", os.path.basename(disk)) while rindex < t.rowCount() and \ t.item(rindex,0).data(0) < devDisk: ## skip the lines before the place of devDisk rindex+=1 already = rindex < t.rowCount() and \ t.item(rindex,0).data(0) == devDisk rindex=self.makeRow(rindex, disk, already) t.resizeColumnsToContents() return def initTable(self): """ initialize the table of devices """ t=self.ui.tableWidget t.setColumnCount(3) t.setHorizontalHeaderLabels([ self.tr("Device"), self.tr("Partitions"),self.tr("Status") ]) t.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents) return def initTab(self): """ initialize the QTabWidget in the user interface removes the widget #1, which comes from Designer widget #0 is special: it contains some help """ w=self.ui.tabWidget.widget(1) self.ui.tabWidget.removeTab(1) w.close() return def main(): """ The main call """ app = QApplication(sys.argv) # i18n stuff locale = QLocale.system().name() translation="live_clone_{}.ts".format(locale) langPath=os.path.join(os.path.abspath(os.path.dirname(__file__)),"lang",translation) translator = QTranslator(app) translator.load(langPath) app.installTranslator(translator) t1=QTranslator(app) t1.load(QLocale(), "qt", "_", QLibraryInfo.location(QLibraryInfo.TranslationsPath)) app.installTranslator(t1) t2=QTranslator(app) t2.load(QLocale(), "qtbase", "_", QLibraryInfo.location(QLibraryInfo.TranslationsPath)) app.installTranslator(t2) ############# lesCles=usbDisk2.Available() p=Popen("ls /usr/lib/live/mount/persistence", shell=True, stdout=PIPE, stderr=PIPE) out, err = p.communicate() shortDiskNames=out.decode("utf8").split() ownDisk="" if shortDiskNames: # if we have ['sda1', 'sda3'], this should give "sda" ownDisk=shortDiskNames[0][:-1] w = MyMain(lesCles, ownDisk) # addHook is not designed to work with a method inside an object # so, let us define the hook outside the main window, and relay # a signal to the main window # the slot keysChanged in MyMain accepts a string parameter # which is the current device if the system is booted from it def show_keys(man, obj): if lesCles.modified: # filter to detect only USB stick objects w.keysChanged.emit(ownDisk) lesCles.modified=False return lesCles.addHook('object-added', show_keys) lesCles.addHook('object-removed', show_keys) w.show() sys.exit(app.exec_()) if __name__ == '__main__': main() live-clone-1.5.1/debian/000077500000000000000000000000001356647605500150165ustar00rootroot00000000000000live-clone-1.5.1/debian/changelog000066400000000000000000000024021356647605500166660ustar00rootroot00000000000000live-clone (1.5-1) unstable; urgency=medium * disregard non-writable partitions * improved the management of double-device USB sticks * shortened d/copyright since LGPL-3 is already explained in /usr/share/comme/licenses -- Georges Khaznadar Sat, 19 Oct 2019 19:56:26 +0200 live-clone (1.4-1) UNRELEASED; urgency=medium * new partition scheme with 4 partitions (the third one is VFAT, the fourth is EXT4, for the persistence) * added a dependency on dosfstools -- Georges Khaznadar Sat, 19 Oct 2019 19:54:10 +0200 live-clone (1.3-1) UNRELEASED; urgency=medium * upgraded to new version: fixed missing imports -- Georges Khaznadar Thu, 05 Sep 2019 23:11:02 +0200 live-clone (1.2-1) unstable; urgency=medium * upgraded to new version: add translators for qt_ and qtbase_; Closes: #931796 -- Georges Khaznadar Thu, 11 Jul 2019 11:49:29 +0200 live-clone (1.1-1) unstable; urgency=medium * First publication. Closes: #931796 -- Georges Khaznadar Wed, 10 Jul 2019 16:30:34 +0200 live-clone (1.0-1) unstable; urgency=medium * First usable version. -- Georges Khaznadar Wed, 10 Jul 2019 11:51:12 +0200 live-clone-1.5.1/debian/compat000066400000000000000000000000031356647605500162150ustar00rootroot0000000000000011 live-clone-1.5.1/debian/control000066400000000000000000000023471356647605500164270ustar00rootroot00000000000000Source: live-clone Section: python Priority: optional Maintainer: Georges Khaznadar Build-Depends: debhelper (>= 11), python3-all, dh-python, python3-pyqt5, pyqt5-dev-tools, qttools5-dev-tools, qt5-default Standards-Version: 4.4.0 Vcs-Git: https://salsa.debian.org/georgesk/live-clone.git Vcs-Browser: https://salsa.debian.org/georgesk/live-clone Package: live-clone Architecture: all Depends: ${python3:Depends}, ${misc:Depends}, python3-pyqt5, python3-markdown, python3-mdx-math, gir1.2-udisks-2.0, fdisk, dosfstools Recommends: qemu-kvm Description: GUI to clone and manage Live-Build USB sticks This application allows one to make bootable USB sticks from an iso-hybrid image issued by Live-Build. It adapts additionally a persistence partition to use the free space on the USB stick. . It features also management tools for live USB sticks: when such USB disks are used daily, they happen to have inconsistencies in their persistence area which can render them unusable. Tools are provided to save persistence data when necessary, and to blank the persistence area, so the USB disk can be used again. . The application detects when it is run from a Debian-Live environment, thus featuring seamless auto-cloning.live-clone-1.5.1/debian/copyright000066400000000000000000000033171356647605500167550ustar00rootroot00000000000000Format: http://dep.debian.net/deps/dep5 Upstream-Name: live-clone Source: authors and maintainer's own work Files: * Copyright: 2019 Georges Khaznadar License: GPL-3 Files: img/application-exit.png img/computer.png img/gnome-run.png img/help.png Copyright: 2002-2008 Ulisse Perusin Riccardo Buzzotta Josef Vybíral Hylke Bons Ricardo González Lapo Calamandrei Rodney Dawes Luca Ferretti Tuomas Kuosmanen Andreas Nilsson Jakub Steiner License: LGPL-3 or CC-BY-SA-3.0 Files: debian/* Copyright: 2019 Georges Khaznadar License: GPL-3 License: GPL-3 This package 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 as version 3 of the License. . This package 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 . On Debian systems, the complete text of the GNU General Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". License: LGPL-3 On Debian systems, the complete text of the GNU Lesser General Public License version 3 can be found in "/usr/share/common-licenses/LGPL-3".live-clone-1.5.1/debian/live-clone.manpages000066400000000000000000000000151356647605500205640ustar00rootroot00000000000000live-clone.1 live-clone-1.5.1/debian/rules000077500000000000000000000004641356647605500161020ustar00rootroot00000000000000#!/usr/bin/make -f # -*- makefile -*- %: dh $@ --with python3 --install-layout=deb --system=pybuild override_dh_auto_configure: make all dh_auto_configure override_dh_auto_clean: make clean dh_auto_clean override_dh_auto_install: dh_auto_install make install DESTDIR=$(CURDIR)/debian/live-clone live-clone-1.5.1/debian/source/000077500000000000000000000000001356647605500163165ustar00rootroot00000000000000live-clone-1.5.1/debian/source/format000066400000000000000000000000141356647605500175240ustar00rootroot000000000000003.0 (quilt) live-clone-1.5.1/img/000077500000000000000000000000001356647605500143505ustar00rootroot00000000000000live-clone-1.5.1/img/application-exit.png000066400000000000000000000051111356647605500203260ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATh޽Y l=3;`OKh 5-jD&Hi6"QQdZUZ%JD* )iK.$` `k{ݷ3>z>;9s߻=A4 &1ye\3&pog`͞,[YR=?-?CQt#n6 vNSpp܂H2hTU,H$cwՁ:K$ 68*~ľ>""!L@]/ "$QFEy%m{Q'q\ZM'co^7IrYMh9 A.INkOEmQkO;]bG >fȀӹMa2?8Ҹ΃#zb9 2cfƹ8U391~/mN$Iv;LŻ"0x7'zlNE@JRL=@&LV01B6 87)*?\a.l6ި0MWBS0@g=̐AF H(i/÷muϷ/ի&K*i| g֮7]Pjݬ?WT̝ṼY. SW pG>n}kو{y U˱d=Rthi0J+LFVˑN?˗US ɓk{Xk5Ϊ*+r<*0YġB!VPB(a~^޴*!:RG7n͛7 ͊CɟHvkoGa͆!>-a \mvPJȐ ~lflڴgd"CQ^uj̆/]BǏ[bM-Րn#jhB IvdFJYAs}x<.ݷm݊BRwEl7ٵ+s[[| M2MJJJuOOo0_ܾ /c0R*"6n@^d6i7Úv5kgNK.?qwAmXebળslmMդPu_x ۢi&[ʰ~zիS;g=c]XZ1vsPS4Q| ]pݙU y^l޼(//0t܉2#׃?ͯZݯ%-AQ{8+GU=ȴt14"#|Igl'PP~nբ!!_S Y-+9J+R#E ,VCQ &a2iyɎ`k)!t+۟jx%– M]V-['qP, .ˢYH{p7rcTw״H\TT7;z{{ XY#eހ$/yLLLD "4m͌@&x:I#O40ƀ>q/FRNGc#!d N:.aL*F#ǗY2`AEυ$DRvz7oYW)Q&.vS࣮Z?\F%43qJN׃.~Ư7{J'pu:k6dĆ.KJ10ps M)3aVfOIoF9 |}=#?aLY`:X-oy5>{}%lqNƌ_7 dݑʒY34DPn D0IENDB`live-clone-1.5.1/img/cloning.gif000066400000000000000000000474651356647605500165100ustar00rootroot00000000000000GIF89a """&&&***...222555888;;;===@@@BBBEEEGGGKKKMMMOOOQQQUUUVVVZZZ\\\]]]___```bbbccceeefffhhhiiijjjlllmmmnnnpppqqqrrruuuvvvwwwxxxyyyzzz|||}}}~~~! NETSCAPE2.0!Created with GIMP! ,H*\ȰÇ#JHŋ3jȱǏ C8$N1)&.G)#͚ xjc0|Y&ΡG;$)iSFjdULAhS&>%4AIX\m܁Jm2"Pk/i\RPQ>}iPth@Ō@,iȓ+_sdɓMHӇ'6BAZ:8tT6ɗ7㓘 & pmt\ Mu>DEA(-" P  \ԩ|$&ax՘@SxAGU\i'oF! $&mAGya#0!} w h@qLBM4z4'1P'O㎃h %itv#$FxՄA Ɏ}Abg&pA '! e@'h4%E#<@'IXd.TWy dAW AU9@Jb'Bi* T%@mX2`'*+A*|(|B+- {Wa' G%*PVEq9P}@{dT0-A 'D@PGt( Y ]UPM+P! ybEHɍDqqAp"P3! B4SW}5M_l3XV-M@xF ?jeR9xuaHPB 'g%xjyv Z @S?HП&:BVL怓|B襟:{ @4AI')5M@b'U8s]?8K8!-@j!y%$\6P vX#i\ v`r DȄ!ͯ~1'O` F6(\T%dqaP=@!*D&\0ԃ iDB 6Ёf!'8Cؐ9aFъWA8Ń`B‚c$%Ƅ1Ym? xiϘ$1w=1 0!z)ɄDRY,%IMVT&oIR2'AIVR!#B2L$ʲ,k\ޒetaҗf2Yaކ% c&AMkVs'Me6Ӝdf9iF18'UӞbg>CJTR'<jIԍc"Yģ!CUB1EQ9dXőT5,iҔԍ-u)aR*Ԧ3=iNQӞ0 ! ,H*\ȰÇ#JHŋ3jȱǏ C8$N1)&.G)#͚ xjc0|Y&ΡG;$)iSFjdULAhS&>%4AIX\m܁Jm2"Pk/i\RPQ>}iPth@Ō@,iȓ+_sdɓMHӇ'6BAZ:8tT6ɗ7㓘 & pmt\ Mu>DEA(-" P  \ԩ|$&ax՘@SxAGU\i'oF! $&mAGya#0!} w h@qLBM4z4'1P'O㎃h %itv#$FxՄA Ɏ}Abg&pA '! e@'h4%E#<@'IXd.TWy dAW AU9@Jb'Bi* T%@mX2`'*+A*|(|B+- {Wa' G%*PVEq9P}@{dT0-A 'D@PGt( Y ]UPM+P! ybEHɍDqqAp"P3! B4SW}5M_l3XV-M@xF ?jeR9xuaHPB 'g%xjyv Z @S?HП&:BVL怓|B襟:{ @4AI')5M@b'U8s]?8K8!-@j!y%$\6P vX#i\ v`r DȄ!ͯ~1'O` F6(\T%dqa2 =@!*B\0\a _DB 6Ёf!'8Cp y""&5 E6"AX 2VAcdHE5~Wtc'dncƁ }HArk,$-%Df#Ȅ0RY$%IMV M'=IK~DH(%3U~bɄ2H1!T-d /9K^%4AIX\m܁Jm2"Pk/i\RPQ>}iPth@Ō@,iȓ+_sdɓMHӇ'6BAZ:8tT6ɗ7㓘 & pmt\ Mu>DEA(-" P  \ԩ|$&ax՘@SxAGU\i'oF! $&mAGya#0!} w h@qLBM4z4'1P'O㎃h %itv#$FxՄA Ɏ}Abg&pA '! e@'h4%E#<@'IXd.TWy dAW AU9@Jb'Bi* T%@mX2`'*+A*|(|B+- {Wa' G%*PVEq9P}@{dT0-A 'D@PGt( Y ]UPM+P! ybEHɍDqqAp"P3! B4SW}5M_l3XV-M@xF ?jeR9xuaHPB 'g%xjyv Z @S?HП&:BVL怓|B襟:{ @4AI')5M@b'U8s]?8K8!-@j!y%$\6P vX#i\ v`r DȄ!ͯ~1'O` F6(\T%dqa2 =@!*d *Ta0\a _DB 6Ёf!'8Cp y""&4 E6"AXEɄ6Lc82~Wtc'dncƁю}H%4AIX\m܁Jm2"Pk/i\RPQ>}iPth@Ō@,iȓ+_sdɓMHӇ'6BAZ:8tT6ɗ7㓘 & pmt\ Mu>DEA(-" P  \ԩ|$&ax՘@SxAGU\i'oF! $&mAGya#0!} w h@qLBM4z4'1P'O㎃h %itv#$FxՄA Ɏ}Abg&pA '! e@'h4%E#<@'IXd.TWy dAW AU9@Jb'Bi* T%@mX2`'*+A*|(|B+- {Wa' G%*PVEq9P}@{dT0-A 'D@PGt( Y ]UPM+P! ybEHɍDqqAp"P3! B4SW}5M_l3XV-M@xF ?jeR9xuaHPB 'g%xjyv Z @S?HП&:BVL怓|B襟:{ @4AI')5M@b'U8s]?8K8!-@j!y%$\6P vX#i\ v`r DȄ!ͯ~1'O` F6(\T%dqa2 =@!*d zBfDB 6Ёf!'8qCԐ8aBFъWA8ŃwDd1!e ɨ6VaHd://Q2g;~"zT-rr#o) T#!ȄЍ;DH$5ɂl6'%JJ%rT2rA2L ʲ-kLqL.K 6Ŝ%/ILf"S,1%LcFSf0K:ܦ5ũLrjDg:9NuRg<%iI_\*O~ӟh@9OAD_1,DЅ 25$CGDVUC8DOEr!/mLgE8i@! ,H*\ȰÇ#JHŋ3jȱǏ C8$N1)&.G)#͚ xjc0|Y&ΡG;$)iSFjdULAhS&>%4AIX\m܁Jm2"Pk/i\RPQ>}iPth@Ō@,iȓ+_sdɓMHӇ'6BAZ:8tT6ɗ7㓘 & pmt\ Mu>DEA(-" P  \ԩ|$&ax՘@SxAGU\i'oF! $&mAGya#0!} w h@qLBM4z4'1P'O㎃h %itv#$FxՄA Ɏ}Abg&pA '! e@'h4%E#<@'IXd.TWy dAW AU9@Jb'Bi* T%@mX2`'*+A*|(|B+- {Wa' G%*PVEq9P}@{dT0-A 'D@PGt( Y ]UPM+P! ybEHɍDqqAp"P3! B4SW}5M_l3XV-M@xF ?jeR9xuaHPB 'g%xjyv Z @S?HП&:BVL怓|B襟:{ @4AI')5M@b'U8s]?8K8!-@j!y%$\6P vX#i\ v`r DȄ!ͯ~1'O` F6(\T%dqa2 =@!*d +BpPB@@3Đ!Bj8C氉 a"E'p" {wL`q ,dE1~K4# ‚ h9n1YkdG:ֱ|-%DL"eC& zxcYE&m0IMJd$B< PDB2L r+[X&KkI˃6e/YӘ$f2yyLR2,3?MLeLgSf8 Mqӛ̈́#)Q.MJuӝZ&O~S HԠcc%90T dBQ8=#/:Q^ѣ:)A@4IK*R-LR7 ! ,H*\ȰÇ#JHŋ3jȱǏ C8$N1)&.G)#͚ xjc0|Y&ΡG;$)iSFjdULAhS&>%4AIX\m܁Jm2"Pi\)D؃iS|) 5ԡВ?> X>()[,0ɓ']=Ol,titp%4AIX\m܁Jm2"Pk/i\RPQ>}iPth@Ō@,iȓ+_sdɓMHӇ'6BAZ:8tT6ɗ7㓘 & pmt\ Mu>DEA(-" P  \ԩ|$&ax՘@SxAGU\i'oF! $&mAGya#0!} w h@qLBM4z4'1P'O㎃h %itv#$FxՄA Ɏ}Abg&pA '! e@'h4%E#<@'IXd.TWy dAW AU9@Jb'Bi* T%@mX2`'*+A*|(|B+- {Wa' G%*PVEq9P}@{dT0-A 'D@PGt( Y ]UPM+P! ybEHɍDqqAp"P3! B4SW}5M_l3XV-M@xF ?jeR9xuaHPB 'g%xjyv Z @S?HП&:BVL怓|B襟:{ @4AI')5M@b'U8s]?8K8!-@j!y%$\6P vX#i\ v`r DȄ!ͯ~1'O` F6(\T%dqa2 =@!*d +Bp Md"B $ *Ta4!R)KdX,Ұw0JFT4'D5 eLV'uE7NcHF;1Yo;1|􊷔d=,2!T#ȃD2Y,%oɁAN$A6)Q*R!'L Uҕ Ʉ2Y*eBl,\/uyP1<0%#L,tf2yKdVS,39mgADkrf:)Nv$*SOybdd=GiLVr)OjR},$!G.|<$D:+3@ Cbԋ%aJ-FѤ8 %FҕTiKažԧ! ,H*\ȰÇ#JHŋ3jȱǏ C8$N1)&.G)#͚ xjc0|Y&ΡG;$)iSFjdULAhS&>%4AIX\m܁Jm2"Pk/i\RPQ>}iPth@Ō@,iȓ+_sdɓMHӇ'6BAZ:8tT6ɗ7㓘 & pmt\ Mu>DEA(-" P  \ԩ|$&ax՘@SxAGU\i'oF! $&mAGya#0!} w h@qLBM4z4'1P'O㎃h %itv#$FxՄA Ɏ}Abg&pA '! e@'h4%E#<@'IXd.TWy dAW AU9@Jb'Bi* T%@mX2`'*+A*|(|B+- {Wa' G%*PVEq9P}@{dT0-A 'D@PGt( Y ]UPM+P! ybEHɍDqqAp"P3! B4SW}5M_l3XV-M@xF ?jeR9xuaHPB 'g%xjyv Z @S?HП&:BVL怓|B襟:{ @4AI')5M@b'U8s]?8K8!-@j!y%$\6P vX#i\ v`r DȄ!ͯ~1'O` F6(\T%dqa2 =@!*d +Bp Md"B $ RPU%O E6@XEɄe5F10`;&ˍ\#hG8^ E&Z$#yH&Km09MJHJN2D)/Lx+q`W&DɢApy]Җd|iQ,Le沕,0?ALLf-hZӛ1fnrә4g9O|' (JEc"jt '@R9C#4:Q*7QlKWҔTc|) wӝ! ,H*\ȰÇ#JHŋ3jȱǏ C8$N1)&.G)#͚ xjc0|Y&ΡG;$)iSFjdULAhS&>%4AIX\m܁Jm2"Pk/i\RPQ>}iPth@Ō@,iȓ+_sdɓMHӇ'6BAZ:8tT6ɗ7㓘 & pmt\ Mu>DEA(-" P  \ԩ|$&ax՘@SxAGU\i'oF! $&mAGya#0!} w h@qLBM4z4'1P'O㎃h %itv#$FxՄA Ɏ}Abg&pA '! e@'h4%E#<@'IXd.TWy dAW AU9@Jb'Bi* T%@mX2`'*+A*|(|B+- {Wa' G%*PVEq9P}@{dT0-A 'D@PGt( Y ]UPM+P! ybEHɍDqqAp"P3! B4SW}5M_l3XV-M@xF ?jeR9xuaHPB 'g%xjyv Z @S?HП&:BVL怓|B襟:{ @4AI')5M@b'U8s]?8K8!-@j!y%$\6P vX#i\ v`r DȄ!ͯ~1'O` F6(\T%dqa2 =@!*d +Bp Md"B $ R0NL P(Kd"X,Ұw0JFR4'D5 eLV'uE7vaH>Vc=vѐуdE*\dB,H%%HN"@G*)QM>R!V&Ke͒LH-uK6e.KSLH)d639McRȄf4MmfAIj~)9 Oҕ;IwҞ`=YO.\e@6&덇<(!yƅ" ]CjAꑢ|,% #ЄZq(CBq$աQҒԊZt)MiR/t,ENw€! ,H*\ȰÇ#JHŋ3jȱǏ C8$N1)&.G)#͚ xjc0|Y&ΡG;$)iSFjdULAhS&>%4AIX\m܁Jm2"Pk/i\RPQ>}iPth@Ō@,iȓ+_sdɓMHӇ'6BAZ:8tT6ɗ7㓘 & pmt\ Mu>DEA(-" P  \ԩ|$&ax՘@SxAGU\i'oF! $&mAGya#0!} w h@qLBM4z4'1P'O㎃h %itv#$FxՄA Ɏ}Abg&pA '! e@'h4%E#<@'IXd.TWy dAW AU9@Jb'Bi* T%@mX2`'*+A*|(|B+- {Wa' G%*PVEq9P}@{dT0-A 'D@PGt( Y ]UPM+P! ybEHɍDqqAp"P3! B4SW}5M_l3XV-M@xF ?jeR9xuaHPB 'g%xjyv Z @S?HП&:BVL怓|B襟:{ @4AI')5M@b'U8s]?8K8!-@j!y%$\6P vX#i\ v`r DȄ!ͯ~1'O` F6(\T%dqa2 =@!*d +Bp Md"B $ R0NLHxV Qd"X)Ұw0JFR4'D5 eLV'UE7vaۘ7v񊀬;1􊷔d=,2!T#ȃD2Y,%oɁlR2$'?JEJ!zK Qҕ Ʉ2Y*eBl,\/uy`JFü.iUrLf/ĉ$59m2Ŭ6iMrvӜp9MiS!d%yJTSdg=)Ozb3YO}3#"Pq|(C%ZDŽNt(F̌բ  /pODRT'uKeZTb%eHiž! ,H*\ȰÇ#JHŋ3jȱǏ C8$N1)&.G)#͚ xjc0|Y&ΡG;$)iSFjdULAhS&>%4AIX\m܁Jm2"Pk/i\RPQ>}iPth@Ō@,iȓ+_sdɓMHӇ'6BAZ:8tT6ɗ7㓘 & pmt\ Mu>DEA(-" P  \ԩ|$&ax՘@SxAGU\i'oF! $&mAGya#0!} w h@qLBM4z4'1P'O㎃h %itv#$FxՄA Ɏ}Abg&pA '! e@'h4%E#<@'IXd.TWy dAW AU9@Jb'Bi* T%@mX2`'*+A*|(|B+- {Wa' G%*PVEq9P}@{dT0-A 'D@PGt( Y ]UPM+P! ybEHɍDqqAp"P3! B4SW}5M_l3XV-M@xF ?jeR9xuaHPB 'g%xjyv Z @S?HП&:BVL怓|B襟:{ @4AI')5M@b'U8s]?8K8!-@j!y%$\6P vX#i\ v`r DȄ!ͯ~1'O` F6(\T%dqa2 =@!*d +Bp Md"B $ R0NLHx)> UAT$ (0J0#Ѩ-"81&r#85QX dh/q z He-LH#HL6d$rIdR&!JAXd'?Ɂd[@+KY2!LV- 쒗%4AIX\m܁Jm2"Pk/i\RPQ>}iPth@Ō@,iȓ+_sdɓMHӇ'6BAZ:8tT6ɗ7㓘 & pmt\ Mu>DEA(-" P  \ԩ|$&ax՘@SxAGU\i'oF! $&mAGya#0!} w h@qLBM4z4'1P'O㎃h %itv#$FxՄA Ɏ}Abg&pA '! e@'h4%E#<@'IXd.TWy dAW AU9@Jb'Bi* T%@mX2`'*+A*|(|B+- {Wa' G%*PVEq9P}@{dT0-A 'D@PGt( Y ]UPM+P! ybEHɍDqqAp"P3! B4SW}5M_l3XV-M@xF ?jeR9xuaHPB 'g%xjyv Z @S?HП&:BVL怓|B襟:{ @4AI')5M@b'U8s]?8K8!-@j!y%$\6P vX#i\ v`r DȄ!ͯ~1'O` F6(\T%dqa2 =@!*d +Bp Md"B $ R0NLHx)>QT, P(2wD0JFR4'd eLV'UE5Qv#AF=1mcݨGpUW$聑 yHHDɢdA0yM$A@ Q.r!)K"@& RY%-rd /˃S2$&.yYLe4+c~"&6Lg S4f7 jH9LiN i%-9OTeg>YI~3':P~r5*w#!A hE)PFt4yD(Ԋ8u(EԋptKI 2Q-UMaISW ! ,H*\ȰÇ#JHŋ3jȱǏ C8$N1)&.G)#͚ xjc0|Y&ΡG;$)iSFjdULAhS&>%4AIX\m܁Jm2"Pk/i\RPQ>}iPth@Ō@,iȓ+_sdɓMHӇ'6BAZ:8tT6ɗ7㓘 & pmt\ Mu>DEA(-" P  \ԩ|$&ax՘@SxAGU\i'oF! $&mAGya#0!} w h@qLBM4z4'1P'O㎃h %itv#$FxՄA Ɏ}Abg&pA '! e@'h4%E#<@'IXd.TWy dAW AU9@Jb'Bi* T%@mX2`'*+A*|(|B+- {Wa' G%*PVEq9P}@{dT0-A 'D@PGt( Y ]UPM+P! ybEHɍDqqAp"P3! B4SW}5M_l3XV-M@xF ?jeR9xuaHPB 'g%xjyv Z @S?HП&:BVL怓|B襟:{ @4AI')5M@b'U8s]?8K8!-@j!y%$\6P vX#i\ v`r DȄ!ͯ~1'O` F6(\T%dqa2 =@!*d +Bp Md"B $ R0NLHx)>QT,aػ`"aA%E)edh1&x9r1YllG:ֱ|-%DL"eC& LV# Lr % OlDH'? QBɄ2U&Dbe+c9d e-osK\r%ArW B a|1 M`6Әe6MTS&8HTRҜ (щIvS)NIOt)@qn$?O4tzP6C zEJ<"F+*nXEEQ'EHQ. ! ,H*\ȰÇ#JHŋ3jȱǏ C8$N1)&.G)#͚ xjc0|Y&ΡG;$)iSFjdULAhS&>%4AIX\m܁Jm2"Pk/i\RPQ>}iPth@Ō@,iȓ+_sdɓMHӇ'6BAZ:8tT6ɗ7㓘 & pmt\ Mu>DEA(-" P  \ԩ|$&ax՘@SxAGU\i'oF! $&mAGya#0!} w h@qLBM4z4'1P'O㎃h %itv#$FxՄA Ɏ}Abg&pA '! e@'h4%E#<@'IXd.TWy dAW AU9@Jb'Bi* T%@mX2`'*+A*|(|B+- {Wa' G%*PVEq9P}@{dT0-A 'D@PGt( Y ]UPM+P! ybEHɍDqqAp"P3! B4SW}5M_l3XV-M@xF ?jeR9xuaHPB 'g%xjyv Z @S?HП&:BVL怓|B襟:{ @4AI')5M@b'U8s]?8K8!-@j!y%$\6P vX#i\ v`r DȄ!ͯ~1'O` F6(\T%dqa2 =@!*d +Bp Md"B $ R0NLHx)>QT,aػ`"aA%E)edh1&x9r1YllG:ֱ|-%DL"eC& LV# Lr % OlDH'? QBɄ2U&Dbe+c9d e-osK\r%ArW B a|1 M`6Әe6MTS&8HTRҜ (щIvS)NIOt)@qn$?O4tzP6C zEJ<"F+*nXEEQ'EHQ. ;live-clone-1.5.1/img/cloning.xcf000066400000000000000000003036271356647605500165160ustar00rootroot00000000000000gimp xcf v011CCJG gimp-commentCreated with GIMPgimp-image-grid(style solid) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) &9UEp[73OkCopie de Arrière-plan!? "     %$#5a /ޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 2Arrière-plan!? "     %$#9{9C'W0p8ޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 2 Copie de Copie de Arrière-plan!? "     %$#::U-U9;CL4Tޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxءxxxxxxxxxxxxxxxxx xx xx xxxء?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 2)Copie de Copie de Copie de Arrière-plan!? "     %$#VfVppV^gp<ޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xءxxxxxxxxxxxxxxxxxxx xx xx xءxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 22Copie de Copie de Copie de Copie de Arrière-plan!? "     %$#rrDrtzޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xءx xxxxxxxxxxxxxxxxxxxx xx xءx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 2;Copie de Copie de Copie de Copie de Copie de Arrière-plan!? "     %$#CO/C\ޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xءx xx xxxxxxxxxxxxxxxxxxxx xءx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 2DCopie de Copie de Copie de Copie de Copie de Copie de Arrière-plan!? "     %$#+Åޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xءxxxxx x    xxxxxx xxx xx xx xء?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 2MCopie de Copie de Copie de Copie de Copie de Copie de Copie de Arrière-plan!? "     %$#|ŨRޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xءx xxxxxx x    xxxxxx xxx xx xءx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 2VCopie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Arrière-plan!? "     %$#R~(ޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy ġZu__҆EOp ġׅGwfK|"r"ߒf ġ""l~&"  ġ*i*.M ġUE \m  ġ*i2e ġ" MncġքEwp5mxG`ڍyrġ]nZQ\ ;@ġ)hһxx xx xxxxxx x    xxxxxx xxx xءx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 2_Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Arrière-plan!? "     %$#1]ޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxءx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 2hCopie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Arrière-plan!? "     %$#E33u!e*~2ޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xءxxxxxxxxxxxxxxxxxxx xx xx xءxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 2qCopie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Arrière-plan!? "     %$#5 56OzO5f=VFoNޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xءx xxxxxxxxxxxxxxxxxxxx xx xءx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 2zCopie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Arrière-plan!? "     %$#QQ0ktkQ`YPbijޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xءx xx xxxxxxxxxxxxxxxxxxxx xءx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 2Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Copie de Arrière-plan!? "     %$# mm;mku[~tޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExءx xx xx xxxxxxxxxxxxxxxxxxxءx xx xx xxAޟ&p.`22nOVi`҆EEME2"V22Kn*_Ufbޠ&qExx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxA@==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?==Oy Zu__҆EOp ׅGwfK|"r"ߒf ""l~&"  *i*.M UE \m  *i2e " MncքEwp5mxG`ڍyr]nZQ\ ;@)hһxx xx xxxxxx x    xxxxxx xxx xx xx x?@== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?== u}j_ h5zUwfK|@"r""=l~ G*2zU. UvrE \ 82 8 }  M@wp5mBxG nZpQ\Jx xx xx xxxxxxxxxxxxxxxxxxxx xx xx xxx?@xxxx xxxx xxxx d 2live-clone-1.5.1/img/cloning_end.png000066400000000000000000000033621356647605500173410ustar00rootroot00000000000000PNG  IHDRt:abKGDC pHYs.#.#x?vtIME1/_tEXtCommentCreated with GIMPWZIDATx_H_E?0bv12bu1dua RQ2dM!D1qiӵwh[墹?﻽E8z}i~<{ys}XDD b `00L HVX,FLfff8wT*""X,<۱#N'"jiiX,Fϟ'VKF^/UUUdbX6V/mmmtA}.zzz6lv` JA.by? HӘhq8`b듍qi#JA\ti67Fee%zsh4ߣZ6ޝ;wD  zADuI,qB~b%u!} (bhh8q8C2ıcdrNϟrΜ9Aj"ɠ **JL&pp8 Rk|2n`0d2" T*%"%"@E2tt: %}*** $1뒾߿Ǜ7or}>%HDYP p Y=y$%盜D @v]v:l6<_;88l6 DBE WI(KP "ZF6ׯel6DAh4bj4xy? "BII 2 ,,޷o$;-߿"–-[Ff!L2qa٪XVx͛7/ٝ;wRQQEQY[,K|d84[JKKC$w^Y|R)r\b޾}ÇIPѣGTRVӪU{vvV򹻻82"":w) zقsI$Nry~?m߾Z B!k۸q#%E|(-(W544jX,իWfiӦMUiǎtqڿ?a2 ΥbI@0vZrJ .իWe BTZZ*zڶmX]v֭[ [RRBk֬!A$~N';|BjZ⯯ϛǩT*9SחFFjTWW˗7oQ188Ç>T 555 qn7v؈ݻwO>(и?~D4ٳgq<~cccuttl6 111!blv t:]A{RhڵkW/f3FGGǑf133ӓ+B ܃:u/"hF" D"p88rȒRhCv#J!LbxxUUUyݻD"d2Bhnn܃lwL +L ;;qf3[&f z,VW'sP(D/^d Dcey & BEz+IENDB`live-clone-1.5.1/img/cloning_end.xcf000066400000000000000000000103221356647605500173270ustar00rootroot00000000000000gimp xcf v011CCLG gimp-commentCreated with GIMPgimp-image-grid(style solid) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) !Clone ready ! ...!? "     %$#L#gimp-text-layer(text "Clone ready ! ...") (font "Sans-serif") (font-size 16.000000) (font-size-unit pixels) (antialias yes) (language "fr-fr") (base-direction ltr) (color (color-rgb 1.000000 1.000000 1.000000)) (justify left) (box-mode dynamic) (box-unit pixels) (hinting yes) 'G G322  322  322  7Y|3l){P|297B|2|C(n->-|C$=v9/"~3=/"~|IޙO||o|~ ~96B| m(zP|E"/) 'p/) '8Z|E*(׌())#  ::a))#  ::a))#  ::a))>dT1Q13+?+˴g&5% yW|ٴ[J\fôG6s9\{ٴP##z\%j p0j\A)˴H\H\H\\V3 H\H\H\A8::"a? Fond!? "     %$#KJz@@@@@@@@@@@@d 2live-clone-1.5.1/img/computer.png000066400000000000000000000064031356647605500167170ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<tEXtTitleComputervtEXtAuthorLapo Calamandreiߑ* CIDATh޵Y}]E?3w{v lw`mh)`J@i ")F" `HL bhS cMB-P )-ЖlKxws}lޝ{gΜ9sߞQ*{)%H!APnaZ΍}V>.Y PfͫtX(?b^{%CaLD,4mjI{)4?-Y ]g'58r8t˦3$#-!R"E]qЌϛc )eNpAaAG'΅8z}!||в32aAybI"W,]}^솺nm++l8 CiGo4)'׬(zil&dV/SK (f$Iߑ BK. s26fi5Q+4aJ5@'&܎HFʭzj dBԾ+F4@ {1O"' G4$+ mICKj !s(2ah4}@ 8PnaUS;_1/ J~ZXPItΗp;BE0j6>el߭#a’y?8cvX !?! Lm%܎`m55$\I£Xz&@객J8aim k(@ KNaQP->,Lx{_GKМ I ]@܋(b핹YF詡)Yx,E EI^=kT0Nl} ܊Zs5$L$z ,\L5PHNff 3)!Tă1DBRgN4$vj ӼɗnBOs)RDqì4BQiFie7`48[?GȳX`,S1E`lv"3l-E<7BfCm2&4`}HZSS+Mb&,?say"|*zE Eі1ه!;[whD;{iy1̺d^-3d,i׌:բ3_0i MιXN0ډ5&1A\.$eĊ8f^m\ **Su⋍L>=3'H Vв7L3N )F_S}KCm㏓!Le < WYe.]:G. :;D溨#)#?.ц8`~dF~g_??0p+6z )a6zb]˱u56l {zzŽYdRȨ8r䈨b9c: 2yf>66&&&fddgϞ &''z;wE}\^Y LNM~(-(/8άr 8>^*a#R&괤FJ䃘6}%aoo/)΢Ta6{>{7=u[@ i Q>w;t0xx{ax %^EBFsCC+ry1 MXxd/;|0'80YLFQx?}݀:O iFggg~xc\+OM#? aƆ87e###fH Ocj4Mɼ hEd 2vdFԘ! O}_ċ/g;hsL&фSܷ&=IғMHX1oSB0$M$S9B"F! oٵ) 1I$1U%Kĉ[׫ _t>qbcl,LbBpo8xI$ $Pӝk.YsQAa?mVkFUr !,]:~qe00пsg%s]{{ Ia͊p* Mo{r$ c_ܧ`o_UϜ> / ѵ_~s l}U{'&\"&|u$UC$U6.֫hJKͧW6aKlݺuq. [˷T0^+jpqUO8~!W˝٬8*5}gT^J}K/"Sgak?>;zL'}#x ;o$s7mԿ|ÿIW(fm> ʘ(wԇ$v1Bou Ҟ* ۷vmq㡯|Oq@/g IDAThZPg6 A4Dx .ĒKJ&M9sM.ѻT+jH.&$T ٥ H,4*H9H"ߟab3_yuƌ.{h>p[$Ty<<+[PxɞǼYkݐeKd6Hp^Vnz#[o^fqDžreWKK ꠻ + x oIp5F(ї_*(UUL9/׃XRWVn0՛DR! ;`4Id"ђk*Cì:FfAJj"dd.?5M~\#Gǃ -7HMHz::1= g!>)Sb!I)iH,hniz$s2$j1+!YD lQ|v]aK< !I+$HLl dj@$.6CyeR})\fuD,mmphR`ttR3R&ƌh1RJ4\L]Ȇy s0G$3u KMPM &S-\jiƬ2YOR)-+1Λ/H~nr;Å"CX`SK'` E}16 ZO7fWuOҸc\͓#Paɉ|6E}TˠReʪ9Qb t]a-*&=2PWoW^}>QvH ݄BWCeZۛ'߳9KC.cI[/"AOj|;F3U]R0*Ql7e.9% V(Bqidҙ&ml- )8!Kpz F5!;; q y }sF4aSs,Fi. u>cv9ɾC[ 6`AdT8`D.ϛuDm~$^PP4iEub $&p\jkSaa(PDpHL-<@*UTC^DW@vF]ƛ衪l"5*&Dz2Ř@*mĂO%A!c_ ? @T '0iҩ3Waѕdf‚ݰ~|n8thTT cܼuZ;Kj L731oe ~G/2 K}׮[wۂόTv%7OjMSHYtMXqg&=ѣ,賧'*m:rĬInDM&[pT1DSQU1+|F+@% Lqk0n[Z.ajgl~ϥao+> UKi҂Yɰ,%%Uc%ۋ3bLNxͅ#k%d}h3`8|?qlLq={̸,xl[;Nb1E©8xkpunS`Dj㉤"0_gR*Η8 uu5eA!ǠBO3[ M x.2fjUP5,:( :7/OAPq=8U:O|!'!9l 84+|ZPw33/*.b >*: (P0'im J  [p[IJ?قOX*!j̀PPwǿrͪ-ώ}uT_'+t pE[kX{`_E@y`__"l`hDFy6&:dF E␠ ΀͚!ٽ(Ơ'rZ Qb>i  )H_ǡꀰto؝-rczծN((BWY öo" +[ :::.qqYkmAnD<#rwW>:*[$Thtypq NP<%Y:Z%Q/`:,?xkZ7ł9B΋zMm^[Xxl*MH"OD1zkSc dus8t '%_"6قIJ>/@\Vٺȗ@X~sA8#!rz`X8_e7 ĞںjI$t`c72gDNGv=؜ ,`Q nܶǤ!XqIWn%D <<?' 9lf+KB''sG(ڎ%aÀ-ήl/k]\k79bI_0|Ū?~r?]]}ɹK \eȄ EAVN:D[PL$M">< #  )ZJk_QsH]i=.j{GGo:Q U8΃P*З>{a @xɠ!&B'=@#Y]xr Vc.wt%@R If.\zۮ>pDқKuYDo7u2w^T|( )%Iﵚfu y Rq岀ۭ̀*1pfu-\«mm%Ģ !͊ötx\EӓIZˋhP'Á#U`w*8SnR l 9ċ,5|]g3="-ZGz^FL>@3}JXiVLilߝ4ΙM8\JKaq$wN|/`4IENDB`live-clone-1.5.1/img/help.png000066400000000000000000000054321356647605500160120ustar00rootroot00000000000000PNG  IHDR00WsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATh՚{T՝?L 30P0 :(Ht$$1 U1ƅ q-Ą2Pꂲ"!In\ a5$0(Ĭ 0}cpan Tu{Ϲ~ZQnx3`i`ҥkm;IR*'|pKb@kMKU) ߓO>c<lx<>!xLϣ*o*$1X[l%8E+йJ).V\P B)*' !x~ x:ⲤP6&^7@X0Ja1L-YHw寪BMm!+>6ZC|0lpP8uQi> Bbve |/+0JAr=;t Cٳv:Gįg>u3v,JIT!0ib`>yinJ{k JrG6ڊ7Ii'pWUpkO?_*iݻqo>b.#G*%z垂{8+Mnza<{زlkFLIJiد g>wڹǘ#۷8;dOEp BpF_Ts0{ #v :%K:"0!lRⴴ %W]Ļ{I q/} (I o2zI#<Ǯ㭃i}Tz pկ%cK0 .oʾq1ağT$?as7=7s,3 0!':ٲc|:>Q==j6[lݶin\y  4B~q >2Z G0ųiimźr[$2zW0i"?Ԫ&Cu,N2=r)Bϋ׋0\hºV^5Y˖]c35oENךp( @.+9 ;;TcJJhxQi C]z)lf~0jbQ%pB4Pp@Ny';x"( BFHz e)]8&w`+pT:5j6&P84lHPBSGvH$JɧEcL2Ia*CBl8$۩>?#AS|5 /KrLnH6E54`hBkpr  9kj$A6mDwxf߿ux"Hq-f<"kvcT|U ~|-/⋰2jApl+9bﶴP4X RGI0 [͙@ O}(%x\Y"7e琢WS[[K<' #Aۉ$ۨ 䘻g+.u/ y ;q>G)uBիWZ.$}7E]Lyt5c2ҽ)N?{y|TTԏ@j!uh'? [ N) N)k(?!2m_@'Xm"ůܶ!nRc炙垄1P+G<+0]#v8(F,xbK:*P5ÂӘ18NP(h..;sOSQ]m1P=. ąk׮W%Zk-NYtRiiqeY$ɧbfKyWWW&Ht#X3SBg&OmyufD??&4IENDB`live-clone-1.5.1/img/jumping-gnu-16x16.png000066400000000000000000000044031356647605500201020ustar00rootroot00000000000000PNG  IHDRazTXtRaw profile type exifxڭWY$' >B !a ||?q2P@==6퟿ k/g ] ^3G^-|Л󃅊1|mOkApK?M(ˎ.C2cg aez7qK8/+-w*u#'jAv_#=bw珡0_#FKOu=P;A[z{K#RެC&fe&=VxG,@͌dN*%P60Z[,:`-R+eGNÍ,B}Tޏy˛ XrYqti" ro&5(e!gB E6! |˪=B-ѦD}ᵴhzPFv״$m9mNt/˒y#z#vHe _NS; ShEfBU ːR;]MM۬-UØkny,T%hrAQ7H]!qRormb"vs/f2/>ޚfjWx3;v _ i󪓥(]4_軑c8V;pehuK%ݹf~roW ޷ËϨw]>!F@{=V8fU3VkbKGDC pHYs  d_tIME +1VIDAT8ˍSAHSqsl;޳!iZr;d"JBv  4s@!Bء" 1qC;$fnkMM}E)>34><jb9:Sz<5UM!V|Rޕw 38pTQjޠ(ja%BƷoIJ,tЯFF$@-cE{{^Pehg<TQ1H9.[Xxɲ,zU0<9Y\Yg`eci, j#[MMhl.--]w8\g?|[֔$d2IDQ$,p8L~J(&Pm ZՔRL aqF IH!+ P%+L3>!͊f3qx< &gxA+mm[jczd2VFEEffg#>nf`hh -W\WyUEBZdccchm;B.MLrEQJ$ts\W7ӕ檪2V'۷}LӼRu ,4Lf0L~=|9BxIENDB`live-clone-1.5.1/img/jumping-gnu-32x32.png000066400000000000000000000077641356647605500201130ustar00rootroot00000000000000PNG  IHDR szzzTXtRaw profile type exifxڭir:sb),)ls9|[R,O$ʬϿ?\%)5/~RK-(7zhoW}Ɗu40/;r{>oOF!nŃs#5|CORıS EnMpOmx4hH JIOIDINDDs)Kιd(-"%RjiEkJ͵Z[ZD¤V\5U&UVz+-T{豧.=ko]iȣ:f̳YgJ+-YyUW[ڎ;my]wDF+jFߨb+_Cx1@,$0O)rI!Լ8b 7'p ! rΠ7M=%, -W VPi6mEf<7/WW:t][D־G cyjD]dL9mtcKT" NCcy|fݚz麩}un^zE{As:sQeһPEfC>"^AfPrNM2U誼n< CH,2!z+CHsl&'+G"FXXz]7m+HeIM{qZE;Qա 420cNb쁷1tԌ,/9vß1<3yײaV%ǵ46ǶjʄCc:d$`0n"#%!B1% [(^)@(o_фc2h3_B6+ Vgl% ?;7.њv$y%nDM A#7_0uX2/ uT A$oP@B0'9:H݉D] \ f)&+!AҨcRl0Ηݽ_?*}Z$"v{ Lz qni%v0Y-5J\j9> su6Ӱ#myI`#;7f]8&L V vg'נ(<2LNAbJ|3dǁB\f@)cdYu`>*eJ*!;kslhГE+@X"rIMv.d(RSlV,3#LF,-'ۇ#[9&v[1h3'+EiC$X ۱!;Hž̦3eRgj/˄J 0~wI}{u03Xxq VSSwY 1[9-e;9`6_jrrbKGDC pHYs  d_tIME *(z4IDATXWmPS~.aa4!$fEY,Najdku2۱::9+$N-3:,eG"k#%$T$1  !&r[iGW̝9}ssr89$+Vn۶۷o&,e7oغb_(Bȑ ØBa`0|sodʗ:]ǫVrrMjJH(J[^V/CVŋ?ٽ{e+Wt@#{].yGuf90 y&8pGB)))o9UUy1kљ|]JUR詩)b||@Edo__Рmhi!om%ht1a^kYE۝CTp=b1~bXAvvN1˲N8* GZ== —ð{f3֦C`6Wߘ Ctly-٠it fff>HRеd~~OII#֧>~2AT ۋruva$$e DSS΄)eW20Wr Vn,ꗪ! xNb`8H$`04?s+?xknnwID^$  rrr!H`ZfĆ<@$9F[X92Jp_-TfR3@("-- Rmmm8nrÇ(HJS񐘘!:͵6;eeX~,??+.UWƪgAff&, <&''! d2L/n7[E)`2 heYMdWdegϟ\--F#innء{N1=zܹ8%'OmD ( '0H$\._jnbE ;;;pcVٮY\.׿>}:nd Nf'珣IENDB`live-clone-1.5.1/img/jumping-gnu-48x48.png000066400000000000000000000317461356647605500201260ustar00rootroot00000000000000PNG  IHDR00W$zTXtRaw profile type exifxڭi\7ΦsNzlV}Uխ,+S1\;/tV[x{{_w?y(rΗ/{}!+X vEǟy+4>yoƪݫ {u 29ͳH=)omn,pyiJ/ΉJ#}6.&$"@=$ E>63rD %6)C5ټh0B "X9Ss#%̊UkmTrRJ-¨QSjhfZmfz뽏z3Ƙq2lϱHjNeW{pHriqɵnv˭~Ϩ}ר_"QS{^#j<\돷S̈X́WE@erb{(,` 'Dgܿ-.rN9}#Cx^TS.N;O׏(kmY1h|XcrMTmny}Zl X pj87k'j3T.1Uеlr#nj?%9Ԓ8ׁ!tKK>rK Y3f =Z1Y08c-ν=6+]+|nRm ɛՁezU.3ܯOvveϓviVxr@G鶌:hcTO\gg*u4Z$fRo9FM;Q[]L_xe2|MjS~ mJ 5H!Co0ʈ!lŋ =w^>F\W3Ȁ:ӫE;Q?jN!ROIʹ7YO4~T4|.X5R1®|ǮqY3m[Y0+GSOWM6sfls̯9Kfa+(5tlS 1@:jv.a =MaF(ҭlVﹸ|~F}y=I2lܵAѮ#M*}i[wl,JuS3d͕G`|$r$ ߯{WJ> 963Ji]{3PpM;巁)\!k 9z CQ&?M>7[T<ڟJ/:Kȫ'>&kߞ:܁# .TT}<մ}l#5\;@[{ $f!P 6. r"p6Ӌ XN^`>O0I֚`^C"K˄6 4fE~Kj(brle;Ւ~8]\_AjcDL@5qD*tJ~L~f(uVS'8^*y[{#tD >Sq~*ԥ>%uEblJӚ-ƄaP"p ǽt2ȔbW&|H?r$J>~Ɛ07~ˣO\+ 3`t02dnI{'7ͥ C E䍂qT#,.1\=UD#6W?RI:~xetyUAJoSO:0m9/[!hBSӃe}+2}òx!btQW'0@ FzWA,ֲ "I ~SIw=?/)`yU\@$xKw'KQ"F"md6Jy0` +EْE+"H5HYPvihl;ِlS F۽kcuh+jivQ" <*jO`!|ZG4SAO @D^*YvQ)!2d]gfHEĤ[Aw0`NBM[Md'S7qFRޱ}-"XB>Asd=A$>z-$@#D VhT`ԻCDīn<:"l2sCMփ%z/ F,;w@B w/(d!B`阀S,䌩 75^Q;![PZG?hOƫ0K-ʂ&}miS| R2N,N1'PN<u/p  qXyITpY@%o+_)_@ȅק!¨Y?%+N &ȕ Wnaѕ<~6hL!u_B[*jyD eSջbom<&bsvD&Rb I; vٌU+8ԭYQ} 7"0bn>~̋ϻ-$jڣP?@K\"(|tR"rN~'σz 0-/L4B*PL{w0Z0[Iz؉@$(G%pE!ɳqt/ppg}t@n"QI,- U1\끡 u<)/%W,Z,z.Qˍ;P#q IbWڻ hfh@yA9#"5z؝ie8odRB qQYȧmO7:uZO@C4:4ҨTlnd.B/eQB?aBxwDą#jKMϪҶ* [Rmsyd OF6i r5 3v˼̲CGx.UpgVB>&.uvp%,ӕFC.ء}G33 e|>X+[fhfXf?f`e>h7 AqZ䕑͎f x 0E] - T-pq}HYTLD?Ii\U¥h+}|6KM [<ha!gOװ=1V/PϾ4!rXNA!|գ< DA 䙨A5@CED6RPjyltSߨh{!=pyYRoƑ;JxX-<ɳ&j|¥rA~LDLt`=PHY>Zz-N1(90&8B;B2Y'.dm>$E`O/dVM`,qGșԇ 09[B젝$8cٔCD<KnS h'BVф!,![>\Rve2T8\,@BHTi֡63[/B=oITl4} {QI( K12l#-aϥ|uƲ4ݓgY=gک.I@+la3xgNB1]^?Cf'_%?w\lڦ3Krxdx Wds͊d*G !Ae_<1LKENz1ZJX{E & eOVde,/LWȾ^Yi^^B%%PFA]=[pu4,ƍ< [{ibޑVk΢b.,#~BP\|M]}%_X$;ͫ0*h=$ZXuy929^.L/E5(;NfT#:y -X1K|O.c) Th3;^Eg)`zXf ,.j$aG﬛ EtZĔ@ҖDv5!&ZllV<% Wa :O!Pos ϏO@&|bk&'/S%9Te\,lx"]9|ZWݻZ-]=ԭbk{曎QHlrE^U?NtU N+!B6?inl‡[&I$A*=뎟1 Ԋ}j,-_KIo="wJT2Cl3h_wBFP`40f#?h՞E>vA*–'R-*PPR/:`Q:3` M00R1U-ޒڠ6Y4'EH55 tZ/i i=ZiXYe#\ C:oF'i,DJG lTD!yS!!sJ JzȔclhZz|Mdj`X.\VECBp bm~\t3P$` AT*@*y] Nʫ/t^K #Pi|[VD"$#2:ITy]p7~ty."w\G`E8 谭|[8T//a1"̬;MmAR^(>ume *3@I{sP,y0,, gm\Qv^6"fID7()5Z.zQ 3"E!|5ܯԂG z9{^UHe(uhEѮy^_Uy[4@`Qg]@dL} mPO j-P dɦv4;5rF='L :w[ESכ|N`PHBtIƿ('5e"} uWHvګX^;#X MTa4@j!!*"k yJG 𨚸X֜QMu r(0lئsakTjk4Ӿ 9Cuʄ1 |kؔ-?;Hf)5,P:> xB.cym cfxlihxyS7ᖦv]fxjrKMC6x4y,)OZaJsY*p'Sv*T_ƀHYKwE wM-x _Nge᪈E ^Wc $D3(uLXjfum34\f 1­F$0nv?tQuIhKwBWH 1 3nPZ.%R30Kұd] P:нRR@F"a)Vȑ)wނo[ FY;YC)6j'\]:u ښsjIG]p]Ɔ鯨/Q IpfI\NДvgR0"lDie'cM,!RDN 𡹠=^[i1g ƅ!55~@YP! xmO"ݝ쀜ўӗ[H^[Z7&_+XNgY$d 4P&N7%6%.ݯdPmMd_t޾%o7{A]9XtC\b] "Ť HEiP;J@;`/H>ӈZ ^׀ੵpCAxtf/c Uʼc 7jQaTnv\2Lm٢l:] nMѳDJfjztӵ+`I@jt pkҡܻr Q+H iԈ:*d m&zŬ55Ms_ HC fF;lgQҔX*hʏFaAKsEG?"Y)K |no^<0FHW58->5]4cPXD=[fBi_!n!I=ͳ|mz6٨4!,iHDt%7qU8ޡ`D)z%7.s7tM Mhࡪ5lDq'/#mCoLK]@L.`@sktvvL?Q.z;Hs0O$F TQ9^/h~욦$Am l\zA}ԅ1yb pWlM'o_I54|%,q_A0-ek ]JOכ>#KUY \ޏ.?_M;R% esRdi^gNz#lG1`k'C)iS5&&sGsTEدv*'x͠#U#V]wEjD9挑ʓQ_108w .Y (^cTdëu5Po\WD6%$H|S`Ēոb=5תꓞ2SG>t3?I#AsbMl^s@an#lXV'd(8M\0D$5{'%_[˴XI9s=DHMY:tS(WԃD8ȋp#*`gjT#f"B;zU{6l_k +\9` u\TC#xFt j~0:jQ Ci8QxÚ`dl6k.0!V%6ܟ͟=GAˈ 9ŞY(hm`#"FclE .MڝQ#ʽ 5eՓrK\WkݩA?fs:\yHawo 1lvܐ/@`cH4y~}7_T;>)iV3NEn7%bbA`+¬hɢ3x jA@;,Zc)*Yb]Sʢ <谷OKQ(uZ  эTzzdFM8<6Nƿq{_>MB4q`QWpW*r?̢G6Ό7y8gBߊt ~:0{)4G%b%;eV.=j]tԐ2>f@ f{FPFV=Or/︠D-sӷ50Hdc:ҙPw1'!71_3Jv$\wnXg$%5Z㯗*n9eAA`&Iگ̈B*ڛn&b],@䤻 NR:I@y‹\jbְބ?np4T%맦&0U7*LN{jԧ!Lphu BAgQ YSap èX/3H*~okƣnō!8Du's|V<_:v?|Eݼnw "_bKGDC pHYs  d_tIME / ҇/IDAThY[pevg~Ռ$#ɲ$!flx\f6J.U[}ۭ*<.&`+c`6&YPd$[ь= MW_Xe?@RM?BvB~J<}mn{oxf [www 4My^$/YU0vg݁@ŢG wkd2H[[,j(B$b޽;vLi裤(3ҨR{Oggj5֍7ܲmbI`Xr|>A( RuÆ NN#;==[!`l dfshkC F`ll ^& <ϣ\.8%455Y~] G+Cػ @BD~^$0t:i*t: ]_\$i(r|~MV82>>.ۗ!  , ի n<"8 J,) pp:jfs`08:66{9A(|R*6]+T*AuB!,.. b1>(hiiq <k[7K/tƾT*;wMM cH$Ȳ ׋ .MzaZ 95Dغxf~Ӫ>}wI c8{Q!ȑ#EN6m$IDOWbFYggs.qZfO8q"J_:IZ Ԋޞ-+KC``C0xW)lF{{*?j5 XFtL9Ec466vaii)T(uťiZ|h6D.0]GP@_ojV+!Bss Ng4o2ee'ꫯUf0puĚ[cAӸ6>2b2Djv LMMMv; dryg]ՙى`(74O"W-533 jcVѹ@A6E:FXDGG^/N'p8`4!Uj  1u]GGX$I0L8N)Տ?~*WBiM#!έ0z$ n @@C<G8<8C6E]]n7VtfP(m0ksiժl&X-ϋnF X&kd2phjjZ}s"cff;w6%"w)54x< k&1%1PJM˥D";I\6B2ܜ{E(qxq=`P( N1ۍ.fqIQՃHYݪBu躞M$+kB N !nc"غu+z{{ EQ0f;{z` 2JҒb)i d2'Z*QV*+gHP lb*8 ]u xox(q?'{v b@4H$D]s G($Ǘ!@_g'(%x HEQVEQ0;;L&]JP0d2 A I6::z…ᣋK5ρC}d2VQ$fș溹WЖ͛a6r܌P(Ip#HfVj燆p'N#2;s[ 4U p{&18vj5$ 5EiWyicO<\aZj|R(B2G:;;{irrϟt9 odJNjBiI7hD1)0L0HӫB.l;3Ξ=~if@ȩ*c?<3?cnJ͝IdLFu X gu0ʲtrGGŖV.9և!.:EQ˗)ł^^qn-n{u"뺎l6x=tS&tn^fKTkPTN:b4 v_KKlhtֶI}8\?թcO?}4LaM㶃㶙c |T( ].\ɲ@)!XYYa###?| ̂֝O=ȿϯ?LSP}}W**o>(dz߃wap8fJ>2 " `? 3(OO D\./;w}.I_w϶q>=uۮ]F$I",B[btL&L&;ydk{?oJ?{~=6(˲L:[nyϺ\.it~~~~7| Lzm9(SgΜ=$=ve2222r/^ԿRS` y|>&&.ruv3`!ǁ.Ykɵ.R+ʲ\uf-z}F.]١bry0X.B_/sSSS)jd2SiZ<ҥKw$FUUÇ Ck_Vt]7Q4'74MUO<<^υL&L&N$2gzh%4Ņh4Lo<ټy3{9< kzkIENDB`live-clone-1.5.1/img/jumping-gnu-64x64.png000066400000000000000000000315721356647605500201170ustar00rootroot00000000000000PNG  IHDR@@iqzTXtRaw profile type exifxśk8c b9x3;˟R%Uw9WYLEF?Anrw*O9_]C:w_o_^|yo~|뮌:{ F9P usi;}\V^cbpaE/~t b}|^~׏_lw/6z_3 "~1Cv{guv{7ي;Wž*_[xlpo%aFKaL|5Zov<= y>/ zlź,C߼ 4}7Ox06خ~.ѓ[y_n/&މȇS7p^ZpD"i !p}'1RLK)Tғjj9;s¨VbK*ZIXy>Ts->ָiҍO7Z={O g#ζ"ֽʫg6wyۗ^~s5zM}x%$gx,y|v@R|s|Ho.oOsrsN{=WkYE elz w{ Ԥs{ך68[+,}1ta 0aW^^r_*pu.q%WGOvWYMu/N tǜ#W}pUτ(E&)NjY5j94pvd Y 1G~2sϫ{0ݜ$c>o2Gbh5!Շ8l+9U(9Ff.Yf3k1qh|fcv-DނҵXvI).ɾqlf'VSrAF N)5ŔdF>vɸ&+%WTWS9%ҍUum~]yD,SJl3[cv%!C>e'GoWLY!CV$-,ksTnp@ 6֟vm'qt} S-W)n|w+ ;5Ht3Ru/g"R#c7 rχ{GV*r~뾉xl~F-T@Z[N$;aGwr?0ahe֓,7Dlӂ+y[v |{)NDHP}FA 1n @ \ĥ4inBurOXk13g,C h@p@2[.jx[mlE[ ,%HMw"-feg3.Ijiӳ J-$)Kq Yc+.r>RX" qaqʎ ukprE[J'&H=mq?񬜽S}'⎖f]1c~(Gw\o7Ivu,x qL2=BxTZ)Tgj?Ee'o M"Fqg^⿟¿ǹ]J['"F4PyT+ٵ+`C|#`>Y64 9Er񢨔) ZUox\d`ڌXN-o!3Z!"I1x*$\a>cKFkUA(TC/'{5hW0LwA 6@B3h[hk1[wj fJD`T5o^W&5/GQaPDm В"t\ѐĥ2 $[0{f{ˊfX0\ʌK8A.uG髖^5)=~wRޝFr#ЏR։~:UB X\P).PoXF^]zIE [eZm[&O $)ڥa!)EIK*M%ׄ pcFg(8Նa߄] >!uEHT'{WH('0E,c-CY7ᯙ0zD? ~XlYQľVW>1i#idFUY5R?9'ӣF\ON\c@÷gFNAW,vVok@4@erpRdPO05OQ"xZ(ADB2!ga$aWWʢny}JEl&l|`!t R8QFZ2ݻyUdLj!D!>y\(+ o ̫gJUCV,Q tY`ڢbާ,'2\@W!v`H#=":rDrB R"x!9K#U6NѿBæk]+MSU*¢P'X!6^1Z xBqN'.ԏ%dɠSJT] QtK><{_< %[DrG `$/͐(x\Ɋ`)$h2qA[G@%,WCI@RDr(l"Av0 4ZEؙ'{֭<D %OF{wE!4d|E >SɄ?YQV2\ B%A"VM񗩬QE#yQ)Md]PY6Fxt2,W>hM75fڥ' 3"ޜgġ10jbͧ߼إ>ά0EPMRިQ*锖Ka L\4pxrP YJgV:"tI"cFn5Y4ZM2 i$GM{]ԇЎCyoiwji>BrV.tD$%֦UYuQL(# Aޤ//bsԥ)']|cc6=\7B/&\BedwBÛu5zKtwWsKho )/>szF0MY侤2W{yDEU"{6]z/盺z09%,8w1TRLUB_ezF@iBLqb$)8GT E&s\S䍨vT/& N@DH*; Q3 R2REo[7I-!ʩ\T7l@JHcT]z1|J$B wKCHVe|%0]qZFǔwR - d$){!SR?u*QeKx{$Jꑓ,{T'?ۅ=~W=0$5&”ˀ z=*ܧ1i2@%,ANc{<^TDLar:8]v^:Eiq_;?M8ְRt`QSKIP@,(Gx7T J[CP i> RB|R1f~iY?}&jX7d 0 ׄ2$ CIrJBSTEBc/dI1bλJ:f@^}|َh lQM2ZDϤB?}OHle] 7 up3j6f 3g"Es lR!;]юA .J vMat:.XNVi8%[sF6dI=v6G6 eM kLbGzG^QH*|S $EH ([EwPKFL Gvx=6SS$i r#!&^% zNiҸQQ峃s<ZOn;=9 իGFpQºd I+nh#ޑ:{h .DyL\Zĉg]h;aER>^m+5娷PDb nx9+( #rﻥȄe4JSI"N66Àč) [M2 8q6%/RPJܧ]^²ٿz0xD͸ *Xn_P'RJCU)"<@ahO$TTe} N\ӓ@%WFMGkgQӺbTKh R<5 V5=U'%|VaXw>sVWXծZצ^ecSY\͌gڒ9 P If$ZljmE -NnR@#'`xLx qUuFfqg$wM;=Gj)N| phWmJY('gS>o[=Z?rL+b"[ ʆ=5KK9""Cr#QiҥA]A~ZFRRsJgys0AxEѣѴbV:9m{%W?ngwnװ6 Ga3*6i$!kxCHԍF)|ҽug$ue`"s&.4Ȥw& rF(HD!&0L'IHSTjv`}H>O9WߠGC}E?]Pu,70mz}wM|42[wb[6).T2 T> L{NBWU,yM\c\Buԃj !5Q7RH1! M$$ D!d(*jX1?@ȏ@F6oCOkjn|ۺPYzgܛӖڱP.[m,BEmteN/l ^";fmd;,r#@D9UiO>֩!EuYm i\ö]Hr5/޿oT\r`HS?| ![0)Sְh e F͗* 9c?tGCAzļDS:g2͏gI9@ۃz8t;Ft_bq'v4-cCap|{%פR]R]~1|@m5T[Sd?١G(DaSP4c'K߹ u+DLÎlK }+-1mӔAJ(Kv;uF"[ ͏:>bSiP|ԽyXӿj}$uAG)"2r5[D'x=>P\:5V[ 6gQ^('Ȝ6)BumN 1UsFڨroZ'wKyk^8h=Qgrl=B; ޳M3pshdTԓ9ܤxg.z̧H[5=:5iSL B H`( [ ;IiI % ف˷ͧI;xe)4U\նۅ3,UB| u=L{|:C[3.uS|V=I?Pau'S1>GS|F qS;Y\wheۢfF}GOd>ߘ@Z- I LBb9bcV|_jQa?OA蘆Gݻ~c:9oVot}~a>l}SA`;c[߿g(!8tu,5@||rI:HVev AsKֈ&Ok"[Ml'mD輦.yF6 VNyA[:V認{R]8/ pT&ZznBB~*zHM;Bw;#g<̓7.nor||)S[WW<}OӄٳDQ#e"Q -;v|18nNIc,bY}䄕~`zBXtRFWWWwٳᜰҴNPzx5mڴ9/ ]\\m۪om0-Gu]]1uHÇDJJ 23*..`GX//94M\+;v,AQUVVqķ<)ojTӽɲ,HwucGիWW,[|Eʕ+1n\\`U}2HwvŶmP(m[MQ@Pא$( 8 s:88PnYu29vΜ |H dee 9Z- EeMm 00'6/\X{nO$!ˡ bA[k+֬YkY|9$.jPPWbܸq˃P(3P$3/]"h.r٠Al$ԝ;1Xlm,R)ƍaf*jGDDҥK_?Npŗ_ Z3ɣ6:u #G@ףEEx㍕jprr0(,,DJJJmEͷ. 5˟a``X6^T}wAXXcbFA@@WTT(nii9P=;bYDA@R!AX[[ >H$P(FCCCV!a6qE ?7annnPTc*o47kʞ_{-ǎ$y1hh !** bhDYY«/_۷o Sw8qҶ9s8>5M ÌzGnق@@GAAA())A`` ꫐d(++Cbb"q%I(//iN7o\TIIQfR; eev-\ǣ7mKxxyA"괶pssNCHH{{{pHXgd w\*ϸx75$MǛvMHn.Kz* 'ODRRa-I4i.]i=VFFb]J C )SG>QX+(@˵k;gN6~& H0yd~nDDܝ˅Hp8A- g~7w쯿A@oL/Gڵuwg,+6vuavP "#.HQQn߆#F[q+BCC;;;DGGd2\= P]D .{ܘglfM9 43 `A?bHJr'O=1z>dWP]]c=5ikK_fMZ .Yap`YvR/5x /e]1c Ja2Fee?mpuuСCɯ vHF0pe(X\~hff,<40|8@ U wwwHRӶpMBRAiy#::c3fK$ۑpZu_ u{ݕ]]pR5ZEFmmFIi,>20d:t'NİazoM;s|g^z茌#M65]Ҧ,]J]p(=y$2 2 êj6115,0lWW{Qv֭6Çza7j ðlbb"[UUPݖ666VL5g+*%$ n݂X, {SS!HxQlm&ttt؈ä"R<aaaرcƌ hj:xnd%Ř5k|}}! QPPG04PT6 0 @z}As?wvvtp@1_ߧlXv폶`[^((.. 8L[رnm'VC:iiJ0J/\^~b999z: ?xa,xyytJ%:;;pT*`}hX,IZ8q4 VXaK 8;{J 9{ 86[,) >>rdddǏe.o)O?Źs00 +WpķիWf[6R]]MK?Ý1LyràSdMQ}߭Fٸk:vrAmIO쌂X( j_&XR a6####wдiVmMMn+s Eݭ[LK1pyv}e$.^|CIDl [<pOO뵶⃍b^lEQ`ر $^^ʲEDD{*wDFF 0m-J.ܹ?gg'wch)ρohnnv,KsIr#RrrlP-[x$fg|pR/bJ[;?rmۆKa„ Sͨvvvݏ N7Hgb=2$TR:MSh4J[nP"sjjjӃEAԩS:t(m|:u +V#_ 6 iiii* 4M#))@SU7o䗌Vڢ"cd~:xouwwO2/?;/zgϞE}}=*8σ/il߾ g-s48t}[UӵiFh +r̝;G Z.V$opq__fXqx/wص+[TNt20 sNbʔ)0|---vJPxd aʎ;V&DxjDo\q=$UVaΝվ~~y\+0hjvIIIx'a-txN)())Sb[,njj{`/0.CH4ɤtR%KMV+ucZmtL戎8Az3@NJŵein>-336|Gv^{;ʆ [n <<<~r|XEvvvKXxX#xb櫯߰ 8$䈟߉uOPm@DDɞ={i(>nܸ{.F:M=5%^$A|>__[[$eaa Pz#M4My,_ I, v8t'0kbn@FUTJdB0=&f+,Òn!!9dBC>9 0HIIa._̙]<{ OkʮsV+u<'?%%6R۽{uZNmm.֮%VIIIر㋕׾%c~,mm&SNw$W<54`߾}P*x;:~wrǖNF`Ĉ `Y===w翃 *7j"Ob>_s2c&8=+| BGQjq8Wtv srr`ef$ ;>zhXƍtxxxzj1.'Ƕ~:Ǽ;**D#Ӄ='I4.&KMNO۷!HA&;s^^ޓmwp ٳga0YMs̞]jYYN2 4n޼g9*=c׮]eYf޽}&fXC111o}mQEQ6˗/gN6 je]Tn޼ ?r?Hl]]ǁ]n9!""]]04M!$ɹCfs77k0t׻{ nH,,,Iǟi"##jup!j6yORSSXVlX. X -Fo>;vXWWWr kjr8EkkkxEB}Ab/(˗qqc96mQKpR}U]NIENDB`live-clone-1.5.1/img/jumping-gnu.png000066400000000000000000001221751356647605500173260ustar00rootroot00000000000000PNG  IHDR=Md pHYs  d_tIME %$R IDATx\ʊmQCoT2M W&(Uf-yfwg7;+3F+jODcmp'4Q7@ u%t|$u'wB~|<|w~Nroѧ~ BPH|^ BPP(  BPP(  BPP(  BPP(  BPP(  BPHP( BPHP( BPHP( BPHP( BPHP( BP(T$( BEBP(T$( BEBP(T$( BEBP(T$( $K@PHX"H*$$mVV&$$z O?^ 0 8{yI͗|7';O.Q"++sRR"APư8TTi0~Rk*&T$(j0o$S`֭"j]PP(qNwTU0z}ay$ȖBVզ"APe>3Y<c^XVw]|XJKKNwL$g OEB: ũ]*Ʒrrrxc`0 gΜR;vV mskv!55-絴ر⽟R@uu5UPP(NwTUTx} ,SUUݻ+r|F*T$(J`Gޱ$F:^`BS-2hvqbxbX$$h4455!--s{ggZno$(J ;q0u$LOsNKNu00Mw㶌 BznB s3;g뉊Bcpp;Ͷ>Dd| ,Z Ô 浥`L,_ n˲ eUTŨGHP(oq8yѴ׮9.^N}d JAA/σJ)3Ph4ZtGEBC TH̐Hl\Q2)?EHnCn>,`z, ?IPPyJ tWh-δTm+ 5AEB~ŜI aެYF#+ q7 EC}y9ǫ.T$([-- Omy@c\ .pŤT*E~O&$LMk+I)him ZeYNEd ;:h e|asO:-BD 7kng`h4~J |>.~nYlZ FCN1-P"ۗ.||-B|p718w.Y#rpɲ.ݰ91/lk"$a}@HP(ʊ|&"{,9X޹ HH0,nUX,F[JUy=XRDz}hv9'2.}ka Vq_n)_Px[x[߽hQs4Νo'0 nl۬֗yDl[J$&K a t =dgT$HP(vg &LH_l("XQ? ?\uP*o[z5;P̅J쎎vZe%3f gjkk޿\tRW-?EH9w.N^4-sqn>cW-޿u9"sҞNԒPnNڥ3vI)`JJfu:56z%"Tj7 齸cIXHOzoP"Aݻw;l-PڊKW@P"=]'|=fB \` H.'V`Gn:QU 8pMJ?{.n"W&ýL_>lV+؈?56 nm.P*O)ʆzOϳdSAS^rHAT/$( aAzf qB::`0n%3p1<9nbppl.'ZN$dfef :1@;  jIP(Df ӗ0Y<3<_RSF[ ŕE0"N`bA}@HVZV*sl֬ ~$>"--o -h4Ҽw'c|Q9W9w&={ \>J3SB:shFdHԒP<-իVbx"^`_B)v{/4]8v(dD53^f/qZ{HKKsś쩧qss3.^"Fs{%Z[闂2ׂ(((k hfpF͈JKKy|gxs˼zZZ n} Ż;v /\KtJ-!FӦM=\ *8nE77B*FUվO;RV˖-T^;VWaZj,bPL* bPP;~G_/y7'&"m4z3\n-SHabg[.+ii)8tfME'LfA缙! #%%s傌 ǜ°`z:$q_@׮]}1n^( NF빑:XjIPE~t96ַvܶL]]X/OKƦ͛8$(yNN8l=aF ӊ?#% \HZw{3VBEǸEpg4M=46m޼W 97Y;im޺9rg҃bҼ(z{sx;lg1I<~X)T$(zMվO@Z1h]`x㍽H_y%4:ЃrPj*^E4H1{NvFnO Ɛ0F ≸a!X# gD:QUi){`iRn.fd%J9rqG {ᆁ4&A- JasO:Io앧~ex컛9Z$,MsgDL f^|EA=O~j9JT$(޾t؆@]EY3gr2#--*զ^39vڽH DY6gyjcR1FyBP(,\7f>w9h%g$4P-NLWZv6'p!c[:J`fsq3^Tbdd,@Qѳ# (Z[ q9>w-鳯od1 VB_" )j"9yR ʹ`@~~>gwL&k׮ueSKq1޶hāy)-ec1[~='իx.[ >q8Y[+Vm%u- '8V!*ɼ] =0!7e_j 4Y8%Ov2?zNNZWVVV{0l6q3 HGESVY%_?!`ݢ1&I,@x>֮^I@sNvnXom̦Dapz *U1PTTTjα,24pM"Iqo.~B%avrvO-S<?٬wn.uZ~saI> \HA`F,!#crngYyyJUwHYjK7%"3$A=89s&П=T*~G?Zڵ6MdJN~Y>Qؼ #0X`VZəF?נ dgx J`3cW\uBF;'dҠ^ .7o+:]PUBҡa{B&rZ~DK Fќx$/^qńmqw^αfFݺt-b|(5#!!,֗?},αsEv;**+$?\>?d:G+jsp|^Ts٩IE;^8窨XTeYxЯ8''T;n}qdܪ.4OʼnQJk*X}˧@}4xW(tE$8xN3=?{.0$ [& +ر7o HPb{ -/OKW)h>~w{8uT/&3-X"3ƔJER)T$(Ap޽6kauopp *_q9uvvb rǹC]WUb0c=H濠azTBU?W_V J088F~B]LuZX0x{?z6UX+0P*qgYV Jn]FkL0Lo|[kxgnt[,Dg r@$Iرc4B@ nW(vu㜻{ baUQL*e9B߳SM#_'جVܷqt^L.813'{i3yf``<$a-,RTXNKZ9|Y|*ʧH477cNo^*$瓟WU7!H߰,P$0%%(..Q<4裀+Vaio؜Nuu5~$ɔ6cO FbDa`Ν(((t^{5HO:W8ť%B2H_0{ެYx~ DBBr 9`Y,ˎ9SC}yˉ) dggC.Gtދ#?b֭"+"A #o,v{/Vhn  *PLZsoc-NoW^f aThkL`?I2GҧE4779j'anAwqbbPϥ;h!I_޳gonnR@s\pM[( 5}z}P-GYٶ\joˑr βmh%A[. BfG/`0 ??zIKKA{qdgeyj$I#bnU?[ UUUؽ~]gii)(/Z *hv7yfay"uuGG,Z[,4nh dgwD`0oBT+(.`ysMh>|EsҲp rAjظeeۈRGm0hoNf MۼyKVS(]@JmmPYY e0嬨po< JM&x7ȗܶqlnӝ?T;V={ss35rrrJ-`(NHPɕ0C"W L s.;"R>}sp\|dR)9ǫ($jo`ĪPPxl\Q ց _"{jbe12OV$W&N8kݻz4 *++O-&(q/T$(kb̙~Eh,x˷9{}P*cB(,zRZ"IBs95a+0xT=qb6_ o.~Bķz_iX%3e2nH<BHh`\} ,GNNybex(HP8>2+L!V? Wq\|вqoQttp[geeoCY6,m8U9!aRALV0a!T H 6oYOT$(DV.ȸ@*j]W7eQ Sc5tG1-y*yQ^AEE5`Yʼ嘖< % w7֬!.ƻ4QM}Hxb :O‹{Ξuys!x[f-zvwuq,XI0b]$0%%ёv[)>?q[AAjjjzv{/ qNgODEB`rC>HȔOw{3';s( PQQT[o!4?9UWz+_BQUJI6>Dr\,^q_7w= ǎ+vB=>Ι|ba^q/$7d`7*[K(T_^OlH,<ɌũnmmÔ =]m!Y\I.`ΝP>(,?Q{mrrrp6=Vn$&`76n?k˂i4[[[_q|Th4cnݻGإR,zXSii)A.&dff\,P6q{}Wt:ܶqWx4>,AUUrE$;Mh^~eQ1oLͶhNlx_̘Y{p"ߏ~,\{Xt܎K_"/^|{ܾ~̘. <%<U`+:\86kߏ?m6 @"aY^8wT:;.3k 55uDH*++yC \w9DŽg6PX/HF"5z,/LmLL IDATuu5S T$(02gE|3(!rۗ$Bb)֬:;0%JgM!˲ur|zTUYdA{ubG^{è fk赗,*++sG~kX0 D[0hMs EEE=aEj.rr|׮]R=8f7QB}p޶y&=b7.S`&㉔-VAm$4S!< |>ڂsXDI)h8O7G~vRGh~Dc)ZGRahMVVd/pl8w{W^cǸ.{ >FC=i&A|ѓnfV\a-_(+3a׌5SYTTDhc&s ͮ1v% 摚PY竫~gKXv h;y>ʉ/h4il.,wHUWznshi4C):QmǽF/Taw;s$Ơ@m^ŃkZ0̮Z)2՟5q]ැիH )H }{>V& Ͳ,Q O 3d-#KK^Q=I< Id<[s!XESQ1cMPM(R EssE4G>1 6ZZ*((@GG;A&u Qj5%^ڃ#5o)+6'5+;0 !^XRɵ|ژhT*RIH"A ;==gs޶9ւ;c竫߳EdDTUE[K$yG8c]5Dq׌kHB:o>=b˲13r]V{BEBяÍ5ot7j7x3gΜ}pv}˪AB|TUCBB`Y -b`D_qn߻q'd2K<8k-lʤRڥCEB!VKtn=t[,RCZZ z}XYb⚑ZpR{F ]@zX+ _X'1/XQKesJ&95مrbb9X&HPBދWt:Iq>G H;DKc#{f.j͵iEH;''ӯ3n< Y'F]i%%%Ϟ&`MV-w5VKlMIx{?s Jvo,duBx`(@^=tN`vaJ<n]t[ޚ'6n$ Sj($$P!"A o,Լ}ZHq!˕BVC?VcԒ2ò,23P^AEE5)\ca*ne[>m-|IqKk+q1g>| ΋P|+7`0"^GRu׻ɗ@TVVsxg65h} ~R> ||swiSc#6g!NN3;~D ET/Ie J4Z,ym8ɚhkk0a} u G{1{z.}j.v]!ڃDJ Bi!J+>b)EQTT eHP⭖9%!Iްl6A '}ܵS]k[UR]M6;RejYqB}*7~fO( cT\O999aoվ&HP-Xx)^_nǏs$wNGg{{Y[[aы%!MOsTXp7Rj^яSx=kdeewG8BńUOE<=v͚g8N> _^G8U|@׉hq4Ea 1kI& Lݻ8}LX^L*%j09TbaG u{ [%ϟPDYN̦wl*XoKB53bܫL"#3gzD SUKښ=^h |Ad0F&j( j/$̅P-GcQ_"ne| gϗP("ʗ+ O X7"L;_]M}ع3AjoSM9{~k=i$α@իV#>W/lU$XU\QcCxFjjj08HnEE{H.5ɗds׆aJ P%w-$(OVwÂRj%) l[&bZ^!ZZZxk[~[bHt]!˾(h"5> cXp ef-JVJsKQ3EE2xk3I@.dDTWWGjs8s H|-b޳'qόr޻ٳCjMwsuZϥVp,p *>q#qh07q9Qx@X$!0a9^{+b,&w@ld7*n]cA_7-U]MnMMMh4$w֮ZDbQQr7n$hfKجeO=9ZGE4 s=]ֿ9RGmHPGlg-)] ;>{= #iʕCzIUſ8/䙵k92q`(NeyOT!qAfG5qN_#F Mb!DERZy}1 ko$\p[ /q>0}:ZM"B.Z+'X*gb~"1NyeaeͿJU+A(FNöÅJkw䂯cFW=jjjj8AC}yx"oѰ~}{|7GʤRDz^oCa0QTRlTTTuE^/AEbsB8zx{?ƣ)hLZ1֭[9;^{] nv{/,ETdRN{bM$Y6C~cǂT?˲HO"?Dw)ckk%f޹ _s!|n7p$Su֘8_RYrj*bpp f L5,]nB v\eØL~]c}׮ _ Y~ L*.aJ MO=v *؊EVOαbզιw9&NN]DcџD͗Fީ u" Zkh;‚4R\(HB_bo򫭭Ô 9y23ӱI*hhn4Akkk+1Aj 9=̝16СV[k[Herb\>?mQwCe;.]a\_|{j[QSS(| e۶qz8Ɨ/&qMkX .?6x,''8I)̧p@g-%T ֮3X j})jVwhΝAgz8" I$SbƊȳgfdt7 ƘHVqHLOFLK5MFK6)+W }_%Z(NL $I(O,+jo.jjj#T$ƙ@_Iձ\|ߏO"IBMM z`((( 5Ϋ}jGjw @Bgd|Tq]R4o,V#o-k401"10\"(Sa#57Xfݹo<J555zPYY9d+B1ȹ_#3"MZJ{{RFl`W>2#l»TmLA[Q,Ԓ;qM;qb'6sV$6s/ZD<7w [GQeeېb$i-c3Gr9ˉTT'$8.J!7劍EzJ8G0s"tX,ٜc&IT$(޹=ķ>$Wڵbp"-NIr2؄ n 2}I'~᤺>;ST-*$w_abZq=S@wbH5ΞN2K>9f6GN(' 1 ZԟKoƄj帚1Wamvrv!i9:Iic9 Y`MO M"AY_-|Y:Οܷ$Λ\pf>EϺz43(J}lgȤRN.ͦQ=sFRHP~;̹4=ڐ 0lEq~t?lRͱs̙M6mѢڻia{))]M8%b"])sx=&cy@xgPQQZ932p|hm춴:0!)ddd̬XQG\: @GjڰbI2 R֕ Rյ34"cs9o&ɩT*Cv%g68{zz`Zw-Ar+ ݽ'=vA.8qrjr`D26jd29;:q ?y ]k"\-7-غqS1sfu- MLb  ! 2=DZXf(iDZw嚀 .3k׆B$ ÀaX۱gw1sއ jjE~䮮$6:Z[ak(G.s}ǯ44JCN|KNFzVi?!&-nňuH.`4eOFa:jmL*EU>CIN(0Lp 1½|b& 8xOy,w{. Zm=~3SW0H쑙39 eiqӟ:s3:R;D4ɗ0(ʐ }dUVrIB!HTt=Q#ܼw?yT IDAT+v{^4Qg7+>7?]vw̥ObL!$"Ns XRy/\rx"^oܨ]H$I#@$(aRT`61fS=(ރrjokw/xp"C{Hx3\>׺1t:͛PUIG`{}xj ?ᮤtcW;p۶ (((;Ĺ4('P(~رs' ?56BgG >7cBY=m +. >/FYٶnƆup "1wm~ax"Tbzܳ 555(eY$&r* @vjz$XʲA{ul=> Z-H4:;߳+9>=xmw'\555̗\tXĂPTŜ-&h4B>益87qLnd`o$byD(((FCNuHFrۯ0TbLO,lV+1iQkۅq%FsmA[z!P* 1M(HXQQ*O?O~87W_uN{x3 ٳӜoO?o}Ǟ>}Bƍί,$˂{u|^+׿_*:/^y͛7EZGO}()d}iݻw)H7n\ٚ#Ov<x= ͠~gn|trغ0 #,mp&Xj%"h4:S`0A&zB)yۯt~ okkE(tCs,-m`@~~>RS@?>O㮤ZZ9=KcOPhii,.7i+jgCV*OuO0]B/#8Iq?|H0ab-q# #***B" pc8Omve؈C!GSS4M jD^00LO WH.teB:N8&Ő$ z)عW(&~/>KS ZZGg-bGOۙƸ 7MXtPO, pc+:bҹᛛPʲ$Zc>8jkDho:OmŒewyb(T\W5< 555! (,\[(((aMIgمp`Gd Q(5I. jkk1ځET$bOrjltJجVWNmΝQl=@ٶmAhDUT*p!˻c4⍼c–;kmk۩d˨ *Qz6ԇq$6oZѠe^,,0--MMMQ?'wbxpuhHcaKQ]m c>|Qܵ5α.h,T$⌷ZZj>tw-|Bhf":QdgglҧT*31UquM!N(+cRHJYr9^[x(J9`xT$"^?uylno8PA@*Uq1lfH4!?6/PqS ˞zs,ݱL*"n:jڻ7nS5 {NT$",S{EF.1}GGp]Vk'W@_Tիm6:$Ŷqs9"&.yH~9+*z6^=GpۥfCsP EC?cm?KxrVwt^ !%7نzjID~G?N!xͨT!ݿ##Qj:;טP-%.Ah5:\Yf͂r\C-UZZ  %0oUo- #i`tEE I[7o?f0pLdI2L |y^  0臫m%UqvX_ RI|E/.1D"#c bx1]x[t-&H'nS[[Zt:TUUEd#;ciL"D07kR#JQX 'sՄr500Kr-#;w#ӥQl$1SPQ`sFhr"()M3Ԍz RK}舚U.$B1ɧc]]]꨻)}鲓Rv+5sfX s׸D,e8 a괩 qr2xdLC#6/_⼏B bq ҵX*!"|nZ6ė;$H0Y.')9W!eQ^ifF߶:|BYn.֬jFm9$"@U<^m۰قq3d&^IOMXa[%%%رs'cqqI|f ڃRTZt}ޢKD23+[E-M.oН+GLje.BÐ|}wTM(eqW(t2@1~;4=΄γ?ùommmTB- FIs>HmV+b3I2%*6nEOƄ #Y*mvw3ʊkX."RGHA e9᰽. ?ϔ8zZIKDܴٶ< ¸f g{P;fc9xr6E/_dTg\;ކ:lڼX6Y<1d%;93Dl t4o>Iq>q10fgAh_p[km֯_iSeQ[[-&TTT 33 JU!D+8!}QV ʼUgυt#n-@,_3%B7Ҍ X$H_^}gRt, tv3YП:-~v{o\$&K |>Ϟ0~_fLH0I< 6|{XL/s I4&Fݺ$ +n y1` @阜~ -8l6ػqtѧuvvhT*CD۩+J%÷#kk$JU}1vRFj4100ddezfҩՕmgǵk~\RnDp@tܵN$ هרHΞޞLނA#1wѴx0==d)*f`ha4Zpk5b^$k?:;FXا\%׬L$$L@L_͋"$>G"55MP*ABXN[$Uݤ?߿\>?>&a%d}XTT؈??DR@Fi_!vα^{tb>Dhk<r5)=,Ռ/~7 D?ۉF8T$eݹ-xs1sB%/Z{߿׮u%B'pFwP?IAA6oRk}?{?ˉom=yC֭n*C / Zv{/x r| 2\Zvbnar좢"@/A*"!Z #|UՇcΘofuwX:`V*XRl6&b/v"ܐB/ݾPo~jlPlvt\l vvvl6L7|aWLGGg6ygɵXB cGIiCBB@VgaE}HR=?3 iTbQ(DdD ,$aCnO?5v&)ܯ#-Bg6p9_^N"[tw䱆QPP͜{ASm;A$"Y-G${m  @X-Y40[DI$IxP&++Q7\{ꉍ\* KhR@sߍ *'|slٲe]}}NyHiLްL2Dqp׆D&ueeۈAj|>ZZZEgd|򚯋f q?7bR*&21S Hb߾cK 9gޟO 9yX΋j"|t ɒ ) uvr|FQ8 &'B_"+Z[TT;kӡ-TH8m! URl⸚I 󸑄nkW0dH@*B>#|8eIl%tLLcD`ސ򲬬WpB\x.dDSs eeB,$.4cÇ9 ׭A smpR5slɒ"*a_ьA%HKP,1q(5rs_.\HDxbFLkB@4A8t:2v{/: 0[D͡{,ԏ9 a^6|u3}^sowHQ@HGcuRjusbcn$}1IÃ͛Bs']'iΟ8~iLuN͍JU챳&5ş7q7Jv~e A*2롇2-Rn'YF;񿦥e_EudX)gboqwvva!y;4NGev1ط;D~`Q'0*o=hAaMxD-`wnj9NJ6Deg_X"\JvgHIYKPBi=~:fCn;tka֍CSVAnRώR@&p뱕$$~>y(w;wqߪbk25fSN2Y l[~Ed-xX}M"6M`->Xњ1nDͦMhٷgN\ekQ|]@)$av,IJd*M/0$^xy{ Hc3]vaeR b#)w2v6:ë’5Չd;\Nށdd2vA߭1"L)i(.~R- ǧDjJQkAQxVUs0qF(Y F߈ޏxNX;^[rpDr(ťiiL/_:rluV}?'i"!FoE]los6e߾AΆV[EEEQX'KN4D$%Mk̺Z$k~ƊҩKs{1A0G/# oX0_{FLAO#T'FfEJJ$ޙL}lG~j KPYYNapp`zQMMMxvcaD"LAy/* c kbݑR*OVY*E-8n6um'V_kk?zm~GȚC6n 8f0R*chhkܜ~=?~ юju6*++qyUU8nLܹ/ȢE ^RX3ҞH,"E6'eՁ]c]?wlo/N+V}sJUpdV_kDc=X%/;*T :yx51>L)i07JqT[OF`6KN*=.Pٵ ƢF p0g Z3q#cZ=(RU:b21y0GVh(SSQDAy\qӼ<9 p:yIռyX &hfm 8w[c-**B]]]\3|#LR\$#u/&JFӞYSN;} 199;sf@;U7g費z{+Ϯ3Sd?,k>#eg,xx>Bԑ:Q[[Wk3ѹH$FYw?P7~ݭg$3|=>XxWD+W_R,E"CY0+!"ϻftjT"Mi7*&̔ ܠ.oDr'+Xܩ(L[k>X,02Y sr$;б+~|I^ 'oȐPQQA_a2maf#=fZUXWLVE]j$1DGJj2'DEy9ñ=gJ8 Aho$dFsݙ-r*l6xň3zkx' VD"՗? UX3V<X´͚] 5WOB-qMp,#m;%5Eòe6 xޅO>9h1D`x6?{~~>"D IJ*Ջ#/3Ģ[VN0c< IDATq/,ы)`|y91dXx'"Uo"QPPKqxnJkh;$䁬LfX@:a'#Ъg"п72Y |}rsQ͛Ǽ"Uoq9 .Ewa;{eyǝ51O0'h@~Dpfx><{O?eM#7qWBt[lAfW˗SZlۙC ~|~δ2`NKq`ZM'1娟 t|JŜR* bӬx?nIȖϗyhe6/_̌us}Xz5e78NONF]]Vͬݞ@bb֊#SS}ЉRV6[z~ a4݉06.orsg wd)jͿ:p,$aZPdSdpw!౯~U|Âc.x-/F$D"B,so"FcT'Rmzaǭ wG'@xDjV͞3GpСKqyNzM81~>*R'r}f]E 7. @$Q$)ij4rȵkE ӧn6@Y&aGEE{ŊTwRR;--ݭ]hNJJr.vmrG;Kk׾tF }s&?)PD_OmpVY{b~Jfrrs5nш{kա܄R=VN<_~~`Yj&9-yk>gxs/ Ђx%S/a^gʼnsǰ&*$&1-7Vvޮ縨U)1t}0w 7W^b;Zh<}jj1\:V#R\^nd)f~]d;+q0s~m0+̍\$B BL ''NMab# BB妘[zZQ9޽{Ѹ6E< ~TRY VM[qBȂPV/`^hiA"uX-7ÙXnX|8.in0z}IUCy ݣ tm GxrOTW2Y rq^sHYO,:;:rbiCx$@5Dx=*_0)$ׯ_g[L!@1 $LaU,R`2py~TbVgLKhDccx%VX=7|6Ap{I-@ssK>P`]`>"빰pg ԃ{b ?M}HG"1+p}`Y:_\,b_4&N# /Ȝ^~尃 6k|,,@Jhh³BnnnM`6etvAP 77,`E:;;B6xA"E6 t5q:@ QH$Ɛ7bfcfnިxq,ˬ`1ILj 4`8vp:i4_| ߉fkU5~c{1E<CKR`ٰBqfNÎ?|4I:/)x 烽GGlE9\H@$K'jJ-$qny m 'rocVаSV֒z[%ADj׿ e$h.ERH-POu2ryF@+]REpqĪ\ w;U^C'v7a??+hh޴I 27y%n9"Lcz{!U(!gֻf"R9pnz(؏G]}=8RCddl3F[nxH3\(xFN z017!58zL+vn9"i4cփ0Q4Ek(+ۄӧ[޸xd,2H$∤IwL/ 3sVމV[cjnOwP,+)nsbtLSY1M# חg oO1sΞm e!E6ge Wabk4)i_ZԘX2qSI3uTӧA-}`1dd徏oH!D"%. W>Rju6n0&g +KVO&CǏ V[o ɚc:͝2RNŬ(RcFzpۇ_)Ij&7KH$̸yo`JT\tyXS=&|'65lsF#r|-x 旇gN,. wttҍFg)a|t$uTLN uo~nC23帓-Ɨ?"8f횘\+q9ܹs5jӘw̙>>iuш=fdqgPH)9V#y [3{K,=s\tr?]B{%qjtvvLر S9&2%D7Kay1^Ĭm`0DGmz,TQHMv]0]H$$%M>?_Jm",]T*}̄ZT(***hm=&$-**)RUW0]ױᰣlʬ%  "LTJ%djTUU-zǭsd)8.VsIbZ%EEEa5ɼNYc]?rn(R\ M￟(܆KjJr|dv1{w7.|PB<ݓhعSټN555QO3Ldf=ݨﮪCYJZZv䱧MsKKwd>c#6Ff}ɧ~0|tE p}]B~P>%A'MºyH!P͛yV41)'(l['*(5%Fczo1(){'CGXr͛߅M=*3H(AY٦_7qhllht=Rҟ 4 r G}ՔdC1T__4N+x ǎ%4izI$IX~`6+[,fT/1b9Ic0-˗G#T@DNkq}ͬ-w5w I$P(;f|t 3Nn񍥸gk|_'aƈ, 6s;sEʹTv5X"wC %ά- "uH$;DŪU%juX&ɛR_\ ^?"SXR;xbITo-,\M8r~Dxe7ORFz{hb]wIYT)xmXD>4yyJx᝶mhSk1۫QV7\ۃ'k%//O|ڵA9sW%Ƶ{]#NTDzv M)) F<({!1&w$ׯS]B@?jӧ[nKרF򻃃߼4S곁oZctD#]`dkyYd4*UZ%Y5oWϤȦFrguv8NЍerf M-dǖ,Y2~nS0O -Ͽt>0X 6--9wg[}TD: .Vh\_#%_ٳWE;|/.9"XR+r#/R?r7M0xޅ~9g{{[gE_.;sv;nv܅a \ٳsqwC]j͑. ?Џgkt AْR#^zi3\&GX:,˵$:ɑ%AzU7o?ގ)/0ϻ=Y.}KKO^O`$Puʔ:NׄNg@ lLd /쮩م[Cv稔JC`xӬ-7Jur22r/𼏿ߢSo Ӳn%qiinOi把 >RR$#ɞq M;xmZa}%BѹDǿԥKc=A"1ΐdc&̮;.R|60-hٷOw-~FDNM>]Вxe$D.8]RLz%EL&2)WnˬP;ԂKpy^q\ǝb T>pKW]]ݰXvӍ7ٰa\RQBC"PX[Ky60xcPqaRUU5S(~߈xL.TUU]Vdf_`Ma0p)IUUpI#둗q.sjX*4f3|#/Xi㚶v;ë}`(5%MMM vlֹfvOl3ļ~م;v[(Y:2h4Y9,]:@OjN55Qx#7w#dEH$ mmU}MPT.@{{$(gex2 6Ȧaz}IT=?A8?>ܞ]2etOB5oww7tGqO:%xMq5X[v64P"seewZ\J]](((p{rL&IMͮ5=>F( 7ǭs[,*.  91$PQUt/pƒ7n}F#*xgم/L78]`㥥F@%xn J^'K';DssY4ys8<ʛehhN婂8rmݳN;Ο=A/z]r񌤢"lV-}@ZYc .ǭƾ Y$ g `>Uw-1-( c B[P *4:ݔ ^Áv|60c-B9tlln8wFʪmb zw퉹n G" Ot BL (DЀOY}݇[ t:k4kd3}y2w!F!T AvbB"rb1 \Lju6pYi޿GY:&,rrf#-- 999og7I7T}tN':;;nPVZ}Ks߈PF Oq "/՟;V.wzzЀ+.i;Rp"<-Kv54 [hq@Qr&# 6l& b8/^s g8ֆ;:..>w0k@;ʯD(b=bCO#$P?ͷ br?G~~6f}@wOF# @fthH$"*=Vix|c),45ۡP(QV ͆h~^_ZƝD )*{TPfK=0̈́.mBaahRt2*++UG"ALt:fqEz[mDlBrkl~]pEBHDܡG&( !<*[ǭG(}D iiϳ&q}(/7!/Oy eeT(`4/**1_a2" i[%ǭ,=ᰃAPpS\ՊZP/j Wdq'x2c{V+ڂBǭŲ;aƂ]0p1rs5-;1M.݌$;s&n纻jaDMͮ.)yW"=-ee2#ᰣ[YUt2JK8<1Ɋ,I49fNٳ쒦L ;:rtQn2L/l.MHM2ZvL3nl6FTQxc_D &.")5[UՎA']yǰ+G.ٹ50h4[U9\ǵkm(XHDP& ΋` -nNnom6mۆ{nKKC˾}>C=Un:7^YPprBբٱ۪#bXlL7*]Gq<JR a(pMĊIzB>JdB/q~:U?-Yrb{ GAOK"RRS137GߋHpHN}?jȬ䃳goW?[wwZ G"Aq,>x1b3|ڳ9//6MoٶhO8 iF*2333w٩nj,G3f^wGtMM׮ MH"AqJ{g΄ԩՈ?+K#R-7t޿ގshniq@8,7: ƶIS&zʕY@cZ$xOe9숽O({TJ%TJL9x554Ҁ~\pLȢ/P ̙>?O>}TA~+H` {" b1eNϯqX$oMMMc`$kkHTTDÒa@>'g6p$|pl@KBVO KEpL:MwA$}O i4 5S}+^r E6-s677 iZq$P\xd \e|Ϲa&ϻ?&ڸHD|rwFuCm:V$%My -\jj[Q|$\:o>ネD)h7tzL4 #H$";MXxBχ >v:$m+蒥Vܬ?&qSe)A$v>ZKB~HJK ZaY+F7A?΋ٝo˨V,l6c^c?ЏYlyyWJEH$"9q`(ǿ^t2t:ݨĖj1irv[kh+)?/*n> |t+ko@OXs_l`Ϳ9 ,WӾ}{^ '. \b.)){o  wNgW[wwH ==M4.\Ӿ}X φ6YTH$"y__ծ^_2G ڨ~&efmcZblr\Y,7,/Ϙb<e5Eibxnbq777exrj < wteIyL:nkh@Νs*F#***|UUm=ׯy{ۖ-Y44G-@UUz3?tP||BwhP)puzЃׯ?n @kU/_~{|݆ ׯ_c?{:.1C<}>ڵktngc K aN=s NiRzlZIhoXgSSVڈ *++qܨ>;XVhoC1 b t_tdn{bկ~kXE2pأKqv N3f~:򰮍%(ZmH H$"455G Q!<6l9c5ӧE'ǵk׸{{/6lm۪#&bAHL}WP#v~윰clBy7uz2$G߰hZQg"{܋-^־Q8sygtz~?G󨯳":8/^HEEEyZQE}&ǭټC#Z'ގU?(bZ4(.indQ,}jDt2md0D^М]K8::Pa̳_@T>‡1*Zw6l(8&gюCZJ)i07g6lgE,S :k5bŲ7aF8s^/mɘ ټ]PvrdEHDx ==L+h4յ kW1:Mm8{XSϼm[5 ADkxFWHTg4̍{XmŮddٳGBU^I$"t9VO`0D't> Ee Dl:x* DkS(1Z 4j+܅^6<ڵqx?ϧ, >].XXBlE]WW?AV}?zp=}d@% xWiWbmb Ӂ{kkə3롬l 6[;$]]A)<16wp1M竪˥hrcb)iD?+[& ?h4cz]n( ڕnKzqRYQQ2 b͌4662exE71ADW]il69v.FqJ7$K'jΟN: X"Z.& rߤ&e7 #7W#j=8λH[^2ED,9@.@cc#LO+V;:,I$"jwؒ%KbGףl, SFss$ZI3>dzQ~ },%ct}^ `;h1naei߇]0wGss3Z[Z_4X,ǂWa4n 9f~$sȿ/#jqNggyصkt#HD숧lT@u"La8&1ƈHHD?>acn#G\RA}nb xʖh{>!8f|,X/2o c4 ĸ%))gV[`\ry;y;{z.k]P*>sLAk$"ܭbbgώ~V&KU_l,L-Ї &2Y;1.Y)&jS/_yD>SEEEVvqHVADY*ᆺ1.ZVZs03&P'zB шM"ڂq[D p'{NgdEHأ[Bpl,lO|rרG]k׮ lu6lȰȊ 1`# x ۙ&:{޽{# (8vp=+8 /A"AG΁\cIEX"8~c56ZAxMTᮮnAZ욵$|绢] :n G&̗"N˱17J6.0Pⶫ^FAI4GȊ C[. 4yم#QQQM0a~Eſ -ƼҩL^*+B[Pt̙ y;,vwM\~Eo&ǶEIDATmׯt#C ~nr97k]f]M7\YYrk7l 8hBwٳstoO?!K8,]`Y]`wT 3Yq\jeee/r,]:j -U'"ƴ`r7ĘMl߇իW bll`2MNd%nP*PV ̆JDQQQY VHD|Q^n8'P\\<"7 {Q^.,w~v]y]](/71?ʕX{^_R*$%M~D(ֹYMz} # R|)ihLP/B.@ss$[s655_ ~e1$dID|RUU-Hy8nϻN$uk$z7D3<`(**¶m$$I,TꏷH hj CBRPUU-9y`0 Y:YԊ8.V]kkkB !w1aijjc.qvZ/g7\-p8Xz5s٨KIrhSۇ?gMͮ5:rR}xwpغZBuH$"!B,tUVVkjva;qnjjR\\d*Y$1.- / zlź,C߼ 4}7Ox06خ~.ѓ[y_n/&މȇS7p^ZpD"i !p}'1RLK)Tғjj9;s¨VbK*ZIXy>Ts->ָiҍO7Z={O g#ζ"ֽʫg6wyۗ^~s5zM}x%$gx,y|v@R|s|Ho.oOsrsN{=WkYE elz w{ Ԥs{ך68[+,}1ta 0aW^^r_*pu.q%WGOvWYMu/N tǜ#W}pUτ(E&)NjY5j94pvd Y 1G~2sϫ{0ݜ$c>o2Gbh5!Շ8l+9U(9Ff.Yf3k1qh|fcv-DނҵXvI).ɾqlf'VSrAF N)5ŔdF>vɸ&+%WTWS9%ҍUum~]yD,SJl3[cv%!C>e'GoWLY!CV$-,ksTnp@ 6֟vm'qt} S-W)n|w+ ;5Ht3Ru/g"R#c7 rχ{GV*r~뾉xl~F-T@Z[N$;aGwr?0ahe֓,7Dlӂ+y[v |{)NDHP}FA 1n @ \ĥ4inBurOXk13g,C h@p@2[.jx[mlE[ ,%HMw"-feg3.Ijiӳ J-$)Kq Yc+.r>RX" qaqʎ ukprE[J'&H=mq?񬜽S}'⎖f]1c~(Gw\o7Ivu,x qL2=BxTZ)Tgj?Ee'o M"Fqg^⿟¿ǹ]J['"F4PyT+ٵ+`C|#`>Y64 9Er񢨔) ZUox\d`ڌXN-o!3Z!"I1x*$\a>cKFkUA(TC/'{5hW0LwA 6@B3h[hk1[wj fJD`T5o^W&5/GQaPDm В"t\ѐĥ2 $[0{f{ˊfX0\ʌK8A.uG髖^5)=~wRޝFr#ЏR։~:UB X\P).PoXF^]zIE [eZm[&O $)ڥa!)EIK*M%ׄ pcFg(8Նa߄] >!uEHT'{WH('0E,c-CY7ᯙ0zD? ~XlYQľVW>1i#idFUY5R?9'ӣF\ON\c@÷gFNAW,vVok@4@erpRdPO05OQ"xZ(ADB2!ga$aWWʢny}JEl&l|`!t R8QFZ2ݻyUdLj!D!>y\(+ o ̫gJUCV,Q tY`ڢbާ,'2\@W!v`H#=":rDrB R"x!9K#U6NѿBæk]+MSU*¢P'X!6^1Z xBqN'.ԏ%dɠSJT] QtK><{_< %[DrG `$/͐(x\Ɋ`)$h2qA[G@%,WCI@RDr(l"Av0 4ZEؙ'{֭<D %OF{wE!4d|E >SɄ?YQV2\ B%A"VM񗩬QE#yQ)Md]PY6Fxt2,W>hM75fڥ' 3"ޜgġ10jbͧ߼إ>ά0EPMRިQ*锖Ka L\4pxrP YJgV:"tI"cFn5Y4ZM2 i$GM{]ԇЎCyoiwji>BrV.tD$%֦UYuQL(# Aޤ//bsԥ)']|cc6=\7B/&\BedwBÛu5zKtwWsKho )/>szF0MY侤2W{yDEU"{6]z/盺z09%,8w1TRLUB_ezF@iBLqb$)8GT E&s\S䍨vT/& N@DH*; Q3 R2REo[7I-!ʩ\T7l@JHcT]z1|J$B wKCHVe|%0]qZFǔwR - d$){!SR?u*QeKx{$Jꑓ,{T'?ۅ=~W=0$5&”ˀ z=*ܧ1i2@%,ANc{<^TDLar:8]v^:Eiq_;?M8ְRt`QSKIP@,(Gx7T J[CP i> RB|R1f~iY?}&jX7d 0 ׄ2$ CIrJBSTEBc/dI1bλJ:f@^}|َh lQM2ZDϤB?}OHle] 7 up3j6f 3g"Es lR!;]юA .J vMat:.XNVi8%[sF6dI=v6G6 eM kLbGzG^QH*|S $EH ([EwPKFL Gvx=6SS$i r#!&^% zNiҸQQ峃s<ZOn;=9 իGFpQºd I+nh#ޑ:{h .DyL\Zĉg]h;aER>^m+5娷PDb nx9+( #rﻥȄe4JSI"N66Àč) [M2 8q6%/RPJܧ]^²ٿz0xD͸ *Xn_P'RJCU)"<@ahO$TTe} N\ӓ@%WFMGkgQӺbTKh R<5 V5=U'%|VaXw>sVWXծZצ^ecSY\͌gڒ9 P If$ZljmE -NnR@#'`xLx qUuFfqg$wM;=Gj)N| phWmJY('gS>o[=Z?rL+b"[ ʆ=5KK9""Cr#QiҥA]A~ZFRRsJgys0AxEѣѴbV:9m{%W?ngwnװ6 Ga3*6i$!kxCHԍF)|ҽug$ue`"s&.4Ȥw& rF(HD!&0L'IHSTjv`}H>O9WߠGC}E?]Pu,70mz}wM|42[wb[6).T2 T> L{NBWU,yM\c\Buԃj !5Q7RH1! M$$ D!d(*jX1?@ȏ@F6oCOkjn|ۺPYzgܛӖڱP.[m,BEmteN/l ^";fmd;,r#@D9UiO>֩!EuYm i\ö]Hr5/޿oT\r`HS?| ![0)Sְh e F͗* 9c?tGCAzļDS:g2͏gI9@ۃz8t;Ft_bq'v4-cCap|{%פR]R]~1|@m5T[Sd?١G(DaSP4c'K߹ u+DLÎlK }+-1mӔAJ(Kv;uF"[ ͏:>bSiP|ԽyXӿj}$uAG)"2r5[D'x=>P\:5V[ 6gQ^('Ȝ6)BumN 1UsFڨroZ'wKyk^8h=Qgrl=B; ޳M3pshdTԓ9ܤxg.z̧H[5=:5iSL B H`( [ ;IiI % ف˷ͧI;xe)4U\նۅ3,UB| u=L{|:C[3.uS|V=I?Pau'S1>GS|F qS;Y\wheۢfF}GOd>ߘ@Z- I LBb9bcV|_jQa?OA蘆Gݻ~c:9oVot}~a>l}SA`;c[߿g(!8tu,5@||rI:HVev AsKֈ&Ok"[Ml'mD輦.yF6 VNyA[:V認{R]8/ pT&ZznBB~*zHM;Bw;#g<̓7.nor||)S[WW<}OӄٳDQ#e"Q -;v|18nNIc,bY}䄕~`zBXtRFWWWwٳᜰҴNPzx5mڴ9/ ]\\m۪om0-Gu]]1uHÇDJJ 23*..`GX//94M\+;v,AQUVVqķ<)ojTӽɲ,HwucGիWW,[|Eʕ+1n\\`U}2HwvŶmP(m[MQ@Pא$( 8 s:88PnYu29vΜ |H dee 9Z- EeMm 00'6/\X{nO$!ˡ bA[k+֬YkY|9$.jPPWbܸq˃P(3P$3/]"h.r٠Al$ԝ;1Xlm,R)ƍaf*jGDDҥK_?Npŗ_ Z3ɣ6:u #G@ףEEx㍕jprr0(,,DJJJmEͷ. 5˟a``X6^T}wAXXcbFA@@WTT(nii9P=;bYDA@R!AX[[ >H$P(FCCCV!a6qE ?7annnPTc*o47kʞ_{-ǎ$y1hh !** bhDYY«/_۷o Sw8qҶ9s8>5M ÌzGnق@@GAAA())A`` ꫐d(++Cbb"q%I(//iN7o\TIIQfR; eev-\ǣ7mKxxyA"괶pssNCHH{{{pHXgd w\*ϸx75$MǛvMHn.Kz* 'ODRRa-I4i.]i=VFFb]J C )SG>QX+(@˵k;gN6~& H0yd~nDDܝ˅Hp8A- g~7w쯿A@oL/Gڵuwg,+6vuavP "#.HQQn߆#F[q+BCC;;;DGGd2\= P]D .{ܘglfM9 43 `A?bHJr'O=1z>dWP]]c=5ikK_fMZ .Yap`YvR/5x /e]1c Ja2Fee?mpuuСCɯ vHF0pe(X\~hff,<40|8@ U wwwHRӶpMBRAiy#::c3fK$ۑpZu_ u{ݕ]]pR5ZEFmmFIi,>20d:t'NİazoM;s|g^z茌#M65]Ҧ,]J]p(=y$2 2 êj6115,0lWW{Qv֭6Çza7j ðlbb"[UUPݖ666VL5g+*%$ n݂X, {SS!HxQlm&ttt؈ä"R<aaaرcƌ hj:xnd%Ř5k|}}! QPPG04PT6 0 @z}As?wvvtp@1_ߧlXv폶`[^((.. 8L[رnm'VC:iiJ0J/\^~b999z: ?xa,xyytJ%:;;pT*`}hX,IZ8q4 VXaK 8;{J 9{ 86[,) >>rdddǏe.o)O?Źs00 +WpķիWf[6R]]MK?Ý1LyràSdMQ}߭Fٸk:vrAmIO쌂X( j_&XR a6####wдiVmMMn+s Eݭ[LK1pyv}e$.^|CIDl [<pOO뵶⃍b^lEQ`ر $^^ʲEDD{*wDFF 0m-J.ܹ?gg'wch)ρohnnv,KsIr#RrrlP-[x$fg|pR/bJ[;?rmۆKa„ Sͨvvvݏ N7Hgb=2$TR:MSh4J[nP"sjjjӃEAԩS:t(m|:u +V#_ 6 iiii* 4M#))@SU7o䗌Vڢ"cd~:xouwwO2/?;/zgϞE}}=*8σ/il߾ g-s48t}[UӵiFh +r̝;G Z.V$opq__fXqx/wص+[TNt20 sNbʔ)0|---vJPxd aʎ;V&DxjDo\q=$UVaΝվ~~y\+0hjvIIIx'a-txN)())Sb[,njj{`/0.CH4ɤtR%KMV+ucZmtL戎8Az3@NJŵein>-336|Gv^{;ʆ [n <<<~r|XEvvvKXxX#xb櫯߰ 8$䈟߉uOPm@DDɞ={i(>nܸ{.F:M=5%^$A|>__[[$eaa Pz#M4My,_ I, v8t'0kbn@FUTJdB0=&f+,Òn!!9dBC>9 0HIIa._̙]<{ OkʮsV+u<'?%%6R۽{uZNmm.֮%VIIIر㋕׾%c~,mm&SNw$W<54`߾}P*x;:~wrǖNF`Ĉ `Y===w翃 *7j"Ob>_s2c&8=+| BGQjq8Wtv srr`ef$ ;>zhXƍtxxxzj1.'Ƕ~:Ǽ;**D#Ӄ='I4.&KMNO۷!HA&;s^^ޓmwp ٳga0YMs̞]jYYN2 4n޼g9*=c׮]eYf޽}&fXC111o}mQEQ6˗/gN6 je]Tn޼ ?r?Hl]]ǁ]n9!""]]04M!$ɹCfs77k0t׻{ nH,,,Iǟi"##jup!j6yORSSXVlX. X -Fo>;vXWWWr kjr8EkkkxEB}Ab/(˗qqc96mQKpR}U]NIENDB`live-clone-1.5.1/img/screen01.png000066400000000000000000004004211356647605500164770ustar00rootroot00000000000000PNG  IHDRwS1MsBIT|dtEXtSoftwaregnome-screenshot> IDATxw|ْPB((MEl`QTP)x *(X. XpUDEAEQQABIHOHf~lI6D<e3g洙=ӬV+6@ @ nd}^'(SdÇjf  ¡Cmv @ cNvMo+2޿6owy'-F@ @ ԑ^ ~l0`v@ @7#00Xl*JXhؓNhlv @ P:@̱@ DVv6lt:Fc0ŝ@ @ 6TU%99Ll6`6X,FXh(mF"?!@ Ajr) 4BBBAaZ),,$33,)*.st˜!@ ABUUN^O׮]r/2~~~N\\:ON1uxoߖ(AuXrTݜ97p"uI 5Naa!: .TUI=PB3riJKK^$I-R EK`Qk]p]3 -Ю@?7u3 y־CF_K:#B  BvNVݻ#Ik~ZMȲLLL ǎ#;'` ϷzbAPpYYL&$z@ 6?NYx5eZѐ$$1Ջ~#:W!5;tܙ#Gݾ};'N`ƌ JJJPUhW 񔔔q'͌L|t4#!lH~=\LŬ3%?gKQ{5La˞5g^/e^.ҳH,0 \b(o$k&n\ǧ?DZxҶfϟHת~Tz]~˴!Kffƨ%d'b$L)#6|,o ˴sdw8Sax7|G<ƶ Gϓ@ Nqq1p7 ATT᮴t2d+- D1T]=Nf3sOу7x̨Qy1cqu JKKjuw )D)46N}:e/B1H+_;^:Qt ;?_t7pʗ/GJ@$XKWRSEZKᗕ y,l(%X%q1lU;5y?79O'A:UԗŶsA&]dn}#'xfɍtsi篑&zޛDz~P bb楁}jݻYn'< /2=~;k׮SN<$ UU]eԷƛoIbb" .dŊX{mISTTĠA=z4}#G䢋.-o}꩷ ';l[@ ) 1(.0t:ӧIF?CU"Wi(>}.=;^hj"`xRm+ F<:&LğNAu;v^B_ J5JK(\gZ'tt:$a6T^^??<+Vo߾̛7<7cZ$#UԣiW&>>gy///z),Xի9sBؘzlٲ~QFO?Ѷm[9x <==)))!9) _OnaAF<=@ 47~xweW8?$|}\FҵehS];j?F;cYCdpRvyy̘,UFPSIk <{w=ȳhsOk<@ FEQ(..m_nn.= ?999,ZEEEt: Pu >3f(..FOs14Msz~7>Cf͚ȑ#ݻ7+WD4FQ@ĝ^'((m)R@ hHxEGj%$nm.\v};ڎ1⩵$[%OI()vT(Q]>߼+2ctWRr/z:QYlF].@ c$2Mp.ED@ /^^^x{{S(77|gV95,77///ESO߾}1͘L&J۷gc9s s!66Lǜ9sػwf];I0  }eȐ!dffֻJO@ H\2w1^?AaBRRzxHu;Fx$sHLJr=LZHF/ͺ=m@ySG+KVJ^ʿ_}.䂶x*W ڛFS]^)QsȔt 4"{< t.I BQ %99ٌfe6IJJ",,J-[[=iii溕KZZZ{Q @ si摚Jvv6?y3LDDD'z,yaK!@ B$e@jj*FoooF#`0Lb6$$$?: !@ ACe|1Mnn.gϞj$00`<=:N @ J$I#>DFF$IBzdDΗz@ Y0aGD@ !@ <@;@ @ 8N @  b2[@ @ Fta@ !@ <@;@ @ 8N @ @ !@ <@;@ @ 8N @ ]ļ.M@ @ 3dȐmkl@ @ Xp@ !@ <@;@ @ 8N @ @ !@ <@;@ @ 8N @ @ 8qZ)@ `i!ĝ@ h'N@$.䒖n@ fdϞ=o~'%',^qt|mh䢋."66E۱X<4~V.#c[rqfӧW/Z*5Yrt#mn+$e{ xzشbVfJ'={///ر#^^^ ⩜@ ڰX,|zc9sJKKX,2!xX /ߚ((A!̞}@ v0 ] qem6 .rl歷ޢ_~nGC꫎\r ={ 5-yy !%5 ;;ܼ ҹSdoihh(BdpxYĘ]sI)gvg9ei hfwVn.l#_BwPz^L/--(א~ TUʞZ{\%%$9Bfqqzꅢ(]@ UQqL(Izz=N`X0L`r*]ii)Fk#88&MȵS1d S煥OӦM8㩆ި'%9tl6geh?J$\)5:&kȪjȲJT, /Ef++zg'k%_~M(((̙3deeCv퐀61:Cjj*$&&ADDDKwA eYvVZVEAqT:_]vht ;wqgAG3hU*VӾڄ]MT c0b~߹Mbb` Mh.Yc#rfz"k?aCbpAqȩ:~Oabdu+O juՆ=8 eBO4mE9 UXHva!Bz|<~~~w^BBB(%-/^^^dggsq?@ ZXy1bieN^op$ǔ2ܧ;*ڄ[U6:nco&喚O? .ӓmb&ĩ"<</;~gْ $"<7~￯}&xآ?ɨ戈iVbQzi`&9Uuw\"Nد)eƒwSPZJ@i)RZRB`h(ݺv%!!t: ܙ . Ӛ,9qiii $88>}ͬ7iii۷X,Aٳ[$]Ad2qAN ulԪ,wNjsǬ+k εSoMX]t"=-O,@?iZlmLbQ:ۯС]4}tًpFF6{9Num}_uyQAU5lC9FP5f[= F_/Vcb6OY~=۶m5 Shh(F[oe̘1KGͷ~$mL|M֯_ϑ#Gj<6 '2sL ֠.bvQ)_~aȐ!*رc˵m4),,1O}ϳjӳRzhh(ǎ׷^m~7={k{ر|W*IAA|6l`ǎtٓ &p7ҳg[*^E裏6[f:d~&y+?x뭷klgc$ +ilܸ~JFy { /d„ \|nb/));VdժUu]ǻEAeggg{av];r3}t[kM]gܸq:u-}ҥ̛7|^kגXk= 4ѣGs7m]űmEWT2 ^Ms+n9>*qW$S1MjFw媫%fV }Dnn.O뇏:U_fC%Rӓi߶rC曈o~6T9{t؜Vr;U"\;W9!^uڣi.QWNͦ!xeRl6]Xaж-=Ϝ!( ^={EQQ~~~DDDM%$$PZZJxx<<*8W|=)))uΓLvxꩧ6mZ粯fe˖ /P\\\<]k2f^y:96|Si9)Ou233y饗x]W}\ZZK/ċ/HAAAYVǾ}xgׯ .dĉ1KzMƊ+\io֭[&|||2e9Oxqf͚ůZ}UVj* ?СC뜿ȑ#?TW,ˬZ;s|r-ZT__yf.:o ;;reUnUnj3شiSʲ2Z$Oիٶm[S7$''suV{syٺu+dL2mټy3&LhtY˹ k:=ʍ7Çk=VQ {eʔ) :۷7e3[ӧOwwqqqرYmkѹa޽?j1HT5k*9 7ѣGk}m۶w߱o>vjzb޽ەf͚F#GsN1tP ປz[nn.'N$z=z4]vu,))̙3ٳ_M6Y}}>ʕ+FW]uQQQuۻw:S;wdĉo,3vXƌȑ# '$$UU %%~͛7c,7`۶mL2ˋO>1cToٲe^gԩL4t:Դo͍k=:U 2Y9uIhHq(gڑWBC̚MPd|KSǗ_ٗ@i,w-ߟgd/;ƍ\7q}IۛP˵JJJk* nݺtR*󅅅F^1cyyy?aŊr;WfJnȑtڵROyGXl>ki{t֭уn:M֨rzs9'ǎR؍;ŋӿ*@.];v,K.<|'~pTL>M}駼Kx{{7̊nݺq)tacYx1niO>$׿{zzҭ[7uԩSYb;v_ϋ/X綼n;3qճGĉU~ƍҥK:QmҶm[ ļy8y$/fzv4M61m47@6nX hJJ <[Z׮]ҥKeY&$$QF1j(͛GVV|zuQh}Mu ꥗h3r:LJMRvkYe-"cU[]UiU~_SEˬk9Q{=.nRtEdd8UN#-,:uNfU^c?f )(oM+s8$٭fvkxXF=H:8d?;"e _Orm,uLMTDT]T Zx,+"IBBծIII  cx~um6:$QPPDFFBtt4{!'7<, ڄ_Ejj*m۶mv¹_W'G?׷m'{n6osGy-mɬ]NWk} ЧOMx6[n]vX6 6-O<)S0 m|ob'T=bԩS+ 4y|z?Qիk֬a̜9]v5昏V믿anaZҦO^xk{aÆ1lذZ]BSW[YiӦ8;u?y}Պ׼.K5ݩ[fu}u[qTb7 ?#9bwUeErPa=>es#gMdffpl&yֆPBCs`;ДvH>sJUsDUUּ_-5lڷkOtTMEUmN8IQr$Y DZڬ' $w@?|kE4N'p޵+}1~ڜV+e"ڣd=h#;9#ݯ%Eve6\eH8-}Z槹38\=.BvJdd$$QTTDf~>4:w"r)-)k׮z())&,,`4a+,,lū"-ĉu]Ĵ<}47ntK5kVs1`vii)V'6OUn_=\O333Y|y)œז:,X~rmڲe ?#Gl?#-Zsuʹv7OÇ'&&MЭY 333onz}ż.T|R1窾W *xbz}W췦i̟?ĠAظq#AAAunck :LT&+^C"36ѽ79S!_r^g'rW7v]x@&LQ$"q<=WM"6?cqG2Tm!]N- D*XRdNrJ2G᳭Oq>GRV d>X ^|^[L~ΟǓ ct7tK!՛ MPˊ"[]Wi^IF.`6ag4ϑ]9­tqj.ptpDFYlr4%|l6\eLv6{<233 C$D$BԿ?WȠ~޽;ݻw'((P>J;S[4|g&Ϙ1ٳ6lw9$Uz2|z[̙c5y=~v׮]5jTO@$7+ح oMI{tZZiii-ԚO>qێnfqwVvGf vۮ8|n0gƍEaa>%& o&cP{4 в<@3GYM0+RܹY tb,wT<0Zϖ o$npөc'BCܩ C]UW\͌W~ _o/'X$i-[-)FFrUnh7n=(:EMyWTOO/rsY7>@Hh(oZmc:M^ mԲE LĕuJٶN'c0$d[,aCq.nsneU\v+0iebi<ycZDXJhH`INK#"RF#YYY \7LNyyyRGin.)IIP\\LFFFk"&;ͥ5/mV!xnǏo(3f _|k۹@k桇rTڵ>/))q 60iҤV-6xKNNd5w#aVҽr-43>i$>-9Tq^އ~ȉ'HkWWL=jb4ݻ7'OńfŦPUMU=xCc(&aڿ+6ûSp u\B}3fؚ^֟ȿw>vN8q;oao`4x8]OA|5\Uά0S2*wʺO6q,}%}ydb222 '0 :Y):<<JIq1F*MQBCC$ ? t:xyyǑ#]Ѵs^sbUD?hРsZgmo2UU$dm8p`v}K,qK_z5NjsV<_iOAu]uUn1zh֮]djd}QM׶"uut>9s Vbxyyrb-*b7ӳWXd6odBk'KBW^9gn)Z:wu;!"NF??7q(ڶ;={p $ PC)-?=?^evk 1rs{1 pݵ<|F_<^}zAgDf I擒̠Yddf?/>6m1fL&zT/(_~E@?d}*M*)98/ʾ?t,$K*H"[?O{HN45d s4T4S6l@3f f1qرJi-̈́ O sgmT'N$663##;3~c2|pL=PPWJKKf@.1@d ]r}CE};ZU>uVp xѿR JUDB1\d`%ew>%sa߱ 6Gl\^M@KLt%O83BvDީ9 #ZnTV~i'&(0OԴt"#"Ӷm[xpY_f͜ATT4 ?" #6mH.1[p:xp\ B+7oBr%X+\"CB4E;t*ieAT4E@R54Is9E*h}3C98EM5R&<ȁÇ_?b!--Ll%"<ł$IUi_NguQ3<<z=ڵرciT\xkݩjdFW HP-ZĦM\b?O>nà E[d SNmtxq\~億pYnݺZ#TYq_]??k׮M.Jϟ?iwv[>""pE1bJgZoʕ++Ym 7I裏K*ͯa_/5jT3m)*K"dsҷo_پ}{5־O֗s [$9[#Z XXT? 5^?*qW-S4T]3Gx{Nat>iHav tIVr"@NMQY&hP:ξ?ZC7*Vt^#@ Dx\&^Naa>&Oя?ο7v/rϬXחԤb8_'QXheK"00p^_ξInVʉ;rZ,j$Ie;&EA uΛI4վ:hݢI]i}z^y3jyl3N49Þ'ݳ'}{`0BII -sitؑ*'zE!;;p_* :wgEvvvݹtQϯߢ.MQwUBPIյ״sz뭼; ,ӹ.iuiC}UlM7/rKIIaժUP^q-ɋot髯܉VZ-2N i]rkJJw>HqqhǏce$.#姟9fzy>$O]Nx#w~׆d"#,{=rqcǠi̚s?^k^ M~G4M,]"S&]MF[uHb&\iFs$^>VNI:4յLSɪ랄٭vĝS? IDAT: T=O=_Cbᯄ 3///>LFN~~Ջ6m I,kUu˩Sg/;lED"sj UEsm*rKR_5 c=ƺu(.. n߾A 4Or 7^xF=̨xkѣuѻwfwnMݻָt@*^{~~L4UVrZ>}Eꫯ+4%5۹f˖-\.6޽0b%\UFu_~AjE+)A2Æ78YŦCrޑhǗ7}ͦ0Kvw<2A~}> sg{w>іvm;&OGY"5=`B((,侇soۿ%IȎ"_@vEt3ݣh*u,]\RASK-8eŵz=%+2$#6keW\$at̛Z8q3gחK$&nt7o&--54LXVTUE/T͵*aw*!***rkTy̞=->WL8mY<^xFY3Y< N=1bFkn;vСClݺ(s1~p!gUJ&~OIa!f33fRj6UR)ORlL o]]Meggn8#G`Zց*Yt\ߵlt5RRtHSAE l~;tAeeVE0nz#4-a })ɘL& Lb_} ~ 1}GQ n$dDB*RE@xU.l((((rۅ+h  %$!μ,dHOl6߬K.\Op-k& ̋1L >?ŬYػw5kxWj:QaO-Mdd$vOέ2onʭ/UW9ؗmWWuŏ6{^RRܩ3_q~2tI\hSMIxꩧ(++;nlKWvYfÃaÆ1l0^xnO<Գ,<\wu2F\}_+K0iiiۺkslڴQF9-^ʂ t ;ұcGf͚Ņ xuk.nϕTZ&Pi@WQWOf?E֞,-, ] mt,֪_@)Sp骹64dee[>IrE{w(WjW5PPXr;+??3iۦ-|.NOcsMcLqS 8{.OV"4$W_^ҍRӓ)==.Y3z"%-%ej))-,Ӫ(J LRxFqiL;}rG%wcilA$IH|}:I.- r)'g%[jAذzUݮgSR}(ŅgϢBV*^Oxv:o11;]V+;w/o<<B@Ѡj+l\`0,2}*>c4Jbcc%#GAs{GRR` dժUͺmK/?lVGՠujwB &Lp VZU._9wVeڴin &&Çsa={*;ۤ8xiiiK,Awyooo^{5"##뮻}MUWueˋ^㑝WW#/awߍM7s``Ν؃rs,ܕ=PyxzRs\ٴ^^\:HN hJAL87q'1:m8G%={w?uJ$Kjj..b1_SkԤghSkXV¸et>&$w5#Y%JLfx=4y{z`OxzaOw䆻 wWm=.MFP`EE_Rl63b ,^&}o- EQԘL%L47WGX:o5="-7fR6Iv*uJyۥozDF9LisJWX>$Q_@DDgv={uL0e.m[Ng\NÃbN'&:JFCxxGtbccZjڵ+...{Rmɓ'Rvm5dL뮻XN>MX= qFrIW_}:<<__J^jӦMcٲe?~U)}3gNӪL}U˴{o%?{W^5ʳ^Ny̟?uWW}4ӡC[03g~p^mhԢ "%r&:֡ʀؾ}cw}K/T/KJHxx87ndNB$^yciƍst6j虙M:6`jUԴZBqVkvt!7# yV,7Ŕǯ?~MJJ7YUˬLJ}{݄TFFRrQM/JGߟѣGJ^{2rmj7E`;ɾÇjrIoߎNà ^NR*t:Z-NJ{ǎ:b={$::*;h.ڷo?Ozj;vӼ+Vp:O;tw}uJ"cǎ-7ҥK}=驧r}/&&L2\/~/RMf̘T5..ݻwdΜ9󪸖5t f`zu~8[cС7o.\-_5!Ut+V'x{B,0JZ/ I.!A &#_evgDu,y k: Ėl봩XmobzA ~8||* jl,|Ï}QV}O<7ӧo8V+>޾Z.dp>%} )c5vW5Ij|ܱ =*I] $//0>ח)lٽ_w 77FCn"57~$JRRSG)& oOOZ;:Unx_i*~ٳg;WdZy7k]T>ϷZO}_ʕ+9z(y 3g6SrrrEuW}T^WWWq9r 9/^dŊriӦr+;̝;Qy6nnn]eDp4*t:zaJ"''ܜ\ 1KZI1- C7TEXvm%=wlwSiv%w,e"B7z׽32A@G޿վ}\ᇸO0;b~'ïM}ic{@DJO'qֿ&v!DDp"oKxr%99w>ghFd6yx{{¦[#(0^w'`..d_K+/p|Ul[d_Ȳ-X,ù66*Z݃k9{4L&V#k@Av6L"ڶ%*2~1btZ-YYfeT\: %ގ$\SQttt^vɓk=mFF'N^,J޽{pwָ!!! k[~9ruQQQVA|Щґ#GʵQ~yj(̚5~|4oРAm۶s8bccYbEz3^pa߽m;￟ݻ;{48p`fW&,,7w婧K.ѣ^w||t}2zQ(Sz\ $'g- 0VKqq1%%%h4z<֙L&HIMG),,ǟtӫ222 !E}t l_vT:l 0!3{pef<ȩS?e6B#VJ}z"77//&Q-kuuV͛Nnn. .GJ¢Eݴ[q9SUkm݆lvWT|W,XTy׮] ruueܹNjgNʕ+({ѢEL4C(,v|1)O?uzOٞ5[,̙CnXd dgeժUN{YB\%K0i$;VΜ9ٳ2dgϞB۶mٸq#[vOT~~1uT6o\|䦛n*k̙3kft`gJv||qusAբѨmU5*dYb1c/ڌŐoeC'8zMq S뛝80{/GFura!҉(t:m&.DKf&򎝶bA`?d $4kQhm$Im˔3rpڴ |??O%o0jč׻2v $Kf_ҹ3 c79zh4UP*UHLH"b.Sɛ~7C; vWjy8Դ iF +lY:38z/ QՀBDZQbl˛JiBÓ֭:JxWEV10՜###;ͅLwDXn9LCFUfǏၻ{לAWWWkƍtL4(FŰahӦ >>>h4HKKcl޼m۶9WRTjt: FtsNĉ曉JEnn.NbÆ Y B7dkMt҅Sz_W};xwܾsά][97 IDATI&9uTyf6o8p Z^b!//ӧOsQ~glBaCm޼Z}6<<ᄏsdV:u*ov=<<7n\.ছnbT,XK/D~:t(z[nx{{;m6V\4 خ?oV歱vZ&NXe 7 I %%6mĮ]}l6m>~!,W>Ye֯_eӇhZjx$I߿u?3fFpY{܃Ĺ I%f:<41lC{]jc'IVɊjAS&3TŲ9լz,Ka=RBl@}ݻ7$LT;G%$vPV(.(>>H۳CoBii+J^}yEEo.7+"RaC|fLkp1͸`2ݳ }bAeͅcGW|G|}|Ⱦx;nNHHFo/?3vr'z]zgXX^bɖ[xa|I V,hyw2y޸:UOe Rtrss!Lvp T%&rss)..gϞt N+1{ƀP.-{UXT*%;wnЋQcvqFfϞ]8p)R*UVa[?)){UYح[fL6ͩħ5k8؇ .&l(jWvҫMj&yV̛7__ݴ͛;8q¹a;ʕƩj=0`oF|[ÆZtYuqWzzGu`7Y??滺b6JRլXz=r}mZ{f̙2gbwwJ%{kr.:IHHHp,,YLV\ԁ$|ױT F#%%&.d_u0냷F/#;zFc++])U3R--˥6-U ʝ \3_%UT {yOB}1xzb6,Vk%0R50ȕ$voۆG7>ϰ =3RwZ_o;cHKKϟ\D졃Rn7}u1ZKZZd!77,o;q-%&*8\dYIzF&{RIZz:Zc}ڽӦ^jZ#|y_U/+{lZ3O]JT*]AtKzF &{W JQ`ѠR*2(8bJ# ƵGѻ7n؀֡۞hqye__&!F+V^͂ n\ZUO?>7|sCdZj֭[Yt)ovСCy7С~2VZf8q"˖-qɊtڕ;vl2/_^e;+vQQQ>N7FשB@R9;^OaQe%/QWv5JP_TJ%=mB'_`+8H nnN=cTs}P(1c'Oo嫯bΝW|חaÆqm1dȐfWB2{l>c֮]ɓ'F_oOrJ,5P(x饗-wqqg`͚5[{VY']ve̘1nݺK~Zo\p׭[7"##(G cǎlݺ6l@LL 8j 6[oo5p#WWWϟC=ĪUXnm2f:u(ymժ6l`̘1NC|HIJeP(<36c f̘QiBȝwɝw @zz:qqq={ jCNw<]pܼڦ[iy{{##Ç9{,YYYL&z=^^^oY_rHHty܃fjS'==<, wwwZnM׮]Sj*}oj5L|}}hպƷCc]Λ-1ﬗޙ-we!z=zݵ/(0oƳadt\FrrH9©8 pѹfÓVm.1 !Kr ijWOzK_xfZ)** "88gi!鸐MZzE3<'Y&''JdBbZ=xQTzѬ`҃Cօ",++(" zY --1?0DqmotQ* oq)..ĉddg6(Flv ܞbp黣T*%w-V%**J $00!Ԃ^gϞٳ"jݝ}jj{9B'...ş$|>>twww..h5jJ%\+p*"_GeǠfY/d .v@"ϥ_G .;PÚ$'Pi![P{ESiq^[T.))܍9EAXX[zɸ8 }|8ĄFc2a1'/?1ZrJU4oEce%I£{QG`PwhWo>;v8`g*ߟtCB0ظi='LvcVˬ$I/ DVVaaa#48шjt-  [e2J%Fwww%&piF#qssԞNdV!e]b?>mC^n[߲ͫ& 8{6???[I\ nNo:`؛/бZaAŋdddp5 2.:ݥ$QXXT_AȲL~~iX鴎gJV&]wʗX'k28ըTh4;ڀmWYnE=3V_zܱuNsTklZho8ǎq `ZZtٻ==оx;9{o:\\\jW)Fm[e֮)NEFCXVd}36MIIE%RΧ 2amۣP@r>FC\{Gݷe$$I&\"Zw7o֭Mӑ$IzڵkϩSa֨:a20-  [{#Z!XrCE+:iNEMcަ95;ڶm>h0  #DPVNA}LIw9Uj5nsss9xQ*U-y~/B}/0S( 0r+[.WP'}̌i3 Oŋ( ՆU*AAA8qd6෧gKTAO? '6@nhFQV F.KDqqc(WWFYZvvx7ΥwNU+[Pw6uVLNSsV篿plѫEEEzV+ͲOAA5jvMt;+!;4ї:6ۭR|˭5r=6jAAAj=pqc4Vմk1[E֔(AZb=ͷGhQ\]]޽;ݻwo\J%TQZ' (,.3KU={}vC|*' BծO7j*yzzr1"""ZL$IUvV![lծ:- Pqo%Сqqqƒlp^^^xzzҡCJ#[lծ: P`SR oU5+bY P`PE:iOAAZs/ u&  4%\AAAh"AAAhDp'  NAA   B ;AAA@w   -AAAZ:bgϞȇ   Pu S_AAA@TAAAhDp'  NAA   B ;AAANeaAAAO]F$8w_}]hN8AN:  %\: P3Q-SAAsɝ,GP ˲? hZ' ͇@\AyV\z5cǎmlBx7j\AA9?mW^t:z=~~~ 8˗c6vtt4w__LbOsY̙3̬UZ+WdرNN__bScNW&22OOOZj7ժ&  ;?$//c2cƌ:Θ1c!P=~!ܹSN8 R!CU箴\xxWHIIa޽r-HYAY܁J"88 &W_O?{ndY&==3gҪU+y뭷e8t# .`4IIIatMe)))̜9P뮻֬YCTT5ӧO7p1]]Ss9,,[oÇ#2=ұcGy>Ǝ]wE=XhseΝtؑhdYvT9r$\s zs5<<~ ___>sfΜɉ'*}e,|VСCh4q -VʪIʭ#00 .p8?Z&00{k2rH&MĽˋ/B`͚5L>ł$IȲbѣ=z~qѧO, +V{[nȲdɒ%Ѯ]JT*Z O}JJJҥ ,ӿ$IbݴnݚX֬Y㔦,$%%N+sαgV^4?55]ge{[nшVu߿? .$..Yv?NQs\iyJJ t:۱\;:Xh/2 Ϗ9s0eʔzSJ׺޽{ӻwo>̌3 䩧\ꫯxIMMERTmK2YHMMnӧ3o$q ɓ/ > pnzW\ɼyk)..&<|xyVZܹsѣ,3rHСCYp!?0gϞݝA9zڬLUUJ7.]wMPPp _s M6c08r:|„ $%%1qD4h+,+'|byw?XU:???>c-ZDNNL:\6m utQWfϞM~gرYIHH&##ԩS5j8_AKܳ=W~-SIOK۳gS{72Rɉ'o 4qASJ-_W5hs'?AK]ihAA஁AkA]III}QTfAhZʵ>Ʃ  \G>ZԦ΂ BگuAjV஦}wL4*޽}6u6A~۽{7F! uǹAAALw   --SAA%w   -AAAZQ-SAA%w   -(AAAh~'xֿi&+]:O?T-Z… #k̜9e˖U,)) ^_o몮7HW:xO>TǥHlllSgCA*4.--/ l4۷3dСCyyy; >e27ndĈ(fJ=SiÚ5k2dN)((?od,_^s}9ژ1c~a.%%ŋsiVZſo>Srq<WϞ=Yv-IIIpY,XX^eMy\jc̘1ٳΊ  ג`yLRnذѣGpq틇G&;;齫Wk׮FnN> %KU{ǹ+\K/Dpp0F;k.rss2e ^^^tޝ8yUС̙3iY޽1cmڴpׯgȐ!T*t:<,^ya2HOOgԩӦM,Y$ h'111tuuѣGi۶SG1bzADD۷o,gذalذZ-((`ԩMtt4yyyqUc…x0x`&Mݻk{>ޱ裏>|8ӧOgϞDEEo9f{9ڴi?w}$оf͚EΝy9~8 KE׆?kײxbڶm=Tݼ1LIIaԩͬY*h4ǦMu<AAh=\X_nξi&wqG˾k,,ٲj#""_~Y6-[d^/?,֭[堠 ybz-k%Id^/ggg˲,VU wYn=CCC崴4Ye̙3sdY{G3f/9sFСܳgOGU寴]v9:Ϟ=+[lfpBYR?S֭۷o_.aaame@>sRSSe@޳g,˲ʲeqEEEj'_WxȲ,K$GEE˗/w̫Ȑ}||/BX,Ν;e999Yeq,b߭F'OǏ_*~=jQݱsN0s1wh֬q9"** Jի%KouP(8q"n޼x{{]vظq#СCP*ԩS|J%qyhZ@Y7ӧ~~~&-Օ*w SO!""JSL.d999pttv=www(Jŋ8s >3o&֭['K/uPTqVJ7""͚5\.Gxx8^x=zTZޡCtO#)) V_yvvvP(VmR?2 aaah4G}Q1f鳻5k ,, / :w=z>,GqYڵR+hժԚ׾}{4k ;v|ט5k<<<`ggiӦ\aaaxꩧ2 * HNNZF۶m+{U YsmZ?.\zAVK.n5rtts{z} 2swLIIʿ ?)) _|6m* -- իW(b4tPi|]|BBB0w\|hذ!"##q- //f|UʘFOOOt ={ĨQe佇RRRPTTL_矇V OOOmϟN0`ʕw9\099fg(|ƚ$""Q&MjYy۷odz> l^zz79>>>2e O镖Ν; Gذa"###F'pUaƌppp@zL,WͳbPPUކ P^=tt^j2qL ;;^^^2d"##$mXxxxͭu5 fΜx:t֭ƍck?ŋo>xxx,޽y)SH>V!X2shի򂝝\]]a._te_'kt,\F2 }75ڴ7oޔqV\Vw+PV-[6"""-399yyyh޼9' ֮] j֭ƍg}("//ׯ~5wuuEDDF ooohl>^#R.Z@Y7|#_]ry8{nH׮]k"#JJJ "JJJj}1`0 X`0sLh4UC~~>A@ll,N8!mf;w:|:uT(,EP(~:~Pֵx\`&]N˗/3Hׯ__)2:p "ׯZ JUmWWK,~۷ARM} 2GիPZZ#G\ /DLL rssq |Gѣ\}\r˗/`ի~@wФI`:%%Ei둞L777r7dkMK7o͛cĉχVő#GUݻwQі;Nb zK_O.cÆ X`:uɓ'c={b޼y3f ЬY3l޼Hݻפծb>x7 oooIp;w.222|U99Xw5NNN E~пj븺;w.RSS [[[bwwwڵ ˖-;5jO>AAG(ԇ1]www <O=.\(-7WO?49WWW̜97n `ڴiڵlɧz /^x>-[MMU75 N fյiImo@߭;v@6mWm>DDDT;dS_:J J:3:qڷo/O+=l70yڞ={0h }~ꫯ3ÃʧǏ'@|]fϞ=XhI?D֭kd>XlmvG-]t Vi]w7Qݱk.k׮4jU>(ͬ{עuGtդyX~ٳ'zi٦Mj4Uc}<\ q7uݽN{k|jCOBD0yW%IrGDDDDDD-wDDDDDDu;""""":2{?Dj=wz&ADDDDDD;#㟴D:""w]DDo|Q9-`pGDDDDDT0#""""" wDDDDDDu;""""":Q`pGDDDDDT0#""""" wDDDDDDu;""""":Q`pGDDDDDT0#""""" wDDDDDDu;""""":Q`pGDDDDDT0#""""" wDDDDDDu;""""":Q`pGDDDDDT0#""""" wDDDDDDu;""""":Q`pGDDDDDT0#""""" wDDDDDDu;""""":QPk'Nr=]v5U""""""IDDDDDT0#""""" wDDDDDDu=͖wޚ*?^DD]o{Ϲ0`&ADDDDDiӦ{ڞ2wDDDDDDu;""""":Q`pGDDDDDT0#""""" h޽*+"""""FDDwлwQطoz)E(JAzo\=@;"""""|pW1Er1wDDDDDDu;""""":2ͭ" ε]b˖-E=\m9yyy] "G puu}㌈j˖-[ajZ "zBwyflٲEzuV}Z!xsBDtI;[}]$ Hѯ_?gYz݃ ZQ#`kk [[. = o\MWr9JKKQTTLVB@hƮ&)ךʣ^zd(,,DFܸq666d# 5|塠(,,ʚZ6 ~:4 Z-jtjrQl򙯯Q1MOO`R P(wUV(ﱬ,t:h4K;""+S_ do2 R>{Kc #"z=2aooo1,?랱5ݺIT&?QI_Y~tuӷ&t q(Zmո{-kH~xދ]/ʹرcZīJܕ@P@Kcgj""CQDQ(k}Z  H/\@Y:F ŋpPTXdh\PRRjgL:u ͛UVWnǎBBBM7++ 'N@LL p@R+W;v4Yn0pId2o^ȑ#P(ܹ {!#$$~~~&y̙3hٲ%Mt:ܹs(hܸ16m-Z}5 8x lmmѡCDtvvv8p\\\ЦMۈӧOԩ'OrI_wuC?bbU$vڅ3g"//!!!hРO,[ nnnXd 7|ƍCfͪ,ñc#;;[ 7̙3ɓ*msa[pvvƖ-[1pBd2m2 :~)ѱcGr ř3g0tP,^dիW1f>g}-[M6F3gOOO,^Y??mZ~̛7;v쀟~g$&&bR]۷o ,, ݺuCnn.&LAU\߿?Zli%%%Oj*!((Z;v@nn.V\ ,\R}^v :xh0|c6lyQXX˗/BBB`kk'N`޼yԩ̙{{{?ƍæM&o᭷BV0sLeA;#SN!44^^^~:V^ `ŊhРcp' j*ܼy()-IJs5 n `0ǛH~DuQ'bpGDd[] IDATKRCqq@./rLB\PF՚;LM"3+7SRܴi,Z-jͫ`˷TQ Pepwu@~Q)JJqQC[j@KYZ60OBcAVƍ?bcѼysȋVMZ;iܿ?Ə={bhԨj5Z-O?!77R>/^Ę1co7RDAAoߎSB̘1C DQRJ_|%K,3,_vPڵ 'N@.]DQ^7SN1c ())Ajj*V^*;cյv YTbРA>|8Ν;]VZɓHLLČ3H "##{U-:t_5O_||24hWWWO&#-- +WYYYq5z_|-Z{/\\\ Q\\+W`(--P. ۇw}ݻw_ԯ_ `8v{:5]sא`#9CiI)sJ 5ODovo  C29KVueiV N( 9z;t3gPXXJ@Wgot:BY`'JV/ H{[5nj!"tZ-4j'ݺ*9EvA\\\ooo6j?@x&`m͚}$??fBPP>ԯ__[[[w߅^79: ,\.ǜ9s/֭[ѯ_?tQJaÆx뭷0w\o֭cXXV,?$,Zaaa޽{qF̝;6iqspp@PPc`\mڴA`` ֯_:tذan--ؖSN Z  Ѷm[e?GET*(J899Ujt>s+7nI #Zj{ 666^͛*=kNJW@ѠsZ&ۊ"TJlllhV!" y٣Nd@(h` XZKD>J]_2 mQF;[;V 9s6K cĖmJ {{ ܡi *TGe`RF-yYUj5JTX~WbZdzK͛^x66&-wr̽bbbpy :T"Y1]J[[[4o޼瞓P~B@m۶d2t;wyg#GGG[8y$8`66 <<<ЧO]+;=̭g|ꊾ}bHKKt,ك^x3QXX8ѝ^ ;wBER@Tq~ QQQԩSθRSSQ麾cy;@T@VCV\+GeRd-j "}l#"BU72ũ[lxk}Y{x½07P(Ш$$w^(,GJMdfd/o`gg'v8ىCYWQ{;(JrhT0D(jd]=;2DQκhBQ~B}|B^2`X *UYlԯ_:$11 88bd?֭[HIIA֭`"OOOٳ(--5i1|p)Hx]_s7aaaݻ7.\N:IQǩSЫW/i],ry4W۷/+,:tƍ# v:5.t8w|}}cjoz cǎԲ'/cܸq6lz6mڠQF.R2\ \\\F?cQ; w 8l\\,r-eiYW5l#"e7J"cs])o㛵ېwAҢr;;;5GII1 PZŲˡT+̌Lz]'`#Ni:(g#=PZ tjK(}t8 8#-;asAcԨQkٲeV;]'00mڴ PTTQQTTu֡SN}FF.]T镟_eM4޽{x /`Xz5/YYYųZL&C.]ḫ۳gO|5k0zh 0Ç+Hy]\JZ bNOG҂YЦe-[9g +B<.YM(e<nyP;P v.ow+D,KKE7nʕ8EHGR-uRYFA@.xcٸR_mi6( -l4*o- JJJ`! /`@P` P~}BBW/KyX;y  ]߸M0q>ϟ7ImڴAqq1.]*Սq:P0C ;#+W 44/^LbLVud2?Fvv6rrrpY[  Vig(,,VzX;;;L6 k֬Ih"T:JO>$:tlꫯb;a>-y{{ʕ+pqrKNEznBB7J"[l#"_e2@A˱bJ+VAWmugDPk GNN֯[BFRRqwU탇<φ.pvEQA]nNt̓ؤꎑZzQҐbz/z=u: 6 .^hqcFFn޼`(+F4h/^ Y:X6Q7tŲ7͛78)={_ǫj255ǚ*ܹ34h[Bc֭puu5 |nJenܠJ%caȐ!/+WJln* HIIAjjU1 F & &&uhP3 ,@ii)6olܻxj5ZGr417BÑb<>{uE>.wDDVI{2g^Ks-Q]zFQQtR$?>|>AAAXp!o &&ƪ};rrr(6VhV AO? #1- ʿZ):?v1#"25ĵF:d#eHfqn,AZAII1B5Ci)7Rp`zޑCG`Ac_J7ܸ$$fJ ]/lǏzudg@Uw("l5h[9P*عs'Zlpaz߿W^^U\]]cXln߾- Rq_ z} Ÿq㐘#77WJSԩS={6"""еk*K"66ⱭXrDFFB|Wj&˵Zt&Ǡ:Ϊk\ܱ)WL#99| ѷo_d2gM*s˙3gpu`0 >>8͚>,, o>䗞~o6{-b…ppp pyiiz.\@rr24ibYcS(hР+h^ޞ((ǯ{@3} 1wDDV2wSv\ {g Ǖhعw &c,W56P*kL(JiQii)v܉n]J7| HϠAdDPP-}(BPrex{x"qc pssC߾}QRRӧOKSbY듏ZhmAAAr?}C ANN,Y{K.@jj*N8|&/HHHޠAн{w<1o<\ppqqALL L6 UB^z ֭C_r7~1`///꫘2eRhk.}||<^uiy&N8RiӦciL8qb1VZѣߐ4k 6m“O>f͚Y_EJJJoBVXv-ZlVZرcr9Ə_Auulmm1uTL>&MB۶mѶm[!..'N ^xd2`4ix ,Z͛7ǒ%K֭[#$$J.\;XUFKL"  P4wגm6n܈ɓ'SDt1#"?WWWuk{@Ya 2ثȻ\!2ƍpjAٳӧO67 (v|2OZG"/7}pV,?`1d֦ -[B׸ i&.W P6seG=z4ze@lKlmm1~xt{ALL N< WWWt =z@PPDQFDW*6lZl;wGqq1<<<0i$ 649=yzzbԩ8}44i"-ׯA! $mLH!e3R޼ySKVҌ̙3+-1杝mqQѴiS9Rz_=&LmۢSNR Zy* JKKSp 4ѣGQRRggg 0}A```ElʼJ1P6-22nΜ9ѣGq!bYW^yݺuƎ뛤c͚58}4ȑ#î]`0'wֲjsLB@Qa1  O./)))}T$lS_iAVW{{ww\@")7l\VVɳͶUiڴ)Ҥ}B 888 ==nnn&g]4*J( l߾cǎfT*>|8,XPln݂[Y˜ & F111DvvYvqF(JJKKDl"ZDQDVv6JZ@ e sqvƢ.aذa5jT=1 ()) P*h4&ǻ.f2ROSVCRѱ|k[4[2c;vرc'3d̟?@Y e攟Ŝ򓝘Ose|bi*i-iiA,mxs3rZ{\cAܪNZZcCks7UXd k۷R\888@T@t:"::;vYcw/߽\˺=zVi&ըU>O8授ZՍ5IHHNn t:9b1Nr`cc2 &Kz ҪL2L{{{׾}ku-..*X%kQ񏝋<8Gj899aϞ=ӧ:htRL0;v$/\;;;888ƦҸ%ks/sW>MZmq,1msiϷbXAE_yyy&ơCUoU~+SxUUזjyUװRڱs՞[KhU* X~UyQapGDdnv؁\]zXsu7^wrv  i 1cƌ{cPhԨZǏMQ u:IR1qD89קOL2x饗йsg|w(yx|:t񁃃\\\PTT+Wzzp/; ]8;;^z#=ZeDTY 6 .L<8x"r7n@R_xvZkۡWnn.ѩS'b t:l޼ڛ:k[U\\\ 4h8q"ϟGGG޽8Yfۘ4iBCC駟J]ioW\AFF֭[CVcɒ%(**Ν;kxMsNbP /LZ# UheW꒒`ӦMt:^#Fɓ'0r4&^zɱWd_?;w3gD>}b iBL&h4(**Bfftw؁,\M+VO>L&VuTΝ?`ȑؽ{7ڷo1cW^۱h"̞=/Fdd$x x{{Hޏ{W^ܹsk"""waŊT3ڽ{7,X;BEbҤI(((͛ѠAi]\^iR"= P^*'z|26m___????lݺ&Jh4o駟A@\\ׯ{={F5rіx{{cʕX8lB={ JNNN&۔otrr.ZݺuѣG?W^;v숎;Xt).]˗#""GF-j `LAmB!-- I\.7̩^z^ǏSO={JѠ~X`c]V8D1#"RU3K7d2uC~y'Oe˖صk1(3=zT\\W[uרQ#P&-ЧO/^IJe˰zjܹڵ'x'zq#| |$&&b`($$Dž 0e\|CE.]?C>DDD:!eʺ u2v?<{,j,]> 5~apGDdFA~~]mk|xII]ad2>}ZC "##1d޽_5̙ŋc;v,<==k^ \G_iP`# ^oh;"rr\ IDATc֪VTe7F|||Ztkѣ1zh;v s?UV_~xwVElmmP(1,լ lmø0#"*Lw TI:aaa8x`eIQ>>>}:7n~ɵ]{2m4l߾Am۶aƌ] ";"GjHRa8y$9nݺaѢE Đ!Cvhݺ5ԹsglݺΝ+-[m۶g=Lq|7puJJJ7oN:L[FJJ ,7+׮]3|UVmsaΜ90aFI&aʕf>䓐dLܹs5kƏQFᣏ> 5>2 ?SKD;""3V\^{ wﶸN~~>^{5L0̼VZz]n L^J3f Tq9'_6|%77󈏏G=ЪU+L2_~%~,XÇ&M#zTgEVcɒ%0c DT3hРU3fN2k׮ڵkqa$$$]vPG_MNRRRA!33F±cK/k?ȑ#={رcׯ₮]bxClӦ Ǝ"'%%%/ѷo_cǎxwh|Ծ}IIIx7ѱcGooI+NVjR JSL0 g8}4YYYXbfϞիWw\ƇYW^z%/w4ʊ+&M/lA\SqV+33}w0 Caaau/^(lٲ%%%O",, /"-S9U/::w={j͙3?8^~dٴi0}t#** 7n4|׮]zfff"** IIIYf!** QQQu71#"кukL0 HNN?hG*GbXnZnJ7n'x.]P5ڵkξ(Q/?Iȷ~pl޼vGAAٍ7qaÆ È#H4iO2>BCCb $$$wELL 뇰0Z$.kh45R3gΠYf1c._ RӧOOddd`ذaZ(w5;T*ooN\\7Cp! :>|x}Ν7n`̙3!*+"N8ڵk_\\A!##'N͛9r$1l0ۮXvvvq\t̚5 z'O6Y|y_#Ow'In{Ϟ燄iott4/h^DtUa֬Y 4jӦm6n܈gǬY`cc#-4h~mUU*XxԲ#1c ܹsطoMbd0o>;msM̛7fB׮]ѵkW\Qcy=c۶mf[I㢌jݺuHLLD6m0}ti +xzz"::l뱝֬YOOOGLLIi&9st 8q"nݺuG9Y VuP׵nDPYf?)xDD#44첒X۶mPeќgysAtt4^}U1h ۛ|&0bƾ}0k,899U;СCֹBhZ`5:=H.W^Ebb"ZhQc=j(?֠d۷̞[666>|8̙}K.&˻t777r9BBB$4ouٳ]<;WZZ Vg܎]ff&kV(>^*kXoqyK/|< ] ó+W]s x.07i$DEEUZnv'χ $d2lٲږ;899AEܸqpwwǀjW&M|:Zdrssri'2 4hVllX@w1ݜd3ӭzqJU)X'Z A ;"ЩS'5kfu?7Hn9 `vPoŸqзo_ƢaÆV*[dMzi4ڵk?Xx.X:gL+Oxwرʠ4884ɲM"..111x\7&&]+ˆjp}{5@Ay-9=T:?ѽ oAuQ]e[tUQoX׮]qq>|XY+u&ɝȉZX 49DeG *E!h,Oyy&U wX[*uLqq1*H:u*={^+}pOOSڸω|cƌ߿pG!$$ `i(((@zzqjG2_~(!QpG!Ul066͛jFǁ$ݸqǏ>s(T"333|w`YVbcQ7A$mذ%%%jCcƌ(--E>}.scǎKyyسgzµk`ccVޢ|˖-8u}Խω|Xj૯{Я_?bʔ)h۶D+͛%߸q[lQ>]5Yz=4B-BBB> ={'ܹs7nSШQ#޽;FضmB!֭[E֭nӧcڵ8unݺoootY0zhشi;"/_|l޼={|}}ajjo"22o޼ҁXr%M???77ƃlٲE 䱱 ޽h,Ѷm[,_]vNNNY?kkk899IO"ŋѽ{w믈͛7%ҷoߎq<Ì3pAf)Z.66ǎCrr24hACnn̘GXX4VWJ=УG ==zٻwܼ(>Z5ٳ|`_:9;wFΝQTT4`޼y8vv܉#Fm:t( x, u̚5 f͒ȑ#sH5 9}e*x~.L*7ݱkW۳G2 hBH5xU2=PZd"'U)U#1z!&M.ȥ<}}}y4jԈ)`oo_%yTZgUy?8#,, 8rܥ-AÆ jRJMMsx<֫WUR - QQMLDIn.--aۃ[%e#yŒ gggh}++;:Oтt޾4edzff37iưWFW`ʐ^@QF23ga}++zz¨);.iw"7) B^^W( k&&"?%CPXbob,[EU~P m{(+)S|EZn *!44?#)!G2Ut*o y6 >sglve%%xg؁7QV\,w_==wiФa.O6nąoUiߌgϰJA=<?'?%w7l@xL:zz߾=ڌÆ»X/OƒWD㦍g`YZ{0n]kk6j37`\[z^PƢDzpyGDd<ܼ{Vܔh;11*6ަMp t[^`* pv8({|0 %99wթD|}/Y[ؽFyUT#"*ɯ0av*OOOٳЭVTB!ı!C prp;<@bqgZ;YyW~Ac];ؕ xk'O4ʣ*ȀJ޾OIb'kjL-OiA4ce\Uvvv;<(**B8!B g>qQQxqrE&Mí[5҂9 VYY8Ի7Ҫb\Ư"jR>ؼ3g^X @ƛ0x evV(ɑ#E4{6޺UETB!?PL>N鬉{6&M~;t%t R*g#"p|Pe*ԨQx -Mi޵E`}e'GE)yU[[{&&oAac/^?*kd+5kC[[APTݿԻwBD/[;wT,*P˝0t*qB!w*ӃԩpVVȊōˑ-$svl\_Xl>A*թS81|8JdO0%ꅾ#κuHsG澆vvbܼ,%~WO+,!dxd#eXl) ۶7~MkZF;vxČ|33+8tݾ(ȐylN|<^?fKYX`RBZKX8;c@h(6i"3]XZѰgO/z5eCK{<%˧kdddFFF5]B!T! nD`'Յ8 ׺hb#G DZ !(*J xs9lT |33geL{v6ǣז-rm?5 =z֭zꥥ .ݻqUtQkB!Qp(V_- = &y |Һ)z~sb/^+Mw #G´ir16+^ф3 V W>r(D/[&w7aah JvJCѣqI2Iׯ+-xdƢ{CPPzVT[Yu_bbb|rjpG!Ow 4Sbz ղ@) z"/1Rke5HVZ&҂g֤ llk׮tEehC73ExLu.kqgZ_VhB^QU zmУGܾ}[j?pqԯ__"N52 !BʣNK:zz3{W*DXB90vtT)GGݏyggCXZ0/UT:oyv5vpܕK4WW/=Tՠs*Kj;F[FFVBT:w Lʠl@YCJZ/2U[f͸X(:뫴zJ^V\C}Vy`WY=&! fffAF0}tʙT `ӦM򂁁իWD!xFB&Madd&M 88> IDATG!-;oL673Ӵ: e破@|˩2kl, ˖-ѠKۃ[E*SuLLv)O.U^byS̜9zzzGcO0elٲǏGXɂlقÇE|2l>D=UVa ޵k222믿b޼yiȭвK!ډeV3M)7nTcmjQ'w K,(K*&+FQڐLYY [+Y((ѵȑ L(yf믿vyVSqƍ8>[zxVɢ>J@a !Ow6rӟ8Ҽ<2gY?xa͔r*ح.Pڍ0f>4c3dY<޵KaR|T1/_ff&\v`hvŁnpm"<޹Ov<;p@j *,8庠C۱#?>bfKmw :=8;_IKٯ_ /JNmIގixs'tk&}&MJ21{"y홱8нzu .͛X`q=,\...t&BHա Uj9:,Z3o<: |ss Q=_Fʭ[wԐׯORp ְG8WOفxvff -M0[Bn.+V`nii887~< mm!(*Ri:;__8t?mI*T3o -u n^@p 6Hq+\K(fgg$yRq[Ei0HHHP(G=/:Bx{{?3tRY3f=0 !R;P] ;+$FF 'Zv@|DDvе+T|HTEXlt,&$(t\N}M߾=Bai)rU 4#GN-XVαkWO$3s4_kƯթSZut@}rssqI@hժq c""" t V$.B(A=n't5TсoUY~|33 9{6's*ut8Wk}E͚as0t^p!uS8 gg 6 hI}} 8tHL8<۶mõkfΜ,Eo0|E߿YǭQd2*~: %#BHE] bѣ0vpt~& iSUehtwpy*wi!O/|Lۙ31<2p8p3܁FyT.OD 3,Sm[]4 ض -TW CΜA-PD=Xn;ضm6l͛7K_cذax)Zh 9͛7ǽ{*L 777b0aеkW*RB!Ccj©_?8zoGҵk(Qa`1o;Q@XJ] 9spoF~:]8::b={6ڵkA!*,vKO2f%o@)׉lPw#3gf(3²2 31#̚5Cx{ PAa!ff37iưC i 36E(ǃ `#]6qqHsyII°^=X^۶ӧx{xwz`Ұ!wP%]\ !Bj .qR_# ! Pr9GQi_>OWj۲eP]mp8nmtUj‰Qra [Oj-6jx Yl8B!fИ;B!BPpG!B! !B!@!B!|(#B!OwB! B!B>B!B';B!BPpG!B! !B!@!B!|(#B!OwB! B!B>B!B';B!BPpG!B! !B!@!B!|(#B!OwB! B!B>B!B'@+@T"""5Z>N:ӳFA!B ꐋ/bj˲lWRR[RpG!BH-B]RTT>7oހa0 rUMXZZB !B!ZC]"+PS,SOEB!BjwuM־Urn!B!zlZÇvvv>|8*vv]O%B!څZ$!!oۿ?Ο?AgP~mEݻFEGi ~IpK!^HB!RQpW1W򚣬L$-^ G`"M PZZ @ )--EٵĠSn߆aB:.9!c|c`%Wj%B!B1wuHn,Bi``/ ~@74= FoSD߀M>)iΆ0Ag,ڵCo&P,1Ҝ Zk;!B!D(C*.PJJ";qhѺ SPv&آ"0(_^@⯿"pLMm b ѺM0`?GFGn]{ F+PZ:ʨ !B!QpW  4{&3h X.'Χ̻=.O+WKn޼ ӣt۴A8@8B:B!Bj'sW(Z.##A' ];2!h.\OX==85ƫdpMw60`|XY]NX1:B!Bj1 Y0˃x|tttB\.7:nڤ0wNf`~߿0r8`Y,"++ <oH+nn/ ii !B!wuVYn\q[*efn|:dA!B=(cʏ151ENvtyfɖԕ?0̄TYYY033 (#B!vp>\]$---.,X t33s߿y2 wP<B!RSacc#N!B(CWFF(**BqqR]Ѓ=zŸTwpiWp7޿^,04 !B!wuDYP?(4 eDD`p_($#`P*(x8tLEix"֖U͞=[*ϟ hժՇYYJJѮHD\Ǭ,\t /;0 ww "0jU}'$$ ((666r`GkC]j5-/^ ak.SN?A\\ǬZ `ݺuګX'ֆaܿ_e::w"_`wow@;w}6oAI g^y2͞ 5d7Q(p8!aXmZ5n;vi;v]˭*8p ]L8'Nϯ򋊊0 6mZ-ij޼y`w~Y0 kV(; 8p͚5øq0qD4nܸFyuQ.\3zBȧM+@*S=x#9- !LLsa-.A oaLdgõ+: %΂th@( II(-a3PvtG?@\&7|oFb[bb"pJm|27`ƍi͚5Æ вe!u[ZZЪU+\vM"-%%ԅn:t(,--k*} ڵ骐(CD n0noDϾ}[Pg`|`t0 a`ށ!_n0r<~е=׶F^{mhԨT=NZ5"!z5lذkRBHUb޼yhԨ|>6m%%%RLf>`CoGK0tP}vŋK] 6 xhРƎ+>o;L8vvvӃ+l٢9*o׮]aff}}}l:(;[۷o1c 4ozzz033CϞ=qy먊CgϞksΕ;0 NVwwwETꢈYQQV^m¦M  U:z~QEdd$wo߾{~%%%صk>s4m055Em6ʿ_SSS1~xۃb۶m U~ :ǎݻڵ14h 0>}ܺ7 `Νm܅#C{3-- s΅ all '''|Ȣ5G`F`֭۷o%V\ aᅨsW²,6mڄVZAOO}q l2cڴiSUYY郻wgϞr Ï?(8qBF {?~׮]ѦMzBOO!!!Çc(--tGa׮]8tΞ=+{̄;pmL8%%%jΞ=W.`jjWbٲe8|0._ kkkAyLyC@@ѨQ# |2ñqFӚ?~///X[[޽{XbYXX-Zdlݺ͚5ȑ#ՃJ"\KEuQD,33u,,,Ю];p\ܸqSNEdd$ۧ6_9wn 777 88s """pYtEorr2Ǝ ssshHKKÍ7۷o'(==ʂ\/_-[m۶_vsGٳgcXf \D98|00dg޽5jA.]`oo7o}_╧ yNNNӧ\.p ԯ__ueyEp""",^>мt.Η>L<7o!PDFFHGdV cccH{.rrr0h =6[lA~OffҟPV sYTݻ٢"655MIIa߾Ma_bgS7ascKؔV쥥ٽFC__65)>yl~Adgyz{ ڰy_9ش6l?ؔd677-((`KJJ5kTkJHH`|>_~,Ą=wx{NN`7l q̃X]]]ԔHhv IDATXaئM@\\R*-""3Fb7|`a,Y–ӄB!;rH}v<_zNj/,,dM4Q奧ziӦlRR8---M|~JghhȚ3**2DbܹsY?#3gΰدJfzjj*kbb`ovP.\:::P2d#Nۿ? QZ={ZZZoc{`$:(;WPP6jԈݻwYkkkVWWU?zxx/_o/))aL`ǎ+q̭[Xl~Qv(ɵTTEqXeYlpp1iiilX_R/ZܹSb3|r4}U СClIIqqq3 H] a Y4<mgO>-U&^t~e=c} nW/./^"F8Q!\hKoQJsDwx&H [-wsE^Ŀc>LxRފ+PZZUVI} x/^z?J|0 ޽{֭17Ceٲe_wkkkqwԄ 999߿?F-0 -Z-[">>G:;v400PnLLJuX~=`psso744͛P$''kRaԨQ6mၥKT Xů a~899tuuvZ4l!!!׸UUZj:,66hҤ m&q5vؼysM6α ̙#mh۶-qqvsss|ՕؿaÆ_@|lٲ&&&m^t„ ZCBB$QFnn.$r\\RhrouU*?333oE*s+3jРAhӦD떨O+u_D… %aڵ2]ULk$Տ:B(00 `lRҼs0m\=OmFU&ƦHINAtu=vQ׮#%9Ʀ6΀a7Wy`j{TPXү_?m*+>8? <.P}vRZ``?=ǏǵkPVq2&&&:(sH8h:w,&"G4s:8::k׮ ~*ueUO"!!ZBfͤy<:t耒<|PrTUk-\0,}\vvvvU9O8((Hgh|RR݋+V`ɒ%Xx1|xXO%w4< &~022ѣGQPP ޞӧO{VZDyʪ/]{S7履~Ç% MyEСRSS bv <\4QEر/~5D|˗/}իP9'5 [&.)`碁uq@XVV&΃ap\p8p8p,g2فs+H\p|e0 rss ###d} D k(Y͛(#<<F~0n8hJ4a@E ?Frroi菜Dcʓ)'//999ׇmA'@Aʼ'De 4wƱcQ\\cǂ)}-<47{3f`ݺu2dtuuѦM_}Vp\t ...֫:֭åK0rH;U_D)sssqx" 6DBB6MѸ;Qˡ/į%%%L:mPf~B6' W;[oXk?[ EdMv}|̛7Oձ&&&&x"\'OҥK|2.^~ puuzT[mUVze&Dm:剮ĉNΤpvv@UCu>hr~VTݟtMS}'l޼:tҥKѦMAGG>/G}6Wu)SsݻwcN.\f &LG… ;wj*ڵ FRZve,^ 2e ._,'n Ҹ6scǎ ÿ+n]]III%p8())QҪ!fxxÔ>d~[Y٘0aĘچa1 ?n݊3gܹsUVVbb'|%\B?LΝ;x5Dk999HMM:hK pgF?u*ІOZΧcOu:o޼Q|^{/9SqFΗ/_\W8OvE&aB899AOOO5W^ _%\XYYaժUغu+?~,.:@KKKqiϜ9>>>񁯯/ڵkvڡ}Сߎ;SNԩ:w,nMC.]u066Tm?>tuudٳG*=++ x9::q8ԫW/ ,X;w.Ho&ZKjѢE;vyNPkh>fɓػwDگǏ +o(OSLAII eI_~%q9|(,,H=FGGk\ ,F7oJkff̹kk!C۷1bqk :j9~Ԭ[l͛7ѠA54iϤq0-|*S>Qːd~022¾}ZΝ+slMCɜիWxxۋDЖ-[$~ѽO?Iƌ3d#jU޽{c̙Xf Э[7ʕ+HNNF-N PuPt5a``Ǐo߾Xr%v 777XZZ"11111Ν;+5uԩMЮ];iӦG\\bbbEZjۑsΡYf $$$`̘16lҼ94i{ٳ...Ett4|>/͛Ç#88[lAÆ ܹsgƪU*[U~*S>///lQQQOOOhBmmm`̘1@׮]agg[n!!!_|oԽ7°yf8::HMM˗QTTKʝD Fhh(fϞ[nɓ022·~ ZnHxzz"77ׯ_ """0rH۰lj'k׮a߾} yÇGrr2<@xh= B^^L;w4R۶mѣGѽ{wDEE!$$Xjbbby4Q]...x֮] kkkD=gϞ+p98y$n߾ @E*K6Sڗ popssãGDw֭[Һk:DDD5>'_]P___W^>N:]]]bƌun]Ե?UE}wyɓq9QQQ8s >Hi͙3gbɒ%@tt4>Ǐc8<֬YR^c6 ;}ASݽ?gϞիWk׮U{ n|{U{tp~`VZEV^@XQYk∈j!,g3HQEQ\ ...tv(jB/^D˖-D"@"ѣG8pJiU)xh;((QEQEQE}(((@ߖIQEQ"SSSRE5'EQEQEQ(((>tpGQEQEQ;((5cݻwdffa77oAHHHץ U/RAAA`-S:a`x(++W0 N<դo߾`/^tV;044t6nj|漏Cnn.BQsjV0 fΜhXbCm攗a8::j:+ڟPx8W^.)j t66mNNNΊ &&& E)E(JtpGQ d޼yBbmml[Y5c(jc﹬,lݺ-|>0l0\rW^ŀxyyݻ B~`hh---899a͚5(,,T;l00 X055C ak-*LMM?&O, e ???XYYA CسguW7Gٳ4haaawww\*;..+Waggӧ#99Yi;a `ii3g"++K!Mumm]HH 333|gΜYfC0006:t耵kעX.n@@IIIro߾x5͹{.ƌ x<`ڴixBܪVԡα^ 066/^z4]qq1.] [[[k?bqN}6g}t7o0s~äIкuk~~~xyP ɓ'N޽{cǎri_LL \xxjj*͛7XbZl @''ŋѶm[ϟWZ'uTjjHM6M6W_}r///ǶmеkWAGG]t] HTc]833 ,@Vabb///\tIaUaŊpppχ#6lP㐢s׌um۶p\t[s9,[ hӦ s={Ν1qD޽{ₑ#G"11Ν˗>}ꫯm6p\~:6n܈'N 22fffjwر믿йsg1BjgJT믿ƩSp x{{SNe^H[nχ+JJJpmB_w܉EwްBnn.QQQ ĥKKKK4umuAY6nݺEHKKÅ aÆ!++ NNN߿?JKKqlذgΜATT$իWcƍ022‚ dQ'NqPYY.]O>Ǐ#,, ={THm69ַoߎ 6{ƽ{pQܼy<,nii)틻wE5j 7Çj1۔:n޼޽{C( ݻwGYY?{bȐ!hٲex_u:}"֭^~x,^SKW" ѣ<==q-{`1o<\z05Q:~)틌 888`ĈHOOGXX°sN̟?_abC ݻw6 .`ڵӧb'^)-QϯرcD$FKnܸ~%EHiiܲs/#BPF+ /))!&ܺJ{);'&&&raΝ#Ȍ3T5,_ ǎѣIQQlّ#GbnnND"\:^.EG)l'&&FkNb1駟驐C$22R^QQA&Nt6+˗ 2e;we˖$>>^nYQQ  H~~\Xqq1!ȦM䖕u u"էO<\E rAYD"!|ҲVԡα.mrZTTDuF4Sn}xl IDATqqqؘ *[6u-9R:7mڤ4+! d+>'cuo&rqe"X, ѩmEGG갪kΝr޽;@I=Hffl޽{ "7oݻ̌p\( WgOU9Usrrdsvv&Ϟ=-KHH y\cdҤIry&={$ȁTʣ*u,m#~~~R|<p8\$--M.>_U)'""$%%tRSSɫWHXXccǎ4S6~[j *.=:;;Dk׮9v,ˋ [nUKr Œ ),,TXJ( L]x<`yW棏>",˅KO2_|BlEl:mwbXZZ$::ZWnn.@IÆ S/@>, W4uiظqB***!aX$!!A!͆ եM5nРAJ֟9H/: 2D!tbbX[[r?I}'NTݻwdժU0uq}w͡NُR-"H@@,ӧaҺukR^^ɓ'ٳJyo޼)ԾyFaٳ 2g:rB3gC*z;z@lڴ ׯe'&&*Mц]& ~:`ҤI Я_?H$DEEջ,ŧ~muk]G.] ,X ʏX,Fdd$a~DH$νS @333 8bX>KۨxdffIBUؾ};;_Ҫ}וL8ɓUmEUCU)o(((窤_զեKYp EsO.\6mZy+i`oo:Œ=Ο! Ω{QM~x;/]M/}*} >=cƌQy1y?]\4HIIٽ{7-[+++˻enKMm!Jms+˟IVU{Ic)uXш@DD憡Cb ҟ9"??զiH666 aҹʖU]^} š_u/m5)))nVzVgvvvGzz:GRܽƎׯc;w.  .{YUMHVG]֩[4!&Cw >Ĺsp9DFF8~8mۆWB[[ua())֭[1|p~i5jt?7FPg/^_|KKKgϞ0774EEEM7e˛b|}0!TCt]3gʕ+ĥKyf\|:thܾ\~n^>~R)}ٔeM}5׾JIӳ';%=ׯcǎ TXTc/_ޢE o_O"dee)V4  vǥ¨Qd$$$`ڴiΝ;rӇҥK씆euI 鯸O>U) k%J=UG-p< ˕Rc]UҲUVuiS55寮A޽ѻwoo$j*ݻK,Axxxl!շ?Qgsс󑝝 ssZP\\ D0(h}^ܹs{Ƅ du՜akDZ?}zLMMX,VzU++)EՍΥԖ@cBN1ѣG'|" _?-- /_Œ{^ڱ=yD!ٳgIzQ'j{}46jҮ];X/i??zKgUyyyx"l6z衰.m.:vKKK}0Ш@DD)n @cxu:k/wHNJ mРATϳnNc{iݟ>}AՖGi8qeee OxUUVV"88X!ܹs(**3;Eܽfq5H$ŋk#gܼy666r߮~eӦMreee/QQQ1c%nՎ;+ U^M (,,įAew%?T3f"}ƍKǛ7o0j(եm&LPWZZ/--.70>֬YS6,--^㇕5e̙3I۽m֮۷M6J*Sc]U\.f͂D"… .x=zm۶)333899!55w B̛7AT/9U޿D}9`ٲe`XnL" 44T3֭['wAo>]6uT!<<_E>&&^QNc{ggg=?~ҹn1118vJ뫭Э[7dggcٲerK.!00_~^o~188ƍÎ;T;E},=fllٳg_EΝ===ܸqyyy3g܅ѻ̙7|8p@mUƒ%K}vt]to^a7\\\p}k]tANNxb۶mv͛pww38F]ömh `ٲeh׮]lEŋѵkWlw>} ,\xyySNE֭ѧOD"\xBhhhO>}`077GTTaoo_퉦.m.\{Сz%{ЩS' 0d`` ݋7ns˗1~x?^#F`Ϟ=puuE^ Ю];,[|c7n&L;wUVG\\pz]Jz!T_c.֭[M6ӧp;'NPkumSׯ/Ν{ `سgO?c޼yر#rxVеkW//1l0 Czz:*++e.]CAtt4ڷoDx_56o\6N:///lٲ LLL'Oؿ:д}Uu\ M6ܹ3lmmgϞ!%%SL1cTZ_mu|AvBXXݑWB"`Ν裏۱cG]vBDD1x`̙3G.ÇqD",ZH(U;w9ܹ [nťƴ.BBBCxzz߿Bm۶ѣ޽;]]]Z 111033rqL6 l6W^H$/-[(0 Ñ"00wUaoo'N׮]þ}d'dll xyy!33'N@XX8a_"22χ6N<;w`ԩ:6l] c鈉vNF]F]0 ݻ7߿Ǐŋ0`ܜ!GGGܺu }p dffb֭?Ɩ-[0gD"9r*=5j(DGGcHNNFPP0eܹsG+!}$u֬Y*ϱ^r$(( o~[65vX=z;wǏq]oߖŮ>6mڄSB" <<'N@^^MX y@}\s̞=;v,pq;wԺukDFF~:lll#Gֱ`ڵFLL N>L{ibS@Uis\~ nnnx{{{Xn뫭۶m;w`޼y 1h DDD`Jfٳg֭[8y$"$$YĊŬ^^]DDD[ EDDӳ(J=;v}kG׺ϛ7vBppp>󿬲۷o#$ڦ(P ...tv( x"ZlۈH$H$x<,-й+mZ`/ѿo 8p/.EQEQDwEQML(իغy#p!*E`X`X(JPQ)DRZdžq=*?mFFFբ.EQEQD_҈^zq VVV7nRRR4-4(3+ }<<1g,Zukpp"l"Jy .ήܩOBjZGQEQ;w$%%ϗ9rϟakkQ)aXl :wꄔT"#퀎Á>tutp!QT\X #+ v(..AqI /]iOF ++ ((MwɲevRXlrDQTsp]tBñU+A(f99y8rGqq1Z98BK ){mm-}~ڸ3MEt(_FIdddˮ^ڄ9(9y$@$>ML^r`dh|}dBlپ Iɰia'{T\X##CukM(f(\-8lĢγ300_ukֵ \;uڕ+pp8lgkHEQE5tpHS޽{7aN(jNZt9~8|If!!9l9lhiiE KTVTpy\dfqb8883o _h\EQEi5-[H![l@(jn[X :::;r7mFu;,^0UޢɁPX>f2haƜ9.EQEQDw߇SME%%!;'056ҽσ+6| ݺ5hY9``Xry ڵt(( )FdkkÇk:E5#ĩgŬ6͂H e`X )DbðF3qpf~ڵCk',-,4\r(QE5 ~gCjZ*`kk0 /SX`9'@Zj>h (}SAGXRt#<_\>ɢSEQcEQM?íw`ll ++k_@Iq1,u@KK `ޗ8|ffcosaت5 ^Sǎ077;(@QE593g`ԸD1+~+5 !! AʫT\|۵##3_-%W iׯPPRm"SEQ(b(((IJ%K0a/.XBNN044FE)/SQXP4}16nنlddB_[7m%x\. HO@fV ` <CCxzxh*((j@tpGQ aaa--~}ot; %%͛Rx|x8 q_գtuu5TEQE54:(j&>ňQRRBX/(ŰP'Ot ,[7o7LB9T*bbP.R`ok WzT ~=`eiݿE 5\j( } EQT3  ;wc8Hx!YY6{˄Xf=BlE>}p"<"Jy .ήܩOBjZKNQEQTCw(>'SgÐ)wcŲ%pa "#퀎Á>tutp!QT\X #+ v(..AqI /]iOF ++M(DwEQ̈́NS> }.,bh xGZzB!l6\.LM*%gC##+MF+GX,){mm-v#[kEQE5X&EQbO>L1 ^C qvA~^.22Rqx$QQ"=#f(//R3^A$z;>O4D\b?`?5س}0 S6(JAz* }}}ٵdAAAmjZtp̰lK`oo[nuYbC4ja̜9SY Զs.1=)%=CQq1LLLE*lmr ڪLPT\cccXYY#,Jaei ߗpز0ZZ]-sVlݼ gOjyXBQ  QYyou 55UY疺ȑ#q ~~~t֨Blfpu3g"00s(̂@ ZzH$07í;all/_A_bΟݻVV!%% ף1t`X֬\ VC(,H@$ T\pJŕ߷/<e?o mڴ?d{It6(JH`ܹtvF@QE5D֭;s\zzFAffÇCGGS'OkQ012Á@ܮ-#.CKƏO[ٳa! x>:`BT}8tqusPRRP TTT@$5z٭1o< 0ѷEQ6o<|E)% Lp*77~~~@ @gϞjgffbh۶- +]tH$¦MЦM|⫯Byyy`jj0ydyW\i2WC qrqЯ_?BKK NNNXf ]:iޕ˗zzzCV0vXX2XpttĆ PQQWWWJa# mץ޽1c<6666m={h, ;Sǃ ;~EQQ b1Я333 6($$C |>3g(IJe mmmWFnnBǏƲqJBڵ nnn055lll0p@ݻW@KK $wW ,@Vabb///\tTUuvzz:L O?ETT,={mmmX[[cʕJ8\nnn077χOdP6jT9Wǃa[[[:|W]Aǎesmmm^RHN7oAHHbcc1l0BGG{իWXL<vvv@޽cB▗c۶mڵ+.]`׮]H$n:'ͻ{LJK-[&+cBlٲֆw={(Ϫ֭[6lLMM0LG5իV7% ;vD"3fdӦM9v@&NHZjEH~a ޽K@NzE\.@SNdȑwwwҷo_MѣG׻?#ի@ɺudϟ?o2Wȑ#dĉܹ\/_,tRp\2`2j(bnnN'''Yn@/ +(( iժ3f 7nիd…*S;vHCȨQȘ1c!@X,KC 3::ZԶUǏe.]Ș1cH Gnܸ|ݦZ rEr#* p$<}L96k 9B3xrL0YJu׽SdS9l8y9{>s 2Đ7oSOɥ+;ɀC߇ C HII  D""ҩS'X[[ &aÆ@@Lt_| SLeeeC,,,H$RNyy9100 zᅣ͍L0x{{WWW0 V'-ׯ5jܹ3@X,9tBD"l6ٳ'!=z :::W^ro߾-+9r$:t(qtt$ȅ Ϝ9 |>ٓ9}$//O.g}F###2rH2i$ҿbbbB\\\Ԏ̿KV^-[Gcj@dLJٓ0 C!?sےƏOlmm) &d…ᐏ?Ovϟ?_aSL! '''2d2|p@CCC#4Ҽz"֭#Yx\VUvСC]0 C:t@<==eRTT$F?w\,[bkkK<==I6m۷CgggC/_ee,ׯ@4vX:FYIHϟuxxxx9B!o޼!| @ Ȉ#Ȑ!C@ƌPxbH-H~#IHH5_DUKMM%^"aaa*;8LmUuI/DvG!܅ԛ7od';w]K/\.ILLK/gdd]˗?hkr9̘1C0XYxII z@.E^ Q1Wɳ$'7JyN$>$DZd[ȡ_M6oJH\\uvrYe6ڵk$::ܾ}|&>d7H\\yIOO'999$??ryu/^,̿yFcD!D֖dR&L H``6ɫWT*wll K.---bddDJKKܹ -[$rˊHxx%%%Ɔ V"ro޼I^x!/"MJJWTT/ ӦM?}T־߽p jŭIYY@Zn]mݻOܹsCT^  de 7oޔ-#p8Bb1駟驐wu9WBHnumwp/d{GQuڿټylP Hdo߾M8rD" ;ǎKI&ivv6ٳ'@8u(/$-[d˖- VXAwwwe?{Kaȷ~+T}Bwtp`2311[ՕػwDev-ؐz!_h_աற\N^^^ٺu²/_.KX,܀I4w?B:#G(,?s @:t kذa b1qrr"Ç1۴X,&qrR_HֽɽÄx8,k2)d(Ior 3r Ï?IӦO Ϝ%w!w%'qqq$U3 J233Inn.),,$BP($b)СC wy{{ɓ0uAa bbiiIt%HW6XxD"!aSBGJJJ!DEE)%nMjݼyS6:={6@̙333R\\,,++Kvo iǏOE!}aX ۪ipWs!5iwpqF4!!!U)k i^~MX,155 j֑z)anݚ+, @zR9ܢNeeCT? uBoW%Ϯ`]ι}J%}S]zz,L:GeԨQJկ_?۷gϞ*m5U!}I١_~H$rAIL.]}N87oި]r=zBCku5barj6-Q\\<FޟE k ߀έ{ͅǃJ4OAX8K[;oր@(fƎ+_vu+hkkC[[ZZZÑ}O_ex"tYnjSz.BBBfAABCCall9vYp :]qqq ĦM~z_^6$11Q/>>prrBk] gXǏ#%%;vD6mx<xmX[[G?]]և5jl~^U9ʎ՚|'Օ 377#))i=*;b1"## 6H$D"v2u9WFvPСCUUÆ S322rssQYY) ӦMS.\Bƿ]vjs:jc2..h߾=vZZZx rrr;V>@Jå'P( {(`*//^ilMU*))AQQd*|W˖-iiijΠAxbرGEN3fS` HOOQې%ս k6]QQ7oޠ eeelpY-Zt[ZZZ*-tR,]駟ٳgcҤI2_fC~maaq\B Mlm+KKK\rEEExb]{UŸР20'69ZZx9z:})7 U\λ&PSS˅6444MMMhhhH4^=:v=h>|8q <}8{,Ė*:v9XloߎE!--Mjbdeebbn¯oߖIF\|o߆԰/O@033CXX@S-[ 44W("(^XeѣBDDs||kUҞ~ Eс*++QVV333巵 QdnQ|ԑc(Xy)vy544ݻRpI2/ZVvےq55=©S" HY9s憺:ڣs?vjjj ccc|>u?rkmg[ ^w]d~ZZZс.0)p}:lmmŋM‡/;ϣG" VVV^lW.s[2Ο?fЀs碩 'NysH6RRRX,ݻwʽ4::Xd `޼y"a}||111"O?_5-iӦA__ƞ={Dicc?Pb Á a``CCC0339,,,`iiO#bј {FFF" \.1"##E.v}6c0ɋ_~$Pl3Z#Z'i`k젪sΡqXp! f\LS?={p899Ν;>/^oV,ڼ633Î;ɓ'#66ݻwǍ7===$%%֑AOOzzzhjjBSSZZZSZ/.fr/pˑÇGFmm-}" ի.\xw$NqFDDDPWWGaa!.^.+W)1°eQQQٳgc֭b"##]v| IDATwxaiiG!776lKRSS$$$_~(((@AAә ..^^^pssq}^, <==annZ;we-ƌm۶>455舨(/ <qqq8~8x<?~gB  66})/eWWW>>>̄pa̘1HJJBpp0```HHH ?PE"{ܹs1j(W^D~~>JJJD<~iiiѣ ݻ(..ƴid:ɷ#eG҈AVVΟ?{{{ 2D}}=&LvC`=w .22?<< +//'_~%qss#:::DKKtޝ|d۶m +͍5={O?q_r%@֮]+K>LOttt{N:J'=z4111! 111"a~7Mٳ'YlRYYI,X@,-- %={$k׮%Ϟ=cI=wYjdƌwАhkk={3g7o\f>Obcc "]t!'N$'ٲe @VX7)) :2c?$ C`booO\.122"$::<}T,|ZZ9QWW']t!}% ._ÇdŊdСƆhhh]K dښG$LII vvvD]]#F !ʊ`[Ľ̟?;DCCt֍DFF*DsΉā{֭[Ge=wlsǏ !H~2;::bI&1ڵ+&bw555x{{3cښ 8^ܻw56=(M_*sLJĜS]---Cx<ٺuBj7=weHt21Ye2220n8Ȍ fk׮:::-BQ2ǎC@@BBB$.P( Jff&yֻ9y&.SV+~ުU;ʫ Xx15(8lIܹs| 0R( By=wWِNP055 \pMMM>}:F"R( VB; Bŋq!dgg:::ׯf̘ӧwx BPBP(rl2,[&WBP(JBQ( BP(5( BP( w BP( @; BP( Byk)8ğ]g044l1dp8Eܿkp8ܹS]\\pPUUN))QF۴7-e0x`p8ܿ_܇ o777hii R^^Zԅ$~zp8*)@OMMM1w NŰlq^[h=tR]wԩS;[Nĉ !ƍ}}}tX+҂=޽P(o4Ը055WgBy eii&wXِ݄ ^X By  <<Š̶Q4W?""":4}lHj?j,BP=wo0477cŊptt򨔔ppp%Ks7Nmm->S@SSXnZZZX÷Ĉp8q㆘_ii) mmm(//X{.&Mccc̛w6$jllD\\<==ajj ---X[[cؾ}LTVV… AQZڒq8~w֔b޽;444`bb`p8ovvvPUUŃ$KHGw~~>>sxzz ̙3q=:::066رc/U~E۵57oPD7 <5Y} ;;;ٳg8s 222yf̛7|/^̴Ÿql_~;peIK2 |8s }]#''3g!88B^^p-\t m 믿;w`֬Y899Iooo466^^^hhh@QQoߎ#Gwa§"88sN0`X>eeeL}ţG___`툋+oE}}=6n(Vee%q% g"))I%QKK FWHOOǗ_~ .СCPQ;膆!++ Ess3N>pddd 99Y$yuٳm۶aҤIb'N0btMj[vT}oذv킓{=!??;v^zٳgLXYY!''dXv}hZ FFFX`U[^f_0`rrrn:/ www!++ Æ C~~\mOr-#׉*++ݻ|~Ǐ'011!ȝ;w Sp8ҽ{w8---B ҷo_RXX755sdƌ"*gɒ%'{~~>166&H YO|ƭX[[dٲeI$NNNzү_?|W";V/&& ;v`n߾MgggRSS#\pAĭwdw֍[7fFvYuQ\\Ep̸;vp\&N~6IZZ^SSÔ{ӦM2V=IGΟ?/ɓDKKB!HQQ;ҭ[7[L BE17#Hll,SrUҥK.sݻwݻ铁"899 fffKFa@_‚Oee%qqq!e*3!> ȥKdNkILLwHY|]vv6@M&Sޭ+W.].K~7BHPP)--)!ҍC0̞=[:Ҷqj*8@ &+۸ rQw#H߾};@Lo֭Yո311!bqFdlݯ~w8  'Y^!4Xۚ QZZZH^ĸ ۠K.V$Γ'Oz !ȁ۷oCd[INNsaݛqkjj"_%㦨ntRRN,,,D^lIC}!***"y W1T[[K_EUwgEa>k׮3gϴ~)B!n"Le;;'c[:cNJ(.. z!r1`455 ǹq={ HOOf;wȺ K{mmm$''cӦM(++)ɓ'1x`444ȑ#8qbVQQARRеkW a]?Cњӧe[Y܄˘JJJ\q󑘘5k믿_쑺s.ѣDpY2ɠAXA{d422b=FDyĈb~~xxxx)glN 44T$\k]]]7333]dtB 8`muuu@__*++/Rė  Sr˫ۧM---ܹSdΝ;܌3f@MM]-ʪo!---8s 6oތ+W2:C CPPX:5j{{ڵȪ;?HCCEEt"+t?{|p^~ GGPѴpRtp/NeEV^F(s:cI5kkkWVV"""022/vk[Yt[GFI _ :Hbҥp222===xzz>̙3ahhȄmxV75552׍}6mڄM6I-[]]ceejtq8ƍ())QeUQQ-nݺtEanhh ܹAABB8I-'ʪoŸ eꞍ:DzhOYs{iu槪 --N P C[[]x#!4$QH;- apٳHHH@BB̙x8'OƮ]矃Tiiwmչm~+ z&MBVVfΜyPQQƍɜ>_~EsssiISy=2OgIɓ8w>ӧO̙38y$[:u {xTV߿;_ڥ%29s`Νؾ};ƏӧOݻ9FVU=z4~z=666Jc!i"oSt~(Y[-@ _aq'I:P.ł-=\|o߆Lі̲w2fff CXX!8ue"ccc8 >011QJDXWlDZ{* ^郯3ʂ  cǢ k֬a]v+W'OVJ p8fƗcٲeؾ};-Z4/ٕ+WPTTĺT {>|---_@ۺG Hnxxw1Ẅ́YѣBDD>S16"')B=x EYWo 077ݻwEQv>}w,%''Nb~nbM?$$ ől[$,+CeŰ hܹvgϞ)-myl+1ݻwk/Wzp/۲F\dR7m@`u)_CYYDɓHLLΝ+s~P*Փ$;wNE… UV!99駟>}:lmmŋ‡/ʔ"uʖu'>>O׺c|ڴiÇgk֬7`cc?uvvF`` JKKºŋػw/kh2WTT`ɒ% rw:fϞ͸yɸWO2Gcc#f̘!rGdg`ooŽu{EE>cs. ,YEb{eTTT`nnTWWG4_BL̷ ..^^^pssq}VaE ##GE=ペcҤIHMMሏǀ@Ann.0d:uJ$RSS\*ݯ_?|R)!? 2feeaΜ9زeLu\XX樭ŹsP^^___拣$6o BlقÇ###FFFr-7+W1c )) 󃁁 !!/(F\\?ǏٳE>}dK郯 ccca˖-۷/|}}ϣg֭[ _~%e/_5\TTLLL" }v777Ç(((gϰcǎ6/Nrذa_KKKp8DEEQ2)[ם7"""...pvv: qEp\\ kff;v 88'OFll,w7n ??zzzHJJb=P$&&HKKC=зo_ؠ wEqq1M&v qZ IDAT LLL___ ##1bc AVVΟ?{{{ 2D}}=&Lp8::::u*p0k,Uyyy|>233aee=zT$N׮]iӦC .]b|G_mWI3۶m;}hjjQQQ :?P( ryfaر(--_\|O88}4>}p-|WرcD6n܈˗/^ă0w\dddI,ڵkX`\.<3g@SSpww^\\\#00<@JJ o>Z4hVX}?Drr2ѳgO$$$mnp8Ü9spUJ)iBHH֭[KKK}:YHP;v Gvv6> dggK|hJٳ󑜜D%:Jg‰^DG/hljn3rFFƍ'SF[@ BP(`سg݋ &t8 ;z/7oޔx߿_\eV_( BP^?޽{amm|P(o>tBP(B;v |>˗/W]n QPmEP( ͛ƒ%KwMP( 5( BPeJP(sGP( BP(oԸP( BP(7jQ( BP(5( BP( w1vvv-k_ ;wv(6Յa}O>lQD:[}젮ZxʨQp٢P(PְtRp8?T9?_*&|rlذ:u*wX-^^^p8xagsp8888t( -^i&w055WgBP^C_'/\SSNcBP(kLDDDg:[ C@!BP$Ceưkᰰ&zm۶ILQQQpvv6 hmllw}wwwhkkCOO^^^ضmXڭaԨQ044qYV9???XYYACC]v&&=&'LMMkkk >۷og™bڵPp8wi4SRR ccchhhK,AUUU=a9("_ZG?033lmm1sLܻw5 8o>x[na2dhhh```___477GFFY.] ùslxxx0accc'(//GAA[,Y\.Wj=0227PRRv؁#;;zbcʕpvv7rsso!''ׯ_իWaiiǣ_}>v`cc=z㡨Gcǰk.L2tt#G*q!XZZ۷1x`<~vvv3f JJJpq?~?\eyx<\.PQQLXdHp}:իW-[Ƥ#k=77x)gϞ̙3͛1o<|!;v,12ʪ$!k733CLL #,\PևBӕǥK`ll ///GDDΞ=$9sF .{ٳ033c#xƪU`dd 0鴞{ڣ) Eeub6{%|>_ E>nݺݻ H`` a bffF|>^WWG l2$fNN>ҥK HEE~=ҭ[7lٲE$y1r}D B_``HKKKr͛7~EC;v0no&H=BHSSpႈے%K{n!$>> }%"i͝; 3fhw;F?UEIKKBZZZȺu/w'iii{MM ׯ@6m$GXq'100Y8p0n>~B ]GiӦB>沖SCC(8~8@LLLH^^^WWGFA x:::DGGG<#M+RW^%]t!Ν;ӧO pHEZZZe]\\Z7Jۧ'MDSUYY0`@~g2P؈́ӓ)A^]@{{{()ʫ'##~>$9~6޽{ee5^cw&&&Z,;@nܸ 'iY&&b``@K.qrrqNÇ3BLMMEܹ\.kS&BfTYf bccC8}cc#֭rqWeIO>DEE֊ UV9p@&L555CCCBnݺ%gʕrwҘ?>@=*V^-&E-Fٳg$p\>,g7oL镗3/XZ#|}Dk㮼x<,ZynM{;e= ׯ{QWW'***ѣG"~1}2e k[ne^ w ȫ nܽJ}(O}6p8^RPP@!۷oʒhIMbɛ&B ]eРAKizꅼC ޽{"KR|bn%@%%%ۍ7PUUw}={/B!󑓓2466޽ sWQ¥^| 1bhkk=w`bKmƄZ=$$ׯgMN;wPWW;wD 3䒫DAAV^?\Hf/Zklmm1d8q٘0aB]ni 2pe1?MMM;V]LRӧAA@@444aaaZl5((H߇ Y*kiR(jCau|‡c02yInBIIq'MǏԷn݊?6m¦MеkW 88q}C`hh̚5 ,@dd$Px{{Y^!hkFEE<(ʔ It֗=z֭tTT; /p!~~~Xp!~B]],rT[wʊz6c ** uuu񚛛QYY tU.-Z>1F]]jjj%4]8)IOe2y[*}(o%3QWW]]]555022Sܚnݺwѵ4) 5 @ 沆e #\?p1;v gΜAJJ RRRa={7!!!6l8t={ HHH9s/,¯%!IP&=z4~z=666WcORL'M,̜9̓tuu7"22R Äą p_;w;~.Ϙ7|ff&̙sss$&&b033c266FMMMe^qrr2mۆ'S4H=Pڃ2'-a\b86?iLL/We\mAEi}UiR(jܽ˸}6ܤ x| v˦3Knݺ3f… +BN:`lٲbK.38z(O?T̿P)+:YYYpqqAbb"r;99aҥXt)O?!""gƤIf?=Huoޯ Q/Bee%TUU7eeer-ۛ8q"FP!==uٵаdBPZZ*%QR%RGMM #XYYȑ#o.cĨcy\T[\\^풩[la]vYi\t 0r[aeea/hB0EEEؼys%kirѣGַlكzƽBYfA  22R0y&6l WzvvvPUUŹsD > J2))))ܻwweyzz_~(++CTTHHKKŋ^477cx˫ؐ>O;;;#00 a5/^j!oYP]] QDת%%%VJj*3P( @e 55GAA << ++ ϟ= fdff&LAM ;#f۰nӀ,,,DHH sssܹs(///VF. 6밴ATT nnnppp@}}=߿ڊ]//={#rrr 5553\8z s@@\]]{{{#33VVVѣG%dddѣѣ|||PSStL4 2ell0lٲ}/pyTTT`غuLi- JJJ,uQHH!裏0|pdff0n8ڵkptt>}|,\P!]#FEC{gϝ,l%%QDIKj+KjjַtQZ/EKP]PS-BE!-D*D֙7L23 !=8sϜs}99Dff&ua.ncc۷#:: ,5k ֭[8<߿5kT/Lܹ~aÆ ETTh~lCsիqm޽-Z@퍬,\|5j RmxWj*"** r탫+"""~<̵C||<ѥK(Jj SND۷]v ι{Aܽ_nݺE'O&???L4k,wNڢ"Ϩ]vdmmMB˗/9PVaɕiժ)))%KϏlllёڵkG|egg7tӭ[?IP;ѪUtAرc=dkk+af4`jԨd2ruuӔ)S6ozaÆqٳgݻw't"''x jڴ)) 7|rss)&&uU>H:tKoyzz\.-ZܹsIRYܩT*Zx1iӆՕ B7}7>c<ñc/uԉH.ۗcL4i5i҄d29;;S^(!!dtk(&&\\\HP3-Y[[SfͨO>3s e\V[?'|X1ާ4mXɉr9yyyQ׮]O?Wj+  \N4n86z%s_'///"ԭ[ /Zd`0jp7kL5KMI 8pIJdBBziRZLYYQ>'ټy3 7|-kqi`0}iӦ5yΝCMʳuV*c04RRRPXXTzd0 `lѵkWv`0 l`0 `0r`0 }u(`0#()`0 ZwM*+xr%N.(hVOIVPe$pq(Q6VR(R(2'`a[V<A\ 1=w Q=wooolذ`0 ƿҲLTp8&Tehߑv:RDb*.D=|T^H7\A`0j1 QO "C%R}g)MAc 2Tci#*OR* j@5`y*ă/xyn-d0Ô;`0 hΎu9hhcB<qRG]TjRi'I+d7h8Lp2K/|`<Ԇ3 f0`0zBEDSջV;JSVR r$pt(,$N<@4*uWMx 1 QOМ!'UL zX% OJ*x8 8 PS%Ri@cݫ'4<M^)w QSr`0 F=rD"duGJ5V7 XD'*$p|n|5<$M9 Ra# 㩇)w ` gCԨB|ldrM'HT*QTT}Yhyq 9Lc0 Q[% >,nܼn4D"gc/:tHGI3Gc`.lV}(((nըQ#͛qz:'I&8l۶EaXȜ9sq`зo_p:_pRVV4j-ܮ+m0[G#CRK0+脳˿oӦ 8Cnnc=?r!Jѥ˗/ݻN\Æ x 3)..5peiBCCta>= 1ZKx晎R2L&Cgpy4o֐d {{{Z Iyyz䴒ZNNh׊`05dgg#..P*hݺ5㍦sL-[BT =z={̪cǎo߾pqqqD;;;899p-755}lmm$HRR^x8888y^ 8,Z`9zq8{,`ҥ\rEꈈ={!%%k@II ,X`\k7oތؠA͛7-n޽ƍC֭n> OOO( #$$.JKKMsڳ*h"ӲeK7gΜӕàAмysaaaXj' ֘୷ނ7J%Zj?<接ȝ#GJ 4@`` p5ɓ'1l0xzzj,X9r$.\`P"²eЦM(Jxzzb (t*UVV2!77w; ZjVк%ZG@=;C`t }:u?۴BlL,?pifh-"eC`6oFk;deG,oKƣ%ܹs'OFf͠P(аaCDGG?K۽{wpV\)Kwщ[`8ŋŰ,L>=5kCbfI 2ѣ n.)޽{V^3ϙ3GOH899x뫊4ԩܠP(1cիz?0`͟?aҥ:5yv_\ ǢEX5g~"dggsApp0 pqš&MI)C&MHHHҥK1qDdHJJ²ev!==ݠb.ưaP\zD=patvލ+W"((ǥKsN$&&b׮]֭Ų`֬Y;w.1yd1I&pssٳj*ddd`ʔ)ppp+QQQ8tѣGaCBB6nhp2/' 008u~g=zgΜ'w" ?<>|'NO>;paQŋ㭷ނ\.Gxx8<<}:rrڞUq}Ǐ`kkk׮o;ڵkѣ #++ )))HNNDZ|ru?1p9sx饗ٳgܹsfGu+ѣGt (**µkװrJM65;-|w7nT*ѹsg\r֭۱g%ǏNJ+`kk޽{C.cӦMHJJ[R44V\YZZR4mN<-Jr ɽ[7PXT8 $ @s26v[h*/^DDDn߾&M_~Į]k.,^o>""Cbb"Zj%WTߏXNBBBp 4k {T*Ezz:~W4nXL[ bccQVV:[nHKKw}-[`׮] WWCRĺuо}{Ox d2ܹs/puu5_~?:v+++a͚5غu+>Qs~-RΝ;8{,LI&Yk~`3%s,Cˬ3aޕSi&RT&]v";мyٴif @/q7n$F*J /,,&MZx1j1ɓJ2.]d'N$q}: <`mܸ1r:w^YGi={65kWמU1p@@zik"7nPJJӖ-[T'שUVu➄~\c~ʔ)P ՕwKƒ%r>իz*ݼyӢO&LF$y:sΝ; y{{ԩ=:u`Z2*..B*((л)//)==.\@OǏSJJѣGĉF.]Lv*s;{A@C)ӓI"k&T*rpp sC||<?zCOqݻ@~y>\$SfرwEaÆ*P^ĘT~t0ZM9={;vP 3oիlll,ȑzq/2fΜ'wqCHٳ\VСCHKKCnn.T*@Ry\zU\_Syvݻ0zGVGm`sϒ9QS!ÅɹD ~:ॗ^,|}}Jo*U۷QRRbK19G1P&M K$… S ~P/_Sgʮԗ/_`ɒ%Xd ѵkWK2dHy^[liR2Xr}Je?1m(CxyyA"]=c $''#!! GNЧO3Fыi q=I //F֊r+xAۿ?nP”)Sh"Kdh׮z聱cQ6w CTu_p!&2>>|8::mQ[ܳde”z9/SC0..528CXbEyQ[/i] 10ENCij*o>?5ի777!J ]v믿sNܹ-[e|HJJ>+V@XX>ckNNN™3gdCY]K?Ď;~8pϟD`jZABQ홣uo2Ywyf}/-Z@nn.\h JhOԹZhՍ*11&Lйsg <<CРA=ϗ_~^{ ۶mþ}'N`…0bĈG&?dSԔ<(((… /[4[n5%,icTr/ 'N@xx8Xz6]7 oܸ&(,~{ rh&A^Z:֯_@sC_jssscpi5 $.ݹpFd,^¯/^4)c *[L\RU96ǼPa%ƒd!<<4fΜ+W/vmVZ;;;8::xtvvvppp@NN Z}r/<|b?J\ |}y ׯ߀+JKKQTRFI_@ƟXcϽz|݃e#?YusqmmN2xӦM d,Ֆ...Xp!, ߁6INN6$|2޽kr]D1@q:4o©Su2neV-dDƭ dfd"Sq+ۙۙwqgΤ!33gNAfF&〓'NLNMťKpiS'O!f:N<7qIdJ-u?ջ˗/z˺s=@s@QQ^?N@Xy=,[ H\|k׮Ջ3B* VݺuzqD$W\j\W+##H$x0sΝ_.q/^T]{{\E,}V%s,[Ӂ92|Mqqq~W1ÇChԩz^JKK_~s!m +֭[?~<aÆ鸓^z5I$*e+Wpu][)r/B'nŊX $TJ N8!gdd.QQFH&QnnAYOӧ 9r͛ԬY3P"۷oС^\.]PUzиqt<ݥ  T*_mڄ ͘1äy5=}eddx,<ŭ]V'ڵk8@/NܓЏk{ G!ۗ .Ao%K^l?8,I{IdP(hݺuzyrrrhٲet=1~#K7nsssEos0-s֬YUz4i㩨P5Jī*\UJL/UTejTjT**-ӖTSii)qi^VV&.- |O'Nԑw߾}P(ʊΜ9'RTB۷o'"ڼyAOW\!{{{:GC8 8Z~Nܹs Qqx)Ο?o벀ME~PTPP gggW)K@l21ƍ'1-ӜgcH* رC'NVo|=s-yY2>.L oߎh,Xk֬APP6l[n>֬YSkk~m]?K.6mϟ_+믿iӦa ĥKp( |P(bZ믿FXXBBB@D8uD:xK.P*hժN*oذ#`ժUٳgСC?Ha߾}x!ZiZ P*&8q"V^+W?D푕D 6 {Avv&L)SбcG4meee8u.^///5ڳ*V^7n`s='b~)L>]Z:c bȑ/Ν;'Nw->sqm? رcZhpc޽͛d,Y"W_}I&M6 L&Õ+Wpr|'bm߾=֬Y1c`ĈxѺukHRܼyΝCqq1EKRtt4^}UZ \.Ǿ}ꊈífo cǍ19OA@ӦPTT;;!=?"""l2ڵ !!!}6</^mq֭Ma]qqv{Ŋ+wŁP\\?ؤ%nnnXf bcc1|p,^͚5ٳg{{{lذAgڞ_ZlVZѣ A`` Я_?z_|Сy8::̄?,YR{Fv퐚 ???t * 탧'3gbbb0qD\HMM^C|||ر#kL0}EPP49+3̱rr@PPΜ9ŋc8rx}Y p?q!tVR|]Ϟ=9s`۶mb'|b聯 p4j&L~he Hclܸ* ݺuaÆ֭[o}vj\ 5W_aݺu!Hкuk3ƍ0eee8s \\\Ke7ocǎ4o .oVAXd 9sNL&/>L< 6}TמUѰaC>|K,ƍѣG#66VL'''|8}4N>`hڴcUǵ9푔ٳgcؼy34i?ƍop9%c\͛_GݻQZZ ///=ܴ0b<3/o>ٳJ7Ɛ!C0h xyyYbڵko6lb޼y5j{\Ə7ΤF۵TQ 驳Z޽{뵡1xlٲ%N8O?;v͛agg(;x ԩPPP۷U_}UHNNFnn.5jݻcf4h1o<$%%ɓpuuŨQ0k,h61Dm/>iӦ8~8^^^ׯ/@hh(.]Ç9s&M&*"p|رc5+?菫‘Pùs琞ݻ>O?T#*k}Xp!p94hZӍR[̱ ܬ3i֬z%կsOHH0%0!!={4[@x?ѵkW|`Ԅ;w"::Æ 0L NNNx뒹sCJJA QW۷M65xޥ!x8w:njRZ\ߑܹ2* CCbb"0qĺaȡK[o^~-R %%3gN]XILLD>}b`0e2 {g{`t%$S S Q#M_FNNlmmѹsg=J]`0 ƿ1 F̜93gf0 xa{ `0 ;`0 0`0 `0Lc0 `0zS #$%%!""8!77FeN4 a۶m$,]Tcw}WgY… q-ZTעL߾}qRSSu9C&M,.w8N>AAA'}]T*2SNpssBƌWΝ;:u*acc'''c֬Y6ǜ~ghLUlJ[F|||;w#>>Rzqey&F777X[[SNذa2귕ˏ{3 aX͛4h111y:yb0d̙T@ɩڴiT*]vtRRRHPԩ >HqmݺޞÇzR$ggg***""\%ԬY32dR.]HTқoIDDwޥٳg')Sٳū"* BAaaaԿ!ON֭[6mI$ ^x ?/ STThт=]~,,,]rtt~Q޽ښА!Cy""v͞=zAGܹhĉ M:J%y{{SϞ={tq׬YCVVViԮ];=Mn%K1bILBr7nLԼyspݿ:uDAԽ{wٳ'999:t'O$WWW@M4_|tB2ҥKdY~=qG"##iȑԲeKQF֖ [rr2^zI'y;v, TJaaa4x`zg֖tbRСCaÆHN:ꄙ:'mڴcYqG-Zk׮$bb"QF[ڗf@I H$vZj۶-4={${n1l֬YVON( """(88RRRh֬YuƼPαcߠ,#dɒGn߭O FB=z@@666tYz7ʊy$@o^F"( zM/"5i҄;wN/ŹÃO}͛ڻw~ghL ?bj֬9;;Sdd$uԉ83Y6wΝ;ڵkg0^qN4bիXUo~m@2^x4h鳲Ĵ7o68W s>n݉,-yX0)cbqnݚz)k&M(//O|sߡuGBB]r233MnݺE7oޤ]v3mڴ$=̐6kLb ^Z/իtM$ꫯMN… @Ǫ(--%GGG@ǎӋ_~XEr׽{wD"!#FZr2ccc ٳ$UK988XWQ"/q!py@aaabʕ+T0/_. ߉<\+ʝZF,ӧСCf)w ;ZMƍ#ԭ[7zYPrgN_7x輤VEzz:I$볂>e;c?(=**ʝ+ݽ{W+V;l0@۶m3YmےD"ѩKx dd+'Wo{ d$H(##C KVI_VVFnnn$޽{:qݒyђ猥 c͝;W/n۶mhC1ꎧAc{P:t7nOji#GٳbxJJ Μ90nZ> -Fzz:ڴi-ZrgΜыի^P?\DLKKKÃ;ϟǽ{L*6۷^3ݑ21|Ϟ=84XVdd$spqqAΝ.c^jp޽{AD6xTDV#/eРA&hlSK8{,ܹ{NJ.]̙JJJ0tP\Ǯ]js9}Ұzj̛7s9sĽ.]2 ///͛w n:#̒w8]N'M+UӆbZ`ҥODU*xٓw^1c̒6s=gp\sa{d,@ L׵kW 6 ~{!ȑ#||| u] i1$w^deegϞpqq>*jμhsq=3 ѧO0CP !'3f 99 HHH=:u>}`̘1z"^u9rꫯ+Wk:i0e,Z/d2ڵk=z`رh޼r 妥u"?zXJFIII{ŵETPDT8E|AESl Jb ĖK,/5+%D j5X"+u R|?pw\fo\Y#b|2߿+++(u 4B˗򠳬$ \C!8::..]KjC"Tf/MXuΝ;v @mI$aÆ}mmYRعs'ԩSmRE},;^@^^劌DZqF],ʃemUʮMԍiff\mqZZ4^ܺoߕ]>\)SwSU:YT^=c{lwHMMŽ{`kk `OUnmu9T9CUIk("UR 4ѣGqIݻǏGjj*=yرc O0eQ\\[ R7ƌ]vȑ#@vv6.\k}W[uVZWiFXcMʫFSe*&_###L>]U=>2Yu*;v,5kvyM*ջ?hm?3N:5k`ر^:N 49111pvv)b1,Y'B All,oߎKа\oSW}C>}>}@"`…ӧ_0`U[eʓWe]\Ut-^Hp̛76mԩSKڵ fffк4oqaРAZ-))?ϊot%/))ںʥ-SSSŋ3f|{j>>`ggl"<<\4666ov)Ϳ}tCII Wgew\\U155E 3婼KꔧM-ƏXѣGQUΝ;HKK;֮]4{Ǝ;~6m_VYruOTUQax9bccɔ8}4\qBK&M@Ck+dsnMxʧw'Joyaƍ:u*vڅ| 6Lu]<9:k(z7wHƍpBPxNfܸqtT%S###?۷D"QR#8Q5QvЬY3\vMo~mѶm[_ř3gܹpuu.JWLٳϞ=+W 6h>m6yطot֐J*/,UqwwGfpro۷+кK:e ЦM=z7رcU 5MXUWB$%%ow~'\r>>>.gc^vʕ+JO銊꣪i*ŋUثW/}{.m&_ո\ZZBI[іlߟt9>JEмx'O*]ѣnݺr5ouɓ'.rR)&O-M`ii{bt뒩X,Ffp} [ݻwb BƪPUQ՜7oF~~|ӧO1j(:t(lmmo>̚5Ki?W7].MdsgiEEE8q"Ӳ|rԩS]?cܹsn ࣏>BQQBCCU>C/ơC`mm ???׭KyFs:e뺨PnbpWK-Yh׮( ,, /U?~>|^^^pttD~0l0|hӦ 0sL~Fhh(-ܸqDhh('''Ӆ.] 33NNN A߾}Ѻukܸq!!!.RYu OOO[ ""NNNF111H$ :Yv-||| tйsg&&&HJJ ,Xaaaҥ 5k(\6m˗/T*E@@z쉨(aݺu:tʲ}'033͛@8;;c̘1T8q"WM6֭ѵkWX[[#!!Az Btt4n߾ 777 03rssѭ[7X6A]EGGcZ5jcƌD"'ggg|4e``Pz ׯ^قQ\\ DFF":: ,ϗu'aooDtUGU Bv퐓'''aprrBnn.ԯ_?,--{߿?Zn OO wL]4i:t _T%$$'O "##Ν;C"`֬Y*jbʔ)x }ۦ$pIxx8b1V^ T!CE]gt=ghRֱ~ Ewܹs1|p 99?>}#F ''=zPN6\'1e4mزe .]={СC2dϟ$%%aڵJ]-[d<ݻqicҤIزeK%Ԋnի|Wqi+V֭[+ԕ."""hCرc(((@hh(~:Xr%pE$&&իpttĜ9sܹs9s&lmm={ܹ3VZ~)йsgc޽pvvFzzʧ 'O;;;o߾*ӈD"|wزe |}}qYܹnB=0c fʕXd o>8qɓ'Q~}ѵM(G%FUi]*ҥKxb8;;#%%FǎO?U](aiiYU`7R[nڵk.2 m۶.]™3gӧO"ZUQ ?&&&ؽ{71|p:bǎqYL0HJJBjj*jti43f JJJ4'mmmq)t8z(ڶm7"..NXhmoooc׮]055E\\233վ`mm4\vQ. M:uU#¢LjIIIQ;e]@*UVaرc|""Z.??hѢ+;v@hh(&N?5TB"9rܴ^%%%x"zUD52TsN`D裏j8DDDT?Gvv|t""]16mˆ#k׮!22\wƢEZKDǹX~=,--1rH,^DDDDZ244џ$ nܸAӴubp-[눈LHHH] 2SSS-A~ 6MKK22#"""""A`Or R`pGDDDDD-vލݻw+tÔۧOrKll,D"vUEjD"xxxtQ*!0|*ɿ[nDuV_mKum… !oСZjTZ'""Ro߾VާOӧJ;""= HwtQ\BB\+WtQ/;2/K.E֭$'"$$U?9y/Q`ll\E""(Yp'z]×0#[[[VYOQQQ6mv؁Ț.ǹiYK~ϩӧOGaddggg|(**RJwy̘1^^^hҤ #GƍjL:nnn011<<<'OYޒ@$k׮xׯǀ k֬Q{wŋ4iallVZa())),,,nɓѲeKz¡C܆O>Q*ׯ5̙32dlmmahhkkkDFFJر"&M1l04m._vժUh߾=LLL`kk3f|HS233!RPٳmT&M?V~X,FuԽsWXXo^^^hܸ1ի;;;W:U>R)Ν ~)^zףG0m4 fffhѢ Ǐ~D":u `ooH$y!.\???VVVݻ<ʠ1xa~hԨk\Oxx87'wׯ3gΠW^S>3g"##{QqѢEذa\]]ѡCԭ[ϟǺu되th Ǐamm HR\|sAѳgOe,**СCuV۶mw>F xN: >}+VP///8wlmm1p@"!!/^T[x17oHMMEJJ -[=??ݺuÙ3g`ccŋ? .M~z=Rԩ_7")) RGĽ{^z!++ W7|vN¼y󐟟%KhMĉT*Ş={ òe˰uVO6mA|5[Ʈ]аaC GNNpN {{{cǎy&ۇ`Æ r n޼CBΝ5ބ ~G<\ ""8eDٳgel߾]JZBFTٳ`nn.;vLa/D"YJ۷ow„ MhڴPcccnݺ£GU~}dddjUؾ}{ݻw BFL333… 9v|r| )tU ܼyS>&\vM>˂@8w|UСC3ٳ :u$ܹ\999?4ѣBz *Et] fffBݺudtT*7N^g_mIII*UD Baa+˗B~~/ D"Seٸq#nݺL0Ai'֭Sb\bK,|;L2Q\\ [n "##k׮ѣJirJ퍏\xf͂B9Te:ȺZZZɓԩN:~¼s_~'ܔzu=򂙙<O[uzj899oٲ'Խ{w<,,,Ю]r}Q޽{wDGGٳgHMM-Wr nذyyy ?:u`hذurrrt.7QE~j+O|\4)))Z< %%܅#"""""zizũD524P6{{N """"""cL""""""=H0#""""" ;""""""=H0#""""" @1OLLrQT(رce*B] *DDDDDDT|玈H0#""""" ;""""""=H0#""""" ;""""""=H0#""""" ;""""""=H0#""""" ;""""""=H0#""""" jӧOP2 j92[ """"" (***s>#"""""JwdL"""""wT鮘IDDDDD*2!b[&;D]WLv$"""""znDDDDDD6]1-Ӧ+&ertԦ[@ײQ5cL""""""=H0#""""" (>.NBQ˙AIENDB`live-clone-1.5.1/img/toolbar.fr.png000066400000000000000000000341551356647605500171360ustar00rootroot00000000000000PNG  IHDRTO=YsBIT|d pHYsgRtEXtSoftwarewww.inkscape.org< IDATxyxT?ef2C`X(.,.R՟[)-"K[QP۪EUQ[, .KEE (K$!d_f&xrg $rs$4hРA÷d<%Ihnnvhp"!!dt: S!8^o%X,$&&p8hkkuYFBB---\.$o@JJ ;DJJ :f222X,].É$0'mmm444rB-TN޽1 ]$I+rQPPХz)//'##׋Nҗ$ EUU8NRRRHKKt:>%I6V+nҥ}ᇍrV\%\ҥ ٌ8y Cw)g'gwW8ޮ^W8wχNT>Vf3fY5N tu4p}Gqq1yyy'8'2oA IJP78y+u8fߏ+hyDzACgQVVرc:u*F3:;o"cБ$IYA:+F%IMG @HjF$ce>,n7$y`tb2SpqENTXXHnݔKDMM $]%ICq!F#EEEt]v, A|>dff$!!GmmmPXNd"===nqHss3Ad~rrj:Nil6RSS=555߿&'--SJ6jjjطo,h4*yb2vUCkk+1qDz֡jۇ$33<]$8NIKKS'vz٭[7z<lQ7&%,-ɡ[VngffƥDQˣeINNAvLnoeTiD^>ۍvr1 >GD,s4btzgMjZdfdvq:c6øQQQO<믿׋fܸqzv9s&Z**!x<<裔*Fٳ))) `{// a׿5,Z@)III +Cff&K.%??VnF %f1ydMFVVVX|9s!%%ɤkvv6cƌ+dРAAu֭\uUL&ĴiӘ9s&:… YdyΎZFIصk?X~=VɄA3fECC]vGfˌ3={67poj /?|Okx饗=zt+W2w\6nH݃|뭷lL&n7mmmL0GyD!{/+V --MKz^ /O~ BTr6nHSSǃhQ[f7rsGM31KڊU:EP@13Gn&=-FN'iiiJcU|>Usҽ$!$2Sz68Nb`i D^f&_>f^/e ߟZAy>|[n2f͚gMnn.ڵK{Q\\ tXoDKj*~2a̙q\|g4srrt|>yϟ&OLNNٳO>$Ռ$I|x$''0bөc۶m<ٳ,$In+,8(y1{4hP={BQor}q9琒B]]wf1r$I!|466*n7<Wf޼y?>(/"qkoo'%% _WdddS9U_W8Z}z1\zɥ.ѱ8TNGsK.W;t!QlRD xx[f&CCQ:lXo%}> ǃO2 'IHۇDkOBb*ùCp`Xػw/YYY457gq466FݲxxGعs'7n2޽;gy&He>x sGG!==]BJ͛ǿ/ViFQQ?8wB)#SRR8UвSZZsȑڵ_?qq s9K/[o2|p%Nvb JKK/fܸqamfn >,}Q%''SPPgT%$I JJJ֡իWsWp嗣:qyTu555Y+2,I&)sPkZ:thМ)((`ӦM|GAs!Z9CgXl8L&^o`Уzj>d0b4d4`27VF#G8ZSG6z݋{njǕGwX^h$!!HG"jN<:݇BڅᠰBJ{V-. ש<\wu|ܹ3,3gRSSʕ+$:cGMM&477x:?}nn.wy'N_|Q){<,I>ө(z;ټy36l`ڴiIOOGWK[[bcαqmmmnFc$I/^Y; )bfsNu^ ryquLUQqpNodCkXBp8$''ӭ[&Gk0 f ~m% -'xHZ00F 1bx<>>I@Uj˅n'33Fss3II$%&iii!999,H~;v2bu` 壏>"//GLs{e֭1"[qq1W]u-⢋.W^a ,ngǎa[~B~JбK!ڽ{7z"!!!1ev;6M!eee|Au:zRcgu=O<&M"//DL&S\֭[lJ~~z|7aONGaa!III$''3j(^|E9r$={l6ǥ< ,s2~ɡF3϶6EҥKIMMeĉ6o%gL&#33O~ŏl_2ٌ!DYFbmG7oxz>6nX*K III8m+PE9>#%UOfVGr yyyqwӇj`U{tFt- /d475NOƏnz| );|޽imif)[bXx0HMM#y< :[?Ū򜨫$~-LLF0*}gXmt/M #n,7ZCշp8Z,74=уz(Gnz={**Xe̩koHJԣL_$z 7O?ͥ^J^ygFعs'J̙ԩS#ڵkIJJb„ qGo^ϝwɤItM;773}t>Ezj8 {1EoӧrFldذp'77WNg嫯>c׮][e˖q3os kmy(wKcHNXs4HQǖc dfS_WK._~quVFrҸ,:z]m^^̌Lo8u8hmm EI  ss9PUEǞoaȠAdffo~zRGmmmuGEEEض;"}BB޽[P[[K{{BBNԩSYl׿ɰZEUJ8syꩧ$*{9-ZDii ŋ/HJJ Ǐ(޽{(Rf3%%%ziii_#K,;PMCΣ:Ť(k(z=={ԨQn~?~<'OY&Y^/Zuuu<,^ &p+f3 ߷o_NYY=cǎ%)))bdl6J}}=[ӧ1WyɹH0 *m[)et§|/CMyF.+СClVlʞbۍ}Jnhll[nQUDDK?1ư!6Kճ399|m;FׯÆsYgS\ܿSyHDBQ^T~C gIݩl8p@i'I'++M6ťQ[BQ(//g߾}a|>6lh42|妛nbŊڵK5X k2Y_qq1~;}PLuB{UVod׮] :Tɵ`z=SLQ;'$IpraZZ1R/^ÇU477+ʘX3a$I*' Uƒ?D'deee˖netuikk믿VUvPBjj |>>S2/15Vy) I/YBY3H|DPV@s$dJ %9?H%{^/dExv3gK.Gh9Z[[ӏq8Xz!tlڴ ͊Qo`Р!dw K#V99zN[HKMUd5O>$N;}FMd2ݻw3c fϞMii\>}pM7)e d}O>̞={wsrӻwo<_}iiia@m0ddd0m4f͚T}eGrrrD 3G~_3sLf̘HNN{dnEv+Iuuu|a?11$I0Pc)))Ջ:~a.BKff&^㏣83"D]|,_C*ﺺ:^u6o$=r .d„ ǯYqAϟORRǏW*I¸޽"׳f⊸N1 $&Y+O|>/;v`0Idȑ#x]n! پ}= Pۢq^V`Zkx@n ##d9A^!ׯg޽7j󨨨Ipzo\-\tяp8466R#R_St:dܬY77o?)ӟn#99T|>UUUɭaÆE``֬Y\.^uf32edn$HVVV&$$P[[ӕ~]\`̙fH:/i)xrrѣAEy;o>|~_=z rتxט9s&. NDž^˕tZIv^KK S~:&@o& 7AnKmm-YYY*N5NFyE z=zfnHNNf„ ޽;Cl6fY1|5k3g ˣw^HKKO>[!Ē$q'd( } AnD<*w]]555l+?Aee% @޽)((POZZZ֭#///'???,>͍>NCm:N"K֭㮻R 0?0,O/8ԣGMF֬Yi- aãƩS'F+ɪcK-|r+??_ukVPfQQKh4yh، 222bOTIDAT'.khDhit&X>\#/ּX,AG֯_䙬ZyǛw\JzKqbG>2;"XKvQ*F+g# A'"d=C/ "Ƙ1cѣG_~_xWNv4$D"x<[.n!5R+VPdzox_x7x*֭[/;eʑ35k)Y}}rd r!'I^{-˖-So))){;L8 .~;يlӦMai{❷{Qd 8薖VXѩj0p\3q8ر,?|, #G?,|#s!_ȑ#$$$0b^/?ϱ~\.E"-?&GAAÆ #//jT\.Ee0x4.PPSRRhmm voذ /E$zoW^ys9'J@ $PSSCݹ:t(Vb|'JcZill믿NQQrM/2eVZ8 ..+jǂ|6n_·~N[ooW_'䮻b\wuxAB?to0ez=o?яx뭷Ov5`x<J$ּ]z5'O殻^#--ŋ>۬XB@_ AMHHPb:t{",YN#77UV1geV1y7<ʱuֱ} 낤#hxIJJRLKYv-O=T9m5t V^~;~m..cڵ,\䢋.b?$K/)"χb_gt"j80 Cm:8 (?07|;wrF ldQW__9Zvfnwy'svlI,X k̙5 \\\\jcI+>#G<-##~dcƍcվmڴ)'~3$Iҍ7鷿 &! ƌ3b֮]' zM>3~$tp1p2&m.Jw~u2P#/-[1Cit\s,vs 5=[\YjРKp@lF BS-@}d4h2uW#pKy`]_A.éHP+2TF\h2gAq*TrTƇmEUo^4` o,jР38U V \=@>B<IC ]l`ESĶoNo~ =b і-V~H^1Ci=ЏQ wr|_0x L" ѠA5": >XA[mH'ǹ[8b"!WAֽwLw "8@SOrhļ?8!B;^U26dz5FاDSq< !+9"2 ]: q2+܍0B;pS9qPGx}qt%fv(~s[:Ett,jW+i?wAv*CV`Agi"@/`?FYĸ> %A= DM09 TPSl ¨m߈wAOcv0Az"Z |&ɃwD-c XU+`(!GEZq"V@\`M@|hq= dž6S !Grq' r.a[06؊܍08((K>r=pf'ʦF!ڪx 8} bZ; E 0!o"P!e; HC*I5G)jV QXJǘKE %&)A$?1G!V{BQAǡItaQHjs8[#DZWlDLH$:XL !;Bsj> { uM 4! ).+ۈ$ pFL/^ HHAl VXGP{>N 1CP /ˀP3?+vuSQVnqP6U{V"%9(v5t(m% YN`?">I`cLB hhB &u@-B{z@.BmCꅈe`H= T{-Fpn!k ^ p#93!q_Xld#l-S-@)b 7"y ],؊~AA }~{[QN+j4sƱ~p'"՟~@(?VDpYU`COgWDaDe o::L"`,6 يhPZ/@Omud>be+bnA4tWkР0 hgpa$4h8XK9"pX8ѠAIOf8]qbJ   ¦l(/wӠAAI NO30jV 4hРAsB} qzB>e$#a}3֠A ĉÆ8e4qqrDOp 8o3 N&)4het\BYoubixɟoCՠAAx |#]"·tx{gӌDP 8P' AՠAw}L?s]o, AՠAwO"k1FCrb{>-Bey%e7p/<  u8G K=4h??#UwԜF,=ڌ@(7< u?=^[OEѠAc9V /q}<&Ƌ;NW.Dx|wՠAI U-@ Poq*>9eѠA)qTcy]݁8,DjР G$[CY j | 8u/qKg, n*'[< čm ]' 4h8p<j;AS E xF`D]Іl:elC nԠAZvOW'T%Nbh6%c}Rh 4q <v ,*}'N@T!(qoT68=_G眐4hРÄ^vqrj ¤Jj#?q:58ԟ" }6{ ڄ_l> (wUנACq C P{"A"W;Ug*F ';Wm@]@\BTW"NLiРAxmIENDB`live-clone-1.5.1/img/toolbar.fr.svg000066400000000000000000001244331356647605500171500ustar00rootroot00000000000000 image/svg+xml Aide Outils Lancer Cloner Quitter live-clone-1.5.1/img/toolbar.png000066400000000000000000000316521356647605500165270ustar00rootroot00000000000000PNG  IHDRTR ,sBIT|d pHYsgRtEXtSoftwarewww.inkscape.org< IDATxwxTegf22! = zf٥| *Zlkc](~. baHQQ`Kidd9ϜaڙLBsMr~I :::::gI}.Ӣs!2 tz.ӥsQSS,ˁU$ ùLy%N+ajډιtR__,:)::$G\\9_Sl6dYFQZw@6m0 466bۑ$UÏb 2jILL@(ZF$ѦM$Ifpbcc$鬴Q8-ǂVxՑ@}}=999L${<:btDrrr( 0"iyy9Ʉ,UG׊TVc\.,K3Miv3[[y<$Iju9_&ri( Nr4:ZiJ&϶ &zxlM<TWUƆݻ1dea6i`>a-3~/K)Lh4v}fCAAQ@QdeBdY]‚nwpwBdYf$Kz$ڴ!˅ 66>+WB>}QSN1p@V\9ضm[w 8N6oƍ9z(qqqSTTDΝq\|WMnJD޽ZYmۆ ٸq#;wDe ڵ+:uu8?H^ Ν;ٻw/999tIcl޼*RRR ر#EEE-Gnp8P,[bl6![F( Bm[VK۶CM j~7[U "˘c \'.VڷiшGQ8TQdoN$ZnN' H0<#2_|O=Ύ;xW`SQQτ #oOUUU>wru1iҤ!_}<|tx<̘1I۷/$r:u* 0+7n䦛nb֬Yv}q]woҶm[ O?T:vbaƍ>;$a2++G4A2BR:vHEeGSǎbvIrRRTZkp;OZdEAT+6{#F79mPF j=3J}Xa.̑#GVZJΝ1M5\5GC_b'NdСL4c6q:;PSSP&jپ};wu:uW^!//D]]-GeLx`2_dT='㜕_|uUUUwSZ,˾4L&F-¦MKCܯ_3eRx;v,>h;Yz5/2O>$7p ȲL}}=;w$==Ty着s=[o{fZZ/n7/"3gGo$%%@CCwf466.=_~%<W\q_IKKCeΝ˷~믿N޽ra(-- ۓD6xHLLMb4T;pdddRXP#syhA_`SxdJ I$I1A#Ӊ墰߬d@lظzbbb(.* t>^3˗GsqhVb&O+-}iӧEEE|?vϧwőQӪ6l !!ѣG4bHrr2}?( 111L&B? /mƄ z у.ؐs,X?\s5L<ٗVYo())_~p- Ai?Z* 1bccX,fEh4i49BB|V6hm'ҫ$IIMD|\zceG8YA^~.i|ݷsi _35!Ʉ` ǣ`4ܷv=Qň^MyJZR]]M0P%'#UUUEؿ?,өS'ʹ5''Nرc'Φ~-%>>'r-sp Wy{Ù1c $ر:a }7 KOSnj^z%VZرc}ϗ/_w]HثW;0lذs0C aܹq\yߟ< ZM"SbӦM撓uY8N^y֬YQ+-vF{}H&K|||vEn3p@ C|8VFbȑ̟?wg,SYY[m9NVX$I <СCy),,w;`ȑr-Z*DnNE`l6xhhhTy9?< 2Q=m [Dl4ۆ(hZ̉)xFǴdRQ<3%,9|w8߷'?e]FR9"/2W. vɈ (/me<1& E)+;A{eEM&lBCqQڶ%--Y&>.kGpVC}}}U?j_SG!2.gSQn„ =Equi%8].bFٳoh4˞={ؼys@ڵO>4440gG)eXƌ?ݻڵ+۷og۶mL6-`I ȑL<9$fHDII ߩ~~øqB#/=uuzK||NyI^GLR&)!uE$0"l00ﭷ׼1 6:B)+2:3ETWWP__Om)<֎)YY ml^WO?rq>r3޹E؋*#DnVHHH|ʨ 1B+'77޽{[ . %%۷kڭO<ѣGԩJN=z4fɓiQo >裀.{^^G]v:t(swyg4h'w4t>3n7},q&pd2E]Ę1cx)..歷i.uh4ҩS';ǣ[ԩ/{w[j[Bvv6]v宻b466`ͺגzlR tMw5 tǫ\ $xZ)P#&XQ`r̯e˗G0v5u\Z 9O>wOQ]]+)xfmv;9uqqq8NN-ZL|BXMӶm[z͢E ޚ5k8tC P6z,Oo𽂂ƍǜ9s8tP@111tŷ0c…ki;rYp!{a…\uU 9﹩HDFFu-ɛN{/5S)..fƌs}u֨򐛛Kff&Mk5|ٌb!99 Ӊcbcv> d`Y&6~l Ue$t@{'%r!$-kqEeł@ؑck$\ׯWM%ܐMel۷{p18'|kk׮CTUUc Ԧ^(Y,8vKBuE.Ē%K֭{}?+Vo߾#hۘRSS{Xb*NUDY?inj^<n;e8&L6mowrmذ 2K/4bs-0gJKK56RY Ǝ,˼K8΀N'8|M\.W@8\.WT嫺 W6B%\^%Ik<ӔsWG)peƍ:t(@y<CiioRE#zu]Ǵi/ill 7xSNmEEE̘1ʽ͛}yXf yulٲÇs-hdV3Xb-ҽg7ڶ˦˖ /Z88TZ4h$!wČ^%ȑihhipQbK,&<+0M>[Rcc#_,Ye^*eYf=y# $XrO544z*Lw<(FvIlرwꫯpo(в%yۗb"Dq̘1TWW3{l/_[cǎ+'|޽{C=z4W\q_~9_xٲe C !%%[l2 x'|jhoߧԻ!{ƮB r;3{̧|=C>}Z=zuH>}"ڵkyClf=z;ߒ.b>c.>s;rW_}{Gnѣ߿ŋc08qbpeqqq<<LZj:dMVf6o>#]:wKp48?Ze$ImRTXDnNii+/T Z%K,ÁnsqmƪU8qYYYQ/卉GߟFJKKپ};>}j%!!!Сo?֒HCC[la۶mX,FEn'55TV+YYYѯ_?tcСo(444pS\\XXVzI~HOOn3uT18́صk,ӷo_y}zHN8AFF@e9@kR?[neرTUU׏>2 E 49*BeUN'ȲXr]s5PZZ 7n~{D)TA-2& PMu_4ĄmZe%j?{8/^63f ӦMJo8Zv?`.x"vnxwu/nWgzn&A)VSqHuoZ={6W_}uSN 555XV1)aM݋hr_G?؍j(%6Vt%Iɓ8_<ꊘ(?$)D/ ڵh(Υ( )IV+f$-[ƈ#|G, n9spxf`0j` ΋Z]lִma ?ͽpUQ>jkkի}:Rz#u5pili<.EzZqFz L&_m'\$I MHHhnESZm4R_byLL uuu|QšҢiShj Me9t<Of1eʔ3cfڷo@JJ Nk6YѾ\E9~8VEmmOXLkOIDAT&Ν˃>HRm1b={odРAk>~V^j0RRR޽M~K9ՑL6m%11o&bQ hȌ34iEEEZJ3W`0Dy9r?1j({=;6\V목aϞ= 8#F0o<\. ,h RRR&66t2|AMFbb"K.fʕ<3:uz]2uԀݢtwɓ\wuٳ,Y\'O'%Buɒ%3}tf3]voRM9(b-; ᠺ?j@ :͟?b!ۣ ߜ6mP]]Qګ>|^zq7M6SO1b͛m$g3X,v***4]x1C aƌ<U7oO?t_I|v<ˠAx7[Yt)\r wuv-b̙`֬Y;/b,_n{_{5͛vM1K2}t (466CQWWǂ c5 *j 6mD4ܹ?\2D(-- nbXQ%##SNaa!v"--C©`M֢]v[>&AC 8))Մe]7|oa|  3gsaܹ 2;7Zk%==뮻goe'Oҷo_\.eee Cx^x|x ]bؿ9L٧mJJJ6m[lcΝtM <߾@:::?> UQ梚sgk?fA=|!--I&1qD~m^z%&N7nVƏyd/w>G][#@X,h:p8h),,D$5LQWGEm1vXƌҥKyyg5k_=Ǐou]ٮ:< \.ꢬ? F L4yn$< L޾}zIII$&&>dɒ~zfkcǎP@bbI?cn&n&̙S+ {;ϛ7OС'.4M{[CCC?ݝ] pZzyCB|,"w8 4 p5rx8ysR%ϋA0:! [IbS`ơ3jN+يaD!N7e@ OxϹNy`׹NOINyN p=Q \&JGG(ٹN/A'yf_ !N`9u ` JX;"ވ~ ? :-! aWBLn&Mw7=䯏/s2 Zp!3 eo Fps׍L"rZEpr9@W/W p!h[cU1%H*tk#z!l[ -:1`M @<U~ ||Qa0_=1+DA̮1+脘UD6BR\ ,>;m8 z o\ |  ,:V,QBf@|0B&@h/up5ؾ'|"h0ZFRK - 0t?+=ć=X41& x_]yڜ^eV-Pvx=Jz;ihN=i9ﺎvu;14#@ýU3B#8fy <3y6jÜVDh_eodD71j'3?{k }/$V#/9{VmZĵ'QD U[ם Ѱ%r=y rGnWݯF c+AmW]}^`VT4fR`@5!_KlMC`+:crOs6WD6#Lmv ftA̢ӎrwk-~ޢ6,ѲSU!PuCNAj!e=SԺ@LTs筑nȬDLkӓSVw8O$ZKc;‹:E=j{NAh78ڬ60~,JxF[MQZːGk)ghN.iz b?Ja5}V| jTHsst C|jJ]AvA `/󈔟M{{ b GkӔ5B:wbLLPxJ 7ͭ:TszϿ!u1"a?B/Ch5V/DDϢK@ BĴ+bZ;bwKv_R0@b"C;QSvo\# QHhSnݽ+ kb.ް^ Cz7-Bpmތ&­9\u'e \$Fsz5Xd4sًX#XDOg3MjM̈94N@1?h(t7F(nSykq{ZKϣZa+ Ci >#LNˈEȃUAض"yBmz5ck91#(S9y[]L蜿8ˁg"L|cs.[ 'b45s GG#_8HGGGW}vtKBWL Z;T!ʬ$(:::::::::?g~IL67iUZ#uח氂;ڟ DDt贈֞n98UGGG'rBӃ8X͊lXг㭜sBk j,mELGGaP ĞnAA|En;T͈-s1bս͉tmftttt~2j߇س҉؏UNa({TV1mĠSRB}o.P{ b'Z;[GGGgC8 !HF. bGt&xxV BcUN{orat¸ODcUl˽ώ8,@}{/ܹQ::::?k {y  ^Y0 8!8q.5d!!0 ovqCxaO]< sעWqn"'b)Ab:::PΥ@U'k {ziV/?OҿON8?nP-hJ]飦 gCBV%jĄz;΄KQi A~ ԛ ?y&򣣣sК?1rBz u{PsLR;A%U/ 'Pxm>^QGGG'$pI|N"l0"V2C,Gh }q&*+ $lP]ҭ[IENDB`live-clone-1.5.1/img/toolbar.svg000066400000000000000000001232621356647605500165410ustar00rootroot00000000000000 image/svg+xml Help Tools Run Clone Quit live-clone-1.5.1/lang/000077500000000000000000000000001356647605500145155ustar00rootroot00000000000000live-clone-1.5.1/lang/HelpAbout.fr.md000066400000000000000000000005061356647605500173310ustar00rootroot00000000000000© 2019 Georges Khaznadar Ce programme est libre, il est distribué sous la licence GPL-3+. Live-Clone a été développé pour permettre aux [clés vives Freeduc](https://usb.freeduc.org/jbart.html) de disposer d'un système d'auto-clonage, ce qui facilite leur sécurisation et leur dissémination. live-clone-1.5.1/lang/HelpTab.fr.md000066400000000000000000000175171356647605500167770ustar00rootroot00000000000000 # La barre d'outils ![barre d'outils](./img/toolbar.fr.png) # * ![Bouton d'aide](./img/help.png)Le premier bouton à gauche de la barre d'outil fait apparaître une fenêtre « à propos » de cette application, et remet le présent document sur le dessus. * Ensuite, le bouton des outils![Bouton d'outils](./img/gnome-run.png) donne accès aux outil de maintenance des clés Freeduc : réinitialisation si quelqu'un les a rendues inconsistantes, mais aussi sauvegarde des données de persistance. * Le bouton de lancement, quant à lui, ![Bouton de lancement](./img/computer.png), permet de lancer le système de la clé Freeduc dans une machine virtuelle (si on a installé le paquet qemu-kvm). * L'application centrale, c'est le clonage de clés USB, ![Bouton de clonage](./img/jumping-gnu-48x48.png), qu'on peut lancer avec le bouton ou à l'aide du titre juste à côté. * Le dernier bouton, tout à droite, permet de quitter l'application. ![Bouton pour quitter](./img/application-exit.png) On peut quitter même quand une commande est en cours et que les moniteurs en affichent les détails. # Le déroulement d'un clonage # Dans l'afficheur juste sous la barre d'outils, on peut voir des détails sur tous les disques USB détectés, qui sont connectés à l'ordinateur. Sous GNU-Linux, leur désignation est ``/dev/sdX`` où ``X`` désigne une lettre de l'alphabet ; ces lettres sont attribuées en général selon la chronologie des branchements. Quand on démarre un clonage ![Bouton de clonage](./img/jumping-gnu-48x48.png), on peut cocher plusieurs disques à la fois ; selon la qualité de l'ordinateur, de ses ports USB et des clés, on peut avoir un avantage à en cloner plusieurs à la fois. Quand le ou les disques sont choisis, il faut désigner l'image Freeduc qu'on veut y inscrire. Si cette application fonctionne *depuis une clé Freeduc*, l'option par défaut est **AUTOCLONE**, c'est à dire clonage de la clé elle-même sur les clés-cibles. On peut aussi choisir, dans tous les cas, une image de disque ISO, qui doit être présente dans le système de fichiers. Il suffit alors de valider tous ces choix et le clonage commence. Il se déroule en quelques minutes, et il est possible d'en suivre la progression dans autant de moniteurs qu'il y a de disques en cours de clonage. L'opération la plus longue est la copie de l'image du cœur du système, qui assure le démarrage du noyau Linux, et la présence de centaines de programmes, fournis par un système de fichiers compressé, en lecture-seule. Quand cette opération se termine, une partition dite de *persistance* est créée, c'est celle qui contiendra toutes les modifications apportées à la clé durant « sa vie » : les données visibles de l'utilisateur, ainsi que nombre de fichiers cachés, liés à des configurations, et aussi les nouveaux programmes qu'on désire y installer. Quand l'opération de clonage se termine, il est possible d'enregistrer les messages des moniteurs à toutes fins utiles. # La logique des outils de maintenance # Il est plus facile de débrancher une clé USB durant le fonctionnement d'un ordinateur que le disque dur qu'il y a à l'intérieur : ce genre d'erreur est fréquent, personne n'est à l'abri. Il arrive donc que le système de fichier de *persistance* devienne inconsistant. En général, les parties inconsistantes sont rapidement réparées au démarrage suivant. Cependant, il arrive que la clé USB devienne inutilisable en cas d'inconsistance grave. D'autre part, ces clés USB sont destinées à l'apprentissage des l'informatique sur système libre, pour des débutants. Or *tous les droits* en écriture peuvent être attribués à l'utilisateur débutant. Si on a l'idée d'effacer un fichier important pour le fonctionnement de l'ordinateur, c'est possible. Fort heureusement, le cœur du système est en lecture-seule ; quand on croit effacer un fichier, en réalité on écrit dans la persistance un code signifiant « ce fichier est effacé » ; le fichier est cependant toujours là dans le cœur du système, ce qui permet la magie de la réinitialisation. ## Réinitialisation de la clé vive ## En fait, pour réinitialiser la clé vive, il faut et il suffit d'effacer deux dossier dans la partition de persistance. Bien sûr, ce faisant on perd tout le travail et toutes les configurations effectuées par l'utilisateur depuis le début de l'histoire de la clé. C'est pourquoi les outils de maintenance sont organisés de façon *prudente*. ## Première étape prudente : garder la liste des paquets logiciels nouveaux ## La clé vient avec des centaines de logiciels pré-installés, mais on peut en vouloir plus. Grâce aux paquets logiciels du système Debian, rien de plus facile ! les commandes ``apt`` permettent de le faire en toute liberté. Quand la persistance est effacée, c'est une bonne idée de conserver quelque part la liste de tous les paquets logiciels qu'on peut souhaiter réinstaller ensuite. ## Deuxième étape prudente : sauvegarder les données de l'utilisateur ## Durant l'histoire d'une clé, la plupart des fichiers intéressants pour l'utilisateur se placent dans le répertoire ``/home/user`` ; on est donc invité à en faire une sauvegarde, totale ou sélective. L'interface des outils propose une vision en arbre de dossiers, qui permet de cocher ce qu'on veut conserver : * tout conserver ... cocher simplement le dossier ``user`` * conserver par exemple les contenu du bureau, les téléchargements, et un projet situé dans le dossier ``/home/user/projets/projet1`` : ne *pas cocher* le dossier ``user``, cocher les dossiers ``user/Bureau``, ``user/Téléchargement``, ``user/projets/projet1`` ; notez bien que si on coche deux points dans l'arbre des fichiers, le point coché le plus proche de la racine peut passer *devant* l'autre, s'il se situe dans un sous-répertoire : c'est toujours la sauvegarde la plus large qui est choisie. La sauvegarde se fait au format ``tar.gz``, aussi connue sous le nom ``tgz`` ; les bons gestionnaires d'archive savent tous interpréter ce format. Si on tente un maintenance sur une clé neuve, il n'y a pas de données personnelles dans la persistance, donc cette étape est écourtée. ## Dernière étape : réinitialiser la persistance ## Cette étape, comme toutes celles qui précèdent, peut être neutralisée, il suffit de choisir un échappement, possible à chaque moment. Comme la réinitialisation se fait avec perte de données, on doit confirmer deux fois qu'on veut bien la faire. L'opération est rapide, et irréversible. Après réinitialisation, la clé USB est prête à fonctionner comme à son premier démarrage  : donc elle démarrera aussi lentement qu'elle l'a fait à a première utilisation, puisque de nombreuses initialisations doivent avoir lieu (un *premier* démarrage prend une à trois minutes de plus que les suivants). # Lancement du système dans une machine virtuelle # Tant qu'on reste dans la même application, on peut tester le fonctionnement de la clé restaurée dans une machine virtuelle, sur le même ordinateur, sans arrêter son fonctionnement. C'est possible si le processeur est équipé pour pouvoir supporter la virtualisation (ce n'est pas le cas de tous les processeurs). Le paquet logiciel ``qemu-kvm`` est nécessaire pour pouvoir profiter de cette fonctionnalité. Il n'est pas installé par défaut dans la distribution Freeduc, mais on peut l'y ajouter. Notez bien que le fonctionnement en machine virtuelle est l'une des seules façons permettant d'obtenir des copies d'écran durant les phases de démarrage et d'arrêt du système, quand le système lui-même serait bien incapable de gérer l'opération de copie d'écran. live-clone-1.5.1/lang/README.fr.md000066400000000000000000000003551356647605500164050ustar00rootroot00000000000000CLONE_JBART =========== Cette petite application permet de cloner des clés USB Freeduc-Jbart Dépendances ----------- * **Python3 :** python3-markdown * **PyQt5 :** python3-pyqt5 * **GI :** Gio, GLib, UDisks, gir1.2-udisks-2.0 live-clone-1.5.1/lang/live_clone_fr.ts000066400000000000000000001630711356647605500177030ustar00rootroot00000000000000 BackupDialog Select backup data Sélection des données personnelles à enregistrer <html><head/><body><p>Please check the tree of data which you want to backup. If you check the topmost node &quot;user&quot;, all and every personal data is chosen, including Mozilla cache and desktop preferences. You may prefer to check subtrees. The subtrees are taken in account only when no node is checked above.</p></body></html> <html><head/><body><p>Veuillez cocher le ou les arbres de données que vous voulez sauvegarder. Si on coche le nœud de niveau supérieur « user », toutes les données personnelles sont enregistrées, y compris le cache de Mozilla Firefox et les préférences du bureau. Vous pouvez préférer seulement sélectionner des sous-arbres. Les sous- arbres sont pris en compte si aucun nœud de niveau supérieur n'est coché.</p></body></html> CloneMonitor Cloning is over Le clonage est terminé Cloning Clonage CloneWizard Clone a Freeduc system to USB drives Cloner un système Freeduc dans des clés USB Select the target disks Sélection des disques-cibles Please check the disks where you want to clone the system. Warning: all data exiting on those disks will be erased, you can still Escape from this process. Veuillez cocher les disques où vous voulez cloner le système. Attention : toutes les données de ces disques seront effacées. Vous pouvez encore vous échapper de ce processus. Source of the core system Source du cœur du système The program is running from a Freeduc GNU-Linux system Le programme fonctionne dans un système GNU Linux Freeduc The program is running from a plain GNU-Linux system Le programme fonctionne dans un système GNU Linux ordinaire Choose an image to clone Choisir une image à cloner ISO Images (*.iso);;All files (*) Images ISO (*.iso);;Tous fichiers (*) Cloning to {} Clonage vers {} Dialog About À propos <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">© 2019 Georges Khaznadar &lt;georgesk@debian.org&gt;</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This program is free, it is licensed under GPL-3+.</p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">© 2019 Georges Khaznadar &lt;georgesk@debian.org&gt;</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ce programme est libre, il est régi par la licence GPL-3+.</p></body></html> MainWindow Freeduc Clone Freeduc Clone CLONING LIVE STICKS CLONER DES CLÉS USB <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:16pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:16pt; font-weight:400; font-style:normal;"> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> Help Aide Tab 2 Tab 2 &File &Fichier &Help &Aide &Quit &Quitter &About À &Propos Tools Outils Erase persistence data Effacement des données persistantes When something goes really wrong, erasing persistence data allows one to return to the initial setup Quand ça part vraiment mal, on peut revenir à la configuration initiale en effaçant les données persistantes Backup personal data Enregistrer les données personnelles When persistence data are erase, personal data disappear: you can backup them in advance Quand les données persistantes sont effacées, les données personnelles aussi : on peut les enregistrer par avance List additional packages Lister les paquets ajoutés When the persistence area is erased all newer package are erased too. One might know their list. Quand on efface la zone de persistance, tous les nouveaux paquets sont effacés aussi. On peut vouloir en connaître la liste. Run in a virtual machine Démarrer dans une machine virtuelle Clone the system core to a USB disk Cloner le cœur du système vers un disque USB ... ... Save personal data, Erase persistence Enregistrer les données personnelles, Effacer la persistance Launch in a virtual machine Démarrer dans une machine virtuelle Quit the application Quitter l'application Help(F1) Aide (F1) F1 F1 Save personal data, Erase persistence (Alt-S) Enregistrer les données personnelles, Effacer la persistance (Alt-S) Alt+S Alt+S Launch in a virtual machine (Alt-R) Démarrer dans une machine virtuelle (Alt-R) Alt+R Alt+R Clone the system core to a USB disk (Alt-C) Cloner le cœur du système vers un disque USB (Alt-C) Alt+C Alt+C Quit the application (Ctrl-Q) Quitter l'application (Ctrl-Q) Ctrl+Q Ctrl+Q Monitor stdout Sortie standard stderr Sorties standard des « erreurs » Cloning is over Le clonage est terminé Do you want to save the logs? Voulez-vous enregistrer les traces d'exécution ? name of the file for the logs Nom du fichier pour les traces Save the messages? Enregistrer les messages ? Log files (*.log);;All files (*) Fichers de journalisation (*.log);;Tous fichiers (*) Close this monitor Fermer ce moniteur Working Travail MyMain Tab closed. Tab refermé. HelpTab.md lang/HelpTab.fr.md Clone ready ... Tab #{0} Clonage terminé ... Tab n°{0} Clone to {} Cloner vers {} Device Périphérique Partitions Partitions Source Source Actions Actions Status Statut Own running system Le système en cours Choose an image to clone to {} Choisir une image à cloner vers {} ISO Images (*.iso);;All files (*) Images ISO (*.iso);;Tous fichiers (*) Cloning ... Tab #{} Clonage ... Tab n°{} Cloning to {} Clonage vers {} HelpAbout.md lang/HelpAbout.fr.md Current USB disks: {} Disques USB connectés : {} No USB stick. Please plug a USB flash disk. Pas de disque USB connecté. Veuillez en connecter un. Erase persistence data Effacement des données persistantes If you go forward, all data in the persistence partition(s) will be lost. If unsure, cancel the operation. The list of erasable persistence partitions is below. Si vous persistez, toutes les données dans la ou les partitions de persistace seront effacées. En cas de doute, Échappez à cette opération. La liste des partitions effaçables est ci-dessous. Select the partitions to clear Sélection des partitions à effacer Be careful. The selected partitions will be cleared when you finish. Attention, les partitions sélectionnées seront effacées quand vous demanderez à finir. No selected USB disk Pas de disque USB choisi Please select at least one cell in the disks table. Veuillez sélectionner une case au moins dans le tableau des disques. Get a list of additional packages Réupération d'une liste des paquets ajoutés Select one disk Sélectionner un disque Which disk do you want to check for packages installed in the persistence zone? Sur quel disque voulez-vous vérifier la liste des paquets installés dans la zone de persistance ? Run a disk in a virtual machine Démarre un disque dans une machine virtuelle Which disk do you want to launch in a virtual machine? Quel disque voulez-vous démarrer dans une machine virtuelle ? ADDITIONAL PACKAGES =================== LISTE DES PAQUETS AJOUTÉS ========================= Save Packages File Enregistrement d'un fichier de paquets Markdow files (*.md);;Plain text files (*.txt);;Any file (*) Fichiers Markdow (*.md);;Fichiers texte (*.txt);;Tout fichier (*) Backup personal data Enregistrer les données personnelles Which is the disk containing personal data to backup? Quel est le disque qui contient les données personnelles à enregistrer ? List of additional packages in {} Liste des paquets ajoutés dans {} Clone a Freeduc system to USB drives Cloner un système Freeduc dans des clés USB Select the target disks Sélection des disques-cibles Please check the disks where you want to clone the system. Warning: all data exiting on those disks will be erased, you can still Escape from this process. Veuillez cocher les disques où vous voulez cloner le système. Attention : toutes les données de ces disques seront effacées. Vous pouvez encore vous échapper de ce processus. Source of the core system Source du cœur du système The program is running from a Freeduc GNU-Linux system Le programme fonctionne dans un système GNU Linux Freeduc The program is running from a plain GNU-Linux system Le programme fonctionne dans un système GNU Linux ordinaire Choose an image to clone Choisir une image à cloner Repair and/or manage a Freeduc USB stick Réparer et/ou gérer une clé USB Freeduc Which disk do you want to repair or to save? Quelle clé voulez-vous réparer ou sauvegarder ? Here is the list of packages which you can restore later. You can edit the text before saving it. Voici la liste des paquets que vous pourriez restaurer plus tard. Il est possible d'éditer ce texte avant de l'enregistrer. There are no new packages installed in the persistence partition Il n'y a pas de nouveaux paquets installés sur la partition de persistance Select personal data to save Sélectionnez les données personnelles à enregistrer Please check the tree of data which you want to backup. If you check the topmost node "user", all and every personal data is chosen, including Mozilla cache and desktop preferences. You may prefer to check subtrees. The subtrees are taken in account only when no node is checked above. Veuillez cocher l'arbre de données que vous voulez sauvegarder. Si vous cochez le nœud supérieur « user », toutes les données personnelles sont sélectionnées, y compris le cache de Mozilla Firefox, les préférences de bureau et la (grosse) configuration de l'émulateur Windows. Vous pourriez préférer cocher des sous-arbres. Les sous-arbres sont pris en compte pour autant qu'aucun nœud ne soit coché au-dessus d'eux. TAR-GZIP archives (*.tgz,*.tar.gz);;Any file (*) Achives TAR-GZIP (*.tgz,*.tar.gz);;Tout fichier (*) Save personal persistence data to {} Enregistrer les données personnelles dans {} Save to {} Enregistrer dans {} save-data donnees Close the log of the archive Fermer le journal d'archivage {} ... Tab #{} {} ... Tab n° {} Nothing is available Rien trouvé No personal data in the persistence partition Il n'y a pas de données personnelles dans la partition de persistance Now, you have carefully backuped sensistive data, you may erase the persistence; however, you can still cancel it. Maintenant, vous avez soigneusement sauvegardé les données sensibles, vous pouvez effacer la persistance ; mais vous pouvez encore y échapper. Persistence erased Données de persistance effacées Persistence data have been erased from {} Les données de persistance de {} ont été effacées Yes, I am sure that I want to erase the persistence. Oui, je suis sûr.e de vouloir effcer la persistence. Yes again, I am completely sure! Encore oui, j'en suis complètement sûr.e ! Save personal data archive Enregistrer l'archive des données personnelles Format the partition {} Formater la partition {} PackageEditor Additional packages Paquets ajoutés <html><head/><body><p>This editor contains the packages installed in the persistence zone. They will be lost if one erases the persistence data. You can edit this text and save it.</p></body></html> <html><head/><body><p>Cet éditeur liste les paquets installés dans la zone de persistance. Ils seront perdus si on efface les données de persistance. Vous pouvez éditer ce texte et l'enregistrer.</p></body></html> Cancel Échappement Save Enregistrer RunWizard Run a disk in a virtual machine Démarre un disque dans une machine virtuelle Select one disk Sélectionner un disque Which disk do you want to launch in a virtual machine? Quel disque voulez-vous démarrer dans une machine virtuelle ? StickMaker [At {0}] {1} [À {0}] {1} You must be root to launch {} Il faut être root pour lancer {} clone a Freeduc-Jbart distribution cloner une distribution Freeduc-Jbart do'nt use the file rw.tar.gz to seed the persistence ne pas utiliser le fichier rw.tar.gz pour initialiser la partition de persistence source of the distribution (required); the keyword OWN means that we are cloning from Freeduc-Jbart source de la distribution (obligatoire) ; le mot-clé OWN signifie qu'on clone depuis une clé USB Freeduc-Jbart the targetted USB stick la clé USB cible Unmounting {} Démontage de {} Copying {0} to {1} ... Copie de {0} vers {1} ... Forget the partition {}3, to create it again Suppression de la partition {}3, pour la créer à nouveau Create the partition {}3 to support persistence Création de la partition {}3 pour supporter la persistance This partition is adjusted to use all the remaining space on {} On ajuste cette partition pour utiliser la place restante sur {} Create the file persistence.conf on the third partition Création du fichier persistence.conf sur la troisième partition Pre-seed the third partition with rw.tar.gz Initialisation de la troisième partition à l'aide de rw.tar.gz Ready. Total time: {} Terminé. Durée totale : {} clone a Debian-Live distribution cloner une distribution Debian-Live source of the distribution (required); the keyword OWN means that we are cloning from a Debian-Live disk source de la distribution (obligatoire) ; le mot-clé OWN signifie qu'on clone depuis une clé USB Debian-Live Create the partition {}3 for VFAT data, using 4GiB Création de la partition {}3, format VFAT, taille 4Gio Create the partition {}4 to support persistence Création de la partition {}4 pour supporter la persistance Create the file persistence.conf on the fourth partition Création du fichier persistence.conf sur la quatrième partition Pre-seed the fourth partition with rw.tar.gz Initialisation de la quatrième partition à l'aide de rw.tar.gz Delete the partition {}{}, to create it again Suppression de la partition {}{}, pour la créer à nouveau Tool Cannot erase persistence data Impossible d'effacer les données de persistance One needs root priviledge to erase persistence data Il faut avoir les privilèges de super-utilisateur pour effacer les données de persistence Persistence erased Données de persistance effacées Persistence data have been erased from {} Les données de persistance de {} ont été effacées Cancel Échappement ToolWizard Repair and/or manage a Freeduc USB stick Réparer et/ou gérer une clé USB Freeduc Select one disk Sélectionner un disque Which disk do you want to repair or to save? Quelle clé voulez-vous réparer ou sauvegarder ? List of additional packages in {} Liste des paquets ajoutés dans {} Here is the list of packages which you can restore later. You can edit the text before saving it. Voici la liste des paquets que vous pourriez restaurer plus tard. Il est possible d'éditer ce texte avant de l'enregistrer. There are no new packages installed in the persistence partition Il n'y a pas de nouveaux paquets installés sur la partition de persistance ADDITIONAL PACKAGES =================== LISTE DES PAQUETS AJOUTÉS ========================= Save Packages File Enregistrement d'un fichier de paquets Markdow files (*.md);;Plain text files (*.txt);;Any file (*) Fichiers Markdow (*.md);;Fichiers texte (*.txt);;Tout fichier (*) Select personal data to save Sélectionnez les données personnelles à enregistrer Please check the tree of data which you want to backup. If you check the topmost node "user", all and every personal data is chosen, including Mozilla cache and desktop preferences. You may prefer to check subtrees. The subtrees are taken in account only when no node is checked above. Veuillez cocher l'arbre de données que vous voulez sauvegarder. Si vous cochez le nœud supérieur « user », toutes les données personnelles sont sélectionnées, y compris le cache de Mozilla Firefox, les préférences de bureau et la (grosse) configuration de l'émulateur Windows. Vous pourriez préférer cocher des sous-arbres. Les sous-arbres sont pris en compte pour autant qu'aucun nœud ne soit coché au-dessus d'eux. Nothing is available Rien trouvé No personal data in the persistence partition Il n'y a pas de données personnelles dans la partition de persistance Save personal data archive Enregistrer l'archive des données personnelles TAR-GZIP archives (*.tgz,*.tar.gz);;Any file (*) Achives TAR-GZIP (*.tgz,*.tar.gz);;Tout fichier (*) Save personal persistence data to {} Enregistrer les données personnelles dans {} Save to {} Enregistrer dans {} save-data donnees Close the log of the archive Fermer le journal d'archivage Now, you have carefully backuped sensistive data, you may erase the persistence; however, you can still cancel it. Maintenant, vous avez soigneusement sauvegardé les données sensibles, vous pouvez effacer la persistance ; mais vous pouvez encore y échapper. Persistence erased Données de persistance effacées Persistence data have been erased from {} Les données de persistance de {} ont été effacées Format the partition {} Formater la partition {} Yes, I am sure that I want to erase the persistence. Oui, je suis sûr.e de vouloir effcer la persistence. Yes again, I am completely sure! Encore oui, j'en suis complètement sûr.e ! clone_jbart HelpTab.md HelpTab.fr.md Clone ready ... Tab #{0} Clonage terminé ... Tab n°{0} specialPage Source of the core system Source du cœur du système The program is running from a Freeduc GNU-Linux system Le programme fonctionne dans un système GNU Linux Freeduc The program is running from a plain GNU-Linux system Le programme fonctionne dans un système GNU Linux ordinaire Choose an image to clone Choisir une image à cloner ISO Images (*.iso);;All files (*) Images ISO (*.iso);;Tous fichiers (*) Backup personal data Enregistrer les données personnelles Select one disk Sélectionner un disque Which is the disk containing personal data to backup? Quel est le disque qui contient les données personnelles à enregistrer ? List of additional packages in {} Liste des paquets ajoutés dans {} ADDITIONAL PACKAGES =================== LISTE DES PAQUETS AJOUTÉS ========================= Save Packages File Enregistrement d'un fichier de paquets Markdow files (*.md);;Plain text files (*.txt);;Any file (*) Fichiers Markdow (*.md);;Fichiers texte (*.txt);;Tout fichier (*) No selected USB disk Pas de disque USB choisi Please select at least one cell in the disks table. Veuillez sélectionner une case au moins dans le tableau des disques. Get a list of additional packages Réupération d'une liste des paquets ajoutés Which disk do you want to check for packages installed in the persistence zone? Sur quel disque voulez-vous vérifier la liste des paquets installés dans la zone de persistance ? Run a disk in a virtual machine Démarre un disque dans une machine virtuelle Which disk do you want to launch in a virtual machine? Quel disque voulez-vous démarrer dans une machine virtuelle ? Erase persistence data Effacement des données persistantes If you go forward, all data in the persistence partition(s) will be lost. If unsure, cancel the operation. The list of erasable persistence partitions is below. Si vous persistez, toutes les données dans la ou les partitions de persistace seront effacées. En cas de doute, Échappez à cette opération. La liste des partitions effaçables est ci-dessous. Select the partitions to clear Sélection des partitions à effacer Be careful. The selected partitions will be cleared when you finish. Attention, les partitions sélectionnées seront effacées quand vous demanderez à finir. HelpAbout.md lang/HelpAbout.fr.md Clone ready ... Tab #{0} Clonage terminé ... Tab n°{0} Tab closed. Tab refermé. Clone to {} Cloner vers {} Cloning ... Tab #{} Clonage ... Tab n°{} Current USB disks: {} Disques USB connectés : {} No USB stick. Please plug a USB flash disk. Pas de disque USB connecté. Veuillez en connecter un. Device Périphérique Partitions Partitions Status Statut Cloning to {} Clonage vers {} uDisk Added partition %s Partition ajoutée : %s Failed to mount the disk: %s Échec au montage du disque : %s Disk not added: not a USB partition Disque non ajouté : partition non-USB Disk not added: empty partition Disque non ajouté : partition vide Already added disk: %s Disque déjà ajouté : %s Added disk: %s Disque ajouté : %s Change for the disk %s Changement pour le disque %s Disk unplugged from the system: %s Disque débranché du système : %s mount point point de montage size taille brand marque disk model modèle de disque serial number numéro de série check cocher live-clone-1.5.1/live-clone000066400000000000000000000000711356647605500155520ustar00rootroot00000000000000#!/usr/bin/python3 import live_clone live_clone.main() live-clone-1.5.1/live-clone.1000066400000000000000000000037461356647605500157250ustar00rootroot00000000000000'\" t .\" Title: LIVE-CLONE .\" Author: Georges Khaznadar .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 07/10/2019 .\" Manual: live-clone User Manual .\" Source: live-clone .\" Language: English .\" .TH "LIVE\-CLONE" "1" "07/10/2019" "live-clone" "live-clone User Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" live-clone \- program to clone GNU\-Linux distributions based on live\-build .SH "SYNOPSIS" .HP \w'\fBsudo\ live\-clone\fR\ 'u \fBsudo live\-clone\fR .SH "AUTHOR" .PP \fBGeorges Khaznadar\fR <\&georgesk@debian\&.org\&> .RS 4 Wrote this manpage for the Debian system\&. .RE .SH "COPYRIGHT" .br Copyright \(co 2019 Georges Khaznadar .br .PP This manual page was written for the Debian system (and may be used by others)\&. .PP Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or (at your option) any later version published by the Free Software Foundation\&. .PP On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common\-licenses/GPL\&. .sp live-clone-1.5.1/live_clone.desktop000077500000000000000000000003301356647605500173050ustar00rootroot00000000000000[Desktop Entry] Version=1.2 Name=Live Clone GenericName=Live Clone Comment=Cloning Live-Boot media Exec=pkexec /usr/bin/live-clone Icon=live_clone Terminal=false Type=Application Categories=System StartupNotify=true live-clone-1.5.1/live_clone.pro000066400000000000000000000005701356647605500164370ustar00rootroot00000000000000lupdate_only { SOURCES += $$PWD/__init__.py \ $$PWD/monitor.py \ $$PWD/tools.py \ $$PWD/wizards.py \ $$PWD/ui_about.py \ $$PWD/usbDisk2.py \ $$PWD/makeLiveStick.py \ $$PWD/ui_live_clone.py \ $$PWD/ui_packageEditor.py } TRANSLATIONS += lang/live_clone_fr.ts live-clone-1.5.1/makeLiveStick.py000066400000000000000000000173531356647605500167120ustar00rootroot00000000000000#! /usr/bin/python3 import os, sys, argparse, glob, time from subprocess import Popen, PIPE, call from PyQt5.QtCore import QObject, QTranslator, QLocale from PyQt5.QtWidgets import QApplication class StickMaker(QObject): def __init__(self): QObject.__init__(self) self.startTime = time.time() self.pathSentence="PATH=/usr/sbin:/sbin:/usr/bin:/bin; " def hms(self): """ returns the time elapsed so far, in format HH:MM:SS """ t=int(time.time()-self.startTime) th=t//3600 tmin=(t-3600*th)//60 tsec=(t-3600*th-60*tmin) return f"{th:02d}:{tmin:02d}:{tsec:02d}" def flush(self, stderr=True, stdout=True): """ flush standard outputs @param stderr don't flush sys.stderr if it's False (True by default) @param stdout don't flush sys.stdout if it's False (True by default) """ if stderr: sys.stderr.flush() if stdout: sys.stdout.flush() return def log(self, s, timestamp=True): """ print some information for stdout @param s a string to log @param timestamp True (by default) implies that there will be a timestamp """ if timestamp: print(self.tr("[At {0}] {1}").format(self.hms(),s)) else: print(s) sys.stdout.flush() return def run(self): """ The main method """ if os.geteuid() != 0: self.log( self.tr("You must be root to launch {}").format(sys.argv[0]), timestamp=False ) sys.exit(1) parser = argparse.ArgumentParser(description=self.tr('clone a Debian-Live distribution')) parser.add_argument('-n','--no-persistence', help=self.tr("do'nt use the file rw.tar.gz to seed the persistence"), action='store_true') parser.add_argument('-s','--source', help=self.tr('source of the distribution (required); the keyword OWN means that we are cloning from a Debian-Live disk'), metavar="source", required=True) parser.add_argument('device', help=self.tr('the targetted USB stick')) args = parser.parse_args() ################### unmount targetted partitions if any ############# cmd=f"mount | grep {args.device} | awk '{{print $1}}'" p=Popen(self.pathSentence+cmd, shell=True, stdout=PIPE, stderr=PIPE) mountpoints,_ = p.communicate() mounts=mountpoints.decode("utf-8").split() if mounts: self.log(self.tr("Unmounting {}").format(', '.join(mounts))) for m in mounts: call(self.pathSentence+f"umount {m}", shell=True) self.flush() ################### copy the ISO-hybrid image ####################### self.log(self.tr("Copying {0} to {1} ...").format(args.source, args.device)) if args.source.upper()=="OWN": mountpoint = glob.glob("/usr/lib/live/mount/persistence/sd*1")[0] sourceDevice=mountpoint.replace("/usr/lib/live/mount/persistence","/dev")[:-1] ### when copying from own, the count of 4M blocks is computed ### from the last sector used by /dev/sd.1 cmd=f"sfdisk -l {sourceDevice}| grep /dev/sd.1| awk '{{print $4}}'" p=Popen(self.pathSentence+cmd, shell=True, stdout=PIPE, stderr=PIPE) sectors,_ = p.communicate() sectors=int(sectors.decode("utf-8").strip()) count = 1+sectors//8192 # convert 512 B sectors to 4 MiB blocks cmd = f"dd if={sourceDevice} of={args.device} status=progress bs=4M oflag=dsync count={count}" else: ### Then, the boot sector bears information for two partitions. cmd=f"dd if={args.source} of={args.device} status=progress bs=4M oflag=dsync" call(self.pathSentence+cmd, shell=True) self.flush() cmd=f"sync; sleep 4; partprobe {args.device}" call(self.pathSentence+cmd, shell=True) self.flush() inputs="" ### command lines for fdisk if args.source.upper()=="OWN": # if there are partitions #4 and #3 in the table, delete them for num in (4, 3): cmd=f"sfdisk -l {args.device}| grep {args.device}{num}" p=Popen(self.pathSentence+cmd, shell=True, stdout=PIPE, stderr=PIPE) reply, _ = p.communicate() if reply.decode("utf-8").strip(): # the partition #{num} does exist self.log(self.tr("Delete the partition {}{}, to create it again").format(args.device, num)) inputs+=f"""\ d {num} """ ############# adds partition #3 for the VFAT data ########## ############# adds partition #4 for the persistence ########## self.log(self.tr("Create the partition {}3 for VFAT data, using 4GiB").format(args.device)) self.log(self.tr("Create the partition {}4 to support persistence").format(args.device)) self.log(self.tr("This partition is adjusted to use all the remaining space on {}").format(args.device)) inputs+="""\ n p 3 +4G t 3 0b n p 4 w """ p=Popen(self.pathSentence+f"fdisk {args.device}", shell=True, stdout=PIPE, stderr=PIPE, stdin=PIPE) p.stdin.write(inputs.encode("utf-8")) message,err=p.communicate() self.log(message.decode("utf-8")) self.log(err.decode("utf-8")) cmd=f"sleep 6; partprobe {args.device}" call(self.pathSentence+cmd, shell=True) self.flush() ################ format VFAT #################################### cmd = f"mkfs.vfat -n DATA {args.device}3" call(self.pathSentence+cmd, shell=True) self.flush() ################ format (ext4) #################################### cmd = f"mkfs.ext4 -L persistence -F {args.device}4" call(self.pathSentence+cmd, shell=True) self.flush() ################## mount the 4th partition ######################## cmd = f"mkdir -p /tmp/{args.device}4; mount {args.device}4 /tmp/{args.device}4" call(self.pathSentence+cmd, shell=True) self.flush() ################# write the file persistence.conf ################ self.log(self.tr("Create the file persistence.conf on the fourth partition")) with open(f"/tmp/{args.device}4/persistence.conf", "w") as outfile: outfile.write("/ union\n") ################## eventually seed the persistence partition ###### if args.no_persistence==False and os.path.exists("rw.tar.gz"): self.log(self.tr("Pre-seed the fourth partition with rw.tar.gz")) cmd = f"zcat rw.tar.gz | (cd /tmp/{args.device}4/; tar xf -)" call(self.pathSentence+cmd, shell=True) self.flush() #################### little cleanup ############################### cmd = f"umount /tmp/{args.device}4; rmdir /tmp/{args.device}4; partprobe {args.device}" call(self.pathSentence+cmd, shell=True) self.flush() cmd = f"sfdisk -l {args.device}" call(self.pathSentence+cmd, shell=True) self.flush() self.log( "\n=======================================================\n", timestamp=False ) self.log( self.tr("Ready. Total time: {}").format(self.hms()), timestamp=False ) if __name__=="__main__": app = QApplication(sys.argv) # i18n stuff locale = QLocale.system().name() translation="live_clone_{}.ts".format(locale) langPath=os.path.join(os.path.abspath(os.path.dirname(__file__)),"lang",translation) translator = QTranslator(app) translator.load(langPath) app.installTranslator(translator) ############# maker = StickMaker() maker.run() live-clone-1.5.1/manpage.xml000066400000000000000000000077541356647605500157430ustar00rootroot00000000000000 .
will be generated. You may view the manual page with: nroff -man .
| less'. A typical entry in a Makefile or Makefile.am is: DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0" manpage.1: manpage.xml $(XP) $(DB2MAN) $< The xsltproc binary is found in the xsltproc package. The XSL files are in docbook-xsl. A description of the parameters you can use can be found in the docbook-xsl-doc-* packages. Please remember that if you create the nroff version in one of the debian/rules file targets (such as build), you will need to include xsltproc and docbook-xsl in your Build-Depends control field. Alternatively use the xmlto command/package. That will also automatically pull in xsltproc and docbook-xsl. Notes for using docbook2x: docbook2x-man does not automatically create the AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as ... . To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be found in the docbook-xsl-doc-html package. Validation can be done using: `xmllint -''-noout -''-valid manpage.xml` General documentation about man-pages and man-page-formatting: man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/ --> ]> &dhtitle; &dhpackage; &dhfirstname; &dhsurname; Wrote this manpage for the Debian system.
&dhemail;
2019 &dhusername; This manual page was written for the Debian system (and may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 3 or (at your option) any later version published by the Free Software Foundation. On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL.
&dhucpackage; &dhsection; &dhpackage; program to clone GNU-Linux distributions based on live-build sudo &dhpackage;
live-clone-1.5.1/monitor.py000066400000000000000000000152461356647605500156450ustar00rootroot00000000000000import sys from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * import datetime, os class Monitor(QObject): def __init__( self, command, args, mainwindow, index, rindex, buttonMessage=None, actionMessage=None, createfiles=[], finishCallback=None, environ=None ): """ the constructor @param command an executable @param args the command line args for the executable @param mainwindow a QWidget which should have signals endmonitor and closemonitor, and a QTabWidget in mainwindow.ui.tabWidget @param index the index of the wanted tab @param rindex the row index to access the table of devices @param buttonMessage the text for the button which appears at the end of the process @param actionMessage a short word to define the ongoing process @param createfiles a list of files which might be created: one can change their ownership if we are running as SUDO @param finishCallback a callback function which should be activated when the monitor finishes. This function takes no argument. @param environ a shell environment; it can be user to get variables SUDO_UID and SUDO_GID """ QObject.__init__(self) self.index=index self.rindex=rindex self.command=command self.args=args if buttonMessage==None: buttonMessage=self.tr("Close this monitor") self.buttonMessage=buttonMessage if actionMessage==None: actionMessage=self.tr("Working") self.actionMessage=actionMessage self.createfiles=createfiles self.finishCallback=finishCallback self.environ=environ self.w=mainwindow.ui.tabWidget.widget(index) mainwindow.ui.tabWidget.setCurrentIndex(index) self.table=mainwindow.ui.tableWidget self.mainwindow=mainwindow self.process = QProcess(self.w) self.process.readyReadStandardOutput.connect(self.readOutput) self.process.readyReadStandardError.connect(self.readErr) self.process.finished.connect(self.finish) self.stdoutTerminal = QPlainTextEdit(self.w) self.stderrTerminal = QPlainTextEdit(self.w) self.cursor=QTextCursor(self.stdoutTerminal.document()); self.err_cursor=QTextCursor(self.stderrTerminal.document()); self.layout = QVBoxLayout(self.w) self.layout.addWidget(QLabel(self.tr("stdout"))) self.layout.addWidget(self.stdoutTerminal, stretch=4) self.layout.addWidget(QLabel(self.tr("stderr"))) self.layout.addWidget(self.stderrTerminal, stretch=1) return def start(self): self.process.start(self.command, self.args) # updates row rindex in self.table self.mainwindow.newmonitor.emit(self) return def downgrade_user(self): if self.environ and \ "SUDO_UID" in self.environ and \ "SUDO_GID" in self.environ: ## it is possible to downgrade the owner of the file for fname in self.createfiles: os.chown( fname, int(os.environ["SUDO_UID"]), int(os.environ["SUDO_GID"]) ) self.createfiles=[] return def close(self): d=datetime.datetime.now() fname, _ =QFileDialog.getSaveFileName( self.mainwindow, self.tr("Save the messages?"), "{action}-log-{date}.log".format( action=self.actionMessage, date=d.strftime("%Y-%m-%d--%H-%M") ), self.tr("Log files (*.log);;All files (*)") ) if fname: self.createfiles.append(fname) with open(fname, "w") as outfile: outfile.write("# STDOUT #\n") outfile.write(self.stdoutTerminal.toPlainText()) outfile.write("\n# STDERR #\n") outfile.write(self.stderrTerminal.toPlainText()) self.downgrade_user() self.mainwindow.closemonitor.emit(self) return True def finish(self): button=QPushButton(self.buttonMessage) button.clicked.connect(self.close) self.layout.addWidget(button) self.downgrade_user() if self.finishCallback: self.finishCallback() self.mainwindow.endmonitor.emit(self) def read(self, source, cursor, edit): """ reads a QByteArray from source and writes it into a QPlainTextEdit widget @param source: either an instance of QProcess.readAllStandardOutput or an instance of QProcess.readAllStandardError @param cursor a QTextCursor instance @param edit a QPlainTextEdit instance """ text= bytes(source()).decode("utf-8") if text.startswith("\r"): ## carriage return cursor.select(cursor.LineUnderCursor) cursor.removeSelectedText() cursor.insertText(text[1:]) else: cursor.insertText(text) edit.verticalScrollBar().setValue(edit.verticalScrollBar().maximum()) return def readOutput(self): self.read(self.process.readAllStandardOutput, self.cursor, self.stdoutTerminal) return def readErr(self): self.read(self.process.readAllStandardError, self.err_cursor, self.stderrTerminal) return class CloneMonitor(Monitor): def __init__(self, command, args, mainwindow, index, rindex, environ=None): """ the constructor @param command an executable @param args the command line args for the executable args[3] is the source to clone, args[4] is the targetted device @param mainwindow a QWidget which should have signals endmonitor and closemonitor, and a QTabWidget in mainwindow.ui.tabWidget @param index the index of the wanted tab @param rindex the row index to access the table of devices @param environ a shell environment; it can be user to get variables SUDO_UID and SUDO_GID """ Monitor.__init__(self, command, args, mainwindow, index, rindex, environ=environ ) self.buttonMessage=self.tr("Cloning is over") self.actionMessage=self.tr("Cloning") self.source=args[3] self.device=args[4] return if __name__ == "__main__": app = QApplication(sys.argv) main = Monitor('ls', ['-lR', '../..']) main.show() sys.exit(app.exec_()) live-clone-1.5.1/org.freedesktop.live-clone.policy000066400000000000000000000021521356647605500221520ustar00rootroot00000000000000 Live Clone Policy http://hal.freedesktop.org/docs/PolicyKit/ Run live-clone Lancement de live-clone Authentication is required: $(program) requires root priviledge. Une authentification est nécessaire : $(program) nécessite des droits de super-utilisateur. live_clone no no auth_self_keep /usr/bin/live-clone /usr/bin/live-clone live-clone-1.5.1/ressource.qrc000066400000000000000000000011571356647605500163210ustar00rootroot00000000000000 img/toolbar.png img/toolbar.fr.png img/help.png img/gnome-run.png img/computer.png img/application-exit.png img/live_clone.png img/cloning_end.png img/jumping-gnu.png img/jumping-gnu-64x64.png img/jumping-gnu-48x48.png img/jumping-gnu-32x32.png img/jumping-gnu-16x16.png img/cloning.gif live-clone-1.5.1/tools.py000066400000000000000000000266311356647605500153160ustar00rootroot00000000000000""" Some routines to implement the Tools actions """ from subprocess import call, Popen, PIPE from PyQt5.QtWidgets import QMessageBox, QFileSystemModel, QVBoxLayout, \ QTreeView, QWidget, QPushButton, QDialog, QTableWidgetItem from PyQt5.QtCore import QObject, QDir, Qt import gi gi.require_version('UDisks', '2.0') from usbDisk2 import uDisk2 import tempfile, os, re from ui_selectBackupData import Ui_BackupDialog class FileTreeSelectorModel(QFileSystemModel): """ This code is influenced by a reply to the question https://stackoverflow.com/questions/51338059/qfilesystemmodel-qtreeview-traverse-model-filesystem-tree-prior-to-view-e """ def __init__(self, parent=None, rootpath='/', verbose=False): QFileSystemModel.__init__(self, None) self.root_path = rootpath self.checks = {} self.nodestack = [] self.parent_index = self.setRootPath(self.root_path) self.root_index = self.index(self.root_path) self.setFilter(QDir.AllEntries | QDir.Hidden | QDir.NoDot) self.directoryLoaded.connect(self._loaded) self.verbose=verbose def log(self, *messages): if self.verbose: print(*messages) return def _loaded(self, path): self.log('_loaded', path) def data(self, index, role=Qt.DisplayRole): if role != Qt.CheckStateRole: return QFileSystemModel.data(self, index, role) else: if index.column() == 0: return self.checkState(index) def flags(self, index): return QFileSystemModel.flags(self, index) | Qt.ItemIsUserCheckable def checkState(self, index): if index in self.checks: return self.checks[index] else: return Qt.Unchecked # not checked by default def setData(self, index, value, role): if (role == Qt.CheckStateRole and index.column() == 0): self.checks[index] = value self.log('setData(): {}'.format(value)) return True return QFileSystemModel.setData(self, index, value, role) def traverseDirectory( self, parentindex, callback=None, stack=[] ): """ recurse the directories and files visible in the view. @param parentindex the index of the dir or file being recursed @param callback a function which will be called with args parentindex and stack @param stack a list of previously recursed indices """ self.log('traverseDirectory():') callback(parentindex, stack) if self.hasChildren(parentindex): self.log('|children|: {}'.format(self.rowCount(parentindex))) for childRow in range(self.rowCount(parentindex)): childIndex = parentindex.child(childRow, 0) self.log('child[{}]: recursing'.format(childRow)) self.traverseDirectory(childIndex, callback=callback, stack=stack+[parentindex]) else: self.log('no children') return def traverseDirectoryWhileUnchecked( self, parentindex, callback=None, stack=[] ): """ recurse the directories and files visible in the view, and stops recursion wherever an item is checked. @param parentindex the index of the dir or file being recursed @param callback a function which will be called with args parentindex and stack @param stack a list of previously recursed indices """ self.log('traverseDirectory():') callback(parentindex, stack) if self.checkState(parentindex)==Qt.Unchecked and \ self.hasChildren(parentindex): self.log('|children|: {}'.format(self.rowCount(parentindex))) for childRow in range(self.rowCount(parentindex)): childIndex = parentindex.child(childRow, 0) self.log('child[{}]: recursing'.format(childRow)) self.traverseDirectoryWhileUnchecked(childIndex, callback=callback, stack=stack+[parentindex]) else: self.log('no children') return def printIndex(self, index): self.log('model printIndex(): {}'.format(self.filePath(index))) class MountPoint: """ Implements a mount point which will be associated with a file system and can be either permanent or temporary; it can be used in "with" statements, ensuring that the file system is mounted in inside the block controlled by the statement, and unmounted when the block is finished if it was not mounted previously. """ def __init__(self, p): """ the constructor @param p a single partition of a disk, given either as a string (/dev/something or /org/freedesktop/UDisks2/block_devices/something) or as a uDisk2 instance """ orgPath="/org/freedesktop/UDisks2/block_devices" if type(p) == str: if p.startswith(orgPath): self._path=p elif p.startswith("/dev/"): self._path=os.path.join(orgPath, os.path.basename(p)) else: raise Exception("Not a partition path: {}".format(p)) devStuff=os.path.join("/dev", os.path.basename(self._path)) self._partition=uDisk2(self.path, device=devStuff) elif isinstance(p, uDisk2): # reread the current properties, which might be volatile self._partition=uDisk2(p.path, device=p.devStuff) self._path=p.path else: raise Exception("Expected some other argument or type : {} type={}".format(p, type(p))) self._capacity = self._partition.capacity self._mountpoint=None self._temp=None return def __str__(self): return self._mountpoint def __repr__(self): return "MountPoint(path={_path}, dir={_mountpoint})".format(**self.__dict__) @property def path(self): return self._path @property def partition(self): return self._partition @property def mountpoint(self): return self._mountpoint @property def is_temporary(self): return self._temp @property def capacity(self): return self._capacity def enter_(self): pipe=Popen( "mount| grep {}".format(self._partition.devStuff), stdout=PIPE, stderr=PIPE, shell=True ) out, err = pipe.communicate() out=out.decode("utf-8").strip() if out: m=re.match(r"{} on (.+) type .*".format(self._partition.devStuff), out) # the partition is mounted, no need to umount it self._mountpoint = m.group(1) self._temp = False elif self._partition.capacity: # only for existing partitions mp="" with tempfile.TemporaryDirectory(prefix="live_clone_") as temp: mp=temp # temp disappears when this block is over call("mkdir {}".format(mp), shell=True) call("mount {} {}".format(self._partition.devStuff, mp), shell=True) self._mountpoint = mp self._temp = True else: self._mountpoint = "" return def __enter__(self): """ callback activated when one enters a With statement @return self """ self.enter_() return self def exit_(self): if self._temp: # temporary mount points are dismissed call("umount {}".format(self._partition.devStuff), shell=True) call("rmdir {}".format(self._mountpoint), shell=True) return def __exit__(self, type, value, tb): """ Callback to exit a With statement; unmounts temporary mounts @param type type of Exception if any @param value parameter of the exception @param tb an TraceBack instance @return True is no exception occured """ self.exit_() return not tb class Tool(QObject): """ This class is a subclass of QObject to inherit translation functions. real tools at its methods """ def runDisk(self, d, window, memory="1G"): """ run a disk in a virtual machine @param d a disk given as a uDisk2 instance @param window a QMainWindow instance @param memory the amount of RAM left to the virtual machine (default=1G) """ cmd="(kvm -m {} -drive file={},format=raw &)".format(memory, d) call(cmd, shell=True) return def select_backup(self, d, window): """ Work out a list of paths to directories one wants to backu @param d a disk given as a /dev/sdx string @param window a QMainWindow instance """ ## the path to personal data is: ## /rw/home ## the partition to mount is the partition #3 with MountPoint(d+"3") as mp: rootpath=os.path.join(str(mp), "rw", "home") d=QDialog(window) d.ui=Ui_BackupDialog() d.ui.setupUi(d) d.model = FileTreeSelectorModel(rootpath=rootpath) d.model.setRootPath(rootpath) d.ui.tree.setModel(d.model) d.ui.tree.setRootIndex(d.model.parent_index) d.ui.tree.setAnimated(False) d.ui.tree.setIndentation(20) d.ui.tree.setSortingEnabled(True) d.ui.tree.setWindowTitle("Dir View") ok=d.exec_() to_save=[] def recurseFiles(): def cb(i, stack): if d.model.checkState(i)==Qt.Checked: pathdata=[index.data() for index in stack+[i]] to_save.append(os.path.join(*pathdata)) return i=d.model.parent_index d.model.traverseDirectoryWhileUnchecked(i,callback=cb) return if ok: recurseFiles() ### GRRR the result is in to_save return def erase_persistence(self, p, window): """ Erase persistence data from a partition @param p a partition given as a uDisk2 instance @parm window a QMainWindow instance """ if os.getuid()!= 0: # we are not root QMessageBox.critical( window, self.tr("Cannot erase persistence data"), self.tr("One needs root priviledge to erase persistence data") ) return with MountPoint(p) as mp: # erase directories work and rw from the persistence partition call("cd {}; rm -rf work rw".format(mp), shell=True) confFile=os.path.join(str(mp),"persistence.conf") if not os.path.exists(confFile): # the file persistence.conf must be eventually restored call("cd {}; echo '/ union' > persistence.conf".format(mp), shell=True) QMessageBox.information( window, self.tr("Persistence erased"), self.tr("Persistence data have been erased from {}").format(p.devStuff) ) return class MyItem(QTableWidgetItem): """ non-editable QTableWidgetItem items """ def __init__(self, text): QTableWidgetItem.__init__(self,text) self.setFlags(self.flags() & ~Qt.ItemIsEditable) return live-clone-1.5.1/ui_about.ui000066400000000000000000000027631356647605500157520ustar00rootroot00000000000000 Dialog 0 0 586 280 About Qt::Horizontal QDialogButtonBox::Ok true buttonBox accepted() Dialog accept() 248 254 157 274 buttonBox rejected() Dialog reject() 316 260 286 274 live-clone-1.5.1/ui_live_clone.ui000066400000000000000000000212371356647605500167540ustar00rootroot00000000000000 MainWindow 0 0 875 636 Freeduc Clone :/img/jumping-gnu-48x48.png:/img/jumping-gnu-48x48.png false false QFrame::StyledPanel QFrame::Raised PointingHandCursor Help(F1) Help(F1) ... :/img/img/help.png:/img/img/help.png 48 48 F1 PointingHandCursor Save personal data, Erase persistence (Alt-S) Save personal data, Erase persistence (Alt-S) ... :/img/img/gnome-run.png:/img/img/gnome-run.png 48 48 Alt+S PointingHandCursor Launch in a virtual machine (Alt-R) Launch in a virtual machine (Alt-R) ... :/img/img/computer.png:/img/img/computer.png 48 48 Alt+R PointingHandCursor Clone the system core to a USB disk (Alt-C) Clone the system core to a USB disk (Alt-C) ... :/img/img/jumping-gnu-48x48.png:/img/img/jumping-gnu-48x48.png 48 48 Alt+C 32 PointingHandCursor Clone the system core to a USB disk (Alt-C) Clone the system core to a USB disk (Alt-C) CLONING LIVE STICKS PointingHandCursor Quit the application (Ctrl-Q) Quit the application (Ctrl-Q) ... :/img/img/application-exit.png:/img/img/application-exit.png 48 48 Ctrl+Q 0 0 :/img/jumping-gnu-64x64.png 0 1 0 4 1 true Help 16 Tab 2 0 0 875 22 live-clone-1.5.1/ui_packageEditor.ui000066400000000000000000000043761356647605500174040ustar00rootroot00000000000000 PackageEditor 0 0 545 440 Additional packages <html><head/><body><p>This editor contains the packages installed in the persistence zone. They will be lost if one erases the persistence data. You can edit this text and save it.</p></body></html> true Courier Qt::Horizontal 40 20 0 0 Cancel 0 0 Save live-clone-1.5.1/ui_selectBackupData.ui000066400000000000000000000044001356647605500200250ustar00rootroot00000000000000 BackupDialog 0 0 676 315 Select backup data 0 0 <html><head/><body><p>Please check the tree of data which you want to backup. If you check the topmost node &quot;user&quot;, all and every personal data is chosen, including Mozilla cache and desktop preferences. You may prefer to check subtrees. The subtrees are taken in account only when no node is checked above.</p></body></html> true Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() BackupDialog accept() 248 254 157 274 buttonBox rejected() BackupDialog reject() 316 260 286 274 live-clone-1.5.1/usbDisk2.py000066400000000000000000000715641356647605500156510ustar00rootroot00000000000000# $Id: usbDisk2.py 36 2014-03-16 19:37:27Z georgesk $ licence={} licence_en=""" file usbDisk2.py this file is part of the project scolasync. It is a rewrite of usbDisk.py to take in account udisks2. Copyright (C) 2014 Georges Khaznadar 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 version3 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 . """ licence['en']=licence_en dependences="python3-dbus python3-dbus.mainloop.qt" import dbus, subprocess, os, os.path, re, time, threading, logging, inspect from dbus.mainloop.glib import DBusGMainLoop, threads_init from gi.repository import Gio, GLib, UDisks from PyQt5.QtWidgets import * #################### activate debugging ####################### debug=False def inspectData(): return "" if debug : logging.basicConfig(level=logging.DEBUG) def inspectData(): caller=1 callerframerecord = inspect.stack()[caller] frame = callerframerecord[0] info = inspect.getframeinfo(frame) return " -- file={0}, function={1}, line={2}".format( info.filename, info.function, info.lineno ) else: pass # logging.basicConfig(level=logging.NOTSET) ############################################################### def safePath(obj): """ Récupère de façon sûre le path d'une instance de UDisksObjectProxy @param obj instance de UDisksObjectProxy, ou simple chaine """ if type(obj)==type(""): path=obj else: path= obj.get_object_path() posUnderscore=path.rfind("_") posSlash=path.rfind("/") if posUnderscore > posSlash: # il faut retirer tout après l'underscore final path=path[:posUnderscore] return path def fs_size(device): """ Renvoie la taille d'un système de fichier et la place disponible @return un tuple : taille totale et espace libre """ try: stat = os.statvfs(device) except: return (0, 0) free = stat.f_bsize * stat.f_bavail # les blocs réservés sont inclus total = stat.f_bsize * stat.f_blocks return (total, free) ############ la variable suivante a été recopiées à l'aveugle ################ ############ depuis un fichier du projet USBcreator ########################## no_options = GLib.Variant('a{sv}', {}) ############################################################################## ############################################################################## ######### des "chemins" correspondant à des disques non débranchables ######## not_interesting = ( # boucle '/org/freedesktop/UDisks2/block_devices/loop', # disque raid '/org/freedesktop/UDisks2/block_devices/dm_', # mémoire vive '/org/freedesktop/UDisks2/block_devices/ram', '/org/freedesktop/UDisks2/block_devices/zram', # disques durs '/org/freedesktop/UDisks2/drives/', ) class UDisksBackend: """ Cette classe a été inspirée par le projet USBcreator. Plusieurs modifications ont été faites au code original. Les fonctions de rappel ne tiennent compte que des périphériques USB """ def __init__(self, logger=logging, diskClass=object): """ Le constructeur. @param logger un objet permettant de journaliser les messages ; par défaut il se confond avec le module logging @param diskClass la classe à utiliser pour créer des instances de disques """ self.install_thread = None self.logger=logger ## self.targets est un dictionnaire des disques détectés ## les clés sont les paths et les contenus des instances de diskClass self.diskClass=diskClass self.targets = {} ## self.modified signifie une modification récente, à prendre en compte ## par une application au niveau utilisateur self.modified=False DBusGMainLoop(set_as_default=True) threads_init() self.bus = dbus.SystemBus() self.udisks = UDisks.Client.new_sync(None) self.manager = self.udisks.get_object_manager() self.cbHooks = { 'object-added': { 'profile': ['man', 'obj'], 'hooks' : [] }, 'object-removed': { 'profile': ['man', 'obj'], 'hooks' : [] }, 'interface-added': { 'profile': ['man', 'obj'], 'hooks' : [] }, 'interface-removed': { 'profile': ['man', 'obj'], 'hooks' : [] }, 'interface-proxy-properties-changed': { 'profile': ['man', 'obj', 'interface'], 'hooks' : [] }, } # mise en place des fonctions de rappel à utiliser pour tout changement self.addHook('object-added', lambda man, obj: self._udisks_obj_added(obj)) self.addHook('object-removed', lambda man, obj: self._udisks_obj_removed(obj)) self.addHook('interface-added', lambda man, obj, iface: self._device_changed(obj)) self.addHook('interface-removed', lambda man, obj, iface: self._device_changed(obj)) self.addHook('interface-proxy-properties-changed', lambda man, obj, iface, props, invalid: self._device_changed(obj)) def addHook(self, signal, func): """ ajoute une fonction à appeler pour un signal nommé, et enregistre cette fonction dans self.cbHooks, après vérification de sa liste de paramètres. @param signal une chaîne @param func une fonction @return le résultat de l'appel à self.manager.connect(signal,func) """ if inspect.getargspec(func).args == self.cbHooks[signal]['profile']: cb=self.manager.connect(signal,func) self.cbHooks[signal]['hooks'].append(cb) return cb return None # voir le fichier integration-test issu des sources de udisks2 def retry_mount(self, fs, timeout=5, retryDelay=0.3): """ Essaie de monter un système de fichier jusqu'à ce qu'il cesse d'échouer avec "Busy", ou que l'erreur soit "déjà monté". Échoue si l'erreur est autre que les deux précédentes. @param fs un système de fichier à monter @param timeout nombre de secondes d'attente au maximum @param retryDelay délai entre deux essais """ while timeout >= 0: try: return fs.call_mount_sync(no_options, None) except GLib.GError as e: if 'UDisks2.Error.AlreadyMounted' in e.message: m=re.match(r".*already mounted[^/]*([^\']+).*",e.message) return m.group(1) elif 'UDisks2.Error.DeviceBusy' in e.message: pass else: raise time.sleep(retryDelay) timeout -= retryDelay return '' def detect_devices(self): """ Fait un inventaire des disques. """ for obj in self.manager.get_objects(): self._udisks_obj_added(obj) def _interesting_obj(self, obj): """ trouve si un objet est intéressant à cataloguer @param obj une instance de UDisksObjectProxy @return un triplet interesting (vrai/faux), drive (objet), partition (objet). """ interesting=False drive=None partition=None # ne tient pas compte des périphériques non débranchables path = safePath(obj) for boring in not_interesting: if path.startswith(boring): return interesting, drive, partition # ne considère que les périphériques de type block block = obj.get_block() if not block: return interesting, drive, partition # initialise drive, nom du disque ? drive_name = block.get_cached_property('Drive').get_string() if drive_name == '/': return interesting, drive, partition else: drive = self.udisks.get_object(drive_name).get_drive() # on ne tient pas compte des CDROMS ni DVDROMS if drive and drive.get_cached_property('Optical').get_boolean(): return interesting, drive, partition interesting=True # détermine si on a un disque ou une partition partition = obj.get_partition() return interesting, drive, partition def _udisks_obj_added(self, obj): """ Fonction de rappel pour les ajouts de disque @param obj un objet renvoyé par l'évènement """ interesting, drive, part = self._interesting_obj(obj) if part: self._udisks_partition_added(obj, drive, part) elif drive: self._udisks_drive_added (obj, drive, part) return def objIsUsb(self,obj): """ détermine si un périphérique est de type USB @param obj un objet UDisksObjectProxy @return vrai si c'est un périphérique USB """ if obj.get_block().props.read_only: return False # on ne considère pas les disques non inscriptibles for s in obj.get_block().get_cached_property('Symlinks'): if b'/dev/disk/by-id/usb' in bytes(s): return True return False def _udisks_partition_added(self, obj, drive, partition): """ Fonction de rappel pour l'ajout d'une partition, met à jour self.targets @param obj une instance de UDisksObjectProxy @param drive une instance de ... @param partition une instance de ... """ path = safePath(obj) block = obj.get_block() self.logger.debug(QApplication.translate("uDisk","Added partition %s",None) % path+inspectData()) fstype = block.get_cached_property('IdType').get_string() parent = partition.get_cached_property('Table').get_string() total = drive.get_cached_property('Size').get_uint64() free = -1 mount = '' fs = obj.get_filesystem() if fs: mount_points = fs.get_cached_property('MountPoints').get_bytestring_array() if len(mount_points)>0: mount= mount_points[0] if not mount and fstype == 'vfat': try: mount = self.retry_mount(fs) except: logging.exception(QApplication.translate("uDisk","Failed to mount the disk: %s",None) % path) if mount: total, free = fs_size(mount) isUsb=self.objIsUsb(obj) if not isUsb: self.logger.debug(QApplication.translate("uDisk","Disk not added: not a USB partition",None)+inspectData()) elif total < 1: self.logger.debug(QApplication.translate("uDisk","Disk not added: empty partition",None)+inspectData()) else: udisk=self.diskClass( path=path, mp=mount, isUsb=isUsb, vendor=drive.get_cached_property('Vendor').get_string(), model=drive.get_cached_property('Model').get_string(), parent=safePath(parent), fstype=fstype, serial=block.get_cached_property('Drive').get_string().split('_')[-1], uuid=block.get_cached_property('IdUUID').get_string(), free=free, capacity=total, device=block.get_cached_property('Device').get_bytestring().decode('utf-8'), label=block.get_cached_property('IdLabel').get_string() ) self.targets[path] = udisk self.modified=True return def _udisks_drive_added(self, obj, drive, part): path = safePath(obj) block = obj.get_block() if path in self.targets: self.logger.debug(QApplication.translate("uDisk","Already added disk: %s",None) % path+inspectData()) return self.logger.debug(QApplication.translate("uDisk","Added disk: %s",None) % path+inspectData()) size = drive.get_cached_property('Size').get_uint64() ##### désactivé, quelquefois drive.get_cached_property('Size').get_uint64() ##### renvoie des résultats erronés juste après le branchement """ if size <= 0: self.logger.debug(QApplication.translate("uDisk","Disk not added: zero byte partition.",None)+inspectData()) return """ isUsb = self.objIsUsb(obj) if not isUsb: self.logger.debug(QApplication.translate("uDisk","Disk not added: not a USB partition",None)+inspectData()) else: udisk=self.diskClass( path=path, isUsb=isUsb, parent='', vendor=drive.get_cached_property('Vendor').get_string(), model=drive.get_cached_property('Model').get_string(), serial=block.get_cached_property('Drive').get_string().split('_')[-1], uuid=block.get_cached_property('IdUUID').get_string(), capacity=size, device=block.get_cached_property('Device').get_bytestring().decode('utf-8'), ) self.targets[path] =udisk self.modified=True return def _device_changed(self, obj): path = safePath(obj) self.logger.debug(QApplication.translate("uDisk","Change for the disk %s",None) % path+inspectData()) def _udisks_obj_removed(self, obj): """ Fonction de rappel déclenchée par le retrait d'un disque. Met à jour self.targets @param obj une instance de UDisksObjectProxy """ path=safePath(obj) logging.debug(QApplication.translate("uDisk","Disk unplugged from the system: %s",None) % path) if path in self.targets: self.targets.pop(path) self.modified=True class uDisk2: """ une classe pour représenter un disque ou une partition. les attributs publics sont : - \b path le chemin dans le système dbus - \b device l'objet dbus qui correspond à l'instance - \b device_prop un proxy pour questionner cet objet dbus - \b selected booléen vrai si on doit considérer cette instance comme sélectionnée. Vrai à l'initialisation - \b rlock un verrou récursif permettant de réserver l'usage du media pour un seul thread """ def __init__( self, path, mp='', isUsb=False, vendor='', model='', parent=None, fstype='', serial='', uuid='', free=0, capacity=0, device='', firstFat=None, selected=True, label='' ): """ Le constructeur @param path un chemin comme '/org/freedesktop/UDisks2/block_devices/sdX' @param mp point de montage ('' par défaut) @param isUsb en général, vrai vu qu'on se s'intéressera qu'à des périphériques USB @param vendor indication de vendeur @param model indication de modèle @param parent périphérique parent (None par défaut) @param fstype type de système de fichiers @param serial numéro de série @param uuid identifiant donné au disque lors du formatage @param free taille de la zone libre pour l'écriture @param capacity taille du périphérique @param device pseudo-fichier pour l'accès au périphérique @param firstFat une instance de uDisk2, de type vfat parmi les partitions @param selected vrai/faux selon qu'on sélectionne ou non le périphérique (vrai par défaut) @param label le label s'il y en a un pour le système de fichiers """ self.path=path self.mp=mp self.isUsb=isUsb self.vendor=vendor self.model=model self.parent=parent self.fstype=fstype self.stickid=serial self.uuid=uuid self.free=free self.capacity=capacity self.devStuff=device self.firstFat=firstFat self.selected=selected self.label=label self.rlock=threading.RLock() return _itemNames={ "1mp":QApplication.translate("uDisk","mount point",None), "2capacity":QApplication.translate("uDisk","size",None), "3vendor":QApplication.translate("uDisk","brand",None), "4model":QApplication.translate("uDisk","disk model",None), "5stickid":QApplication.translate("uDisk","serial number",None), } _specialItems={"0Check":QApplication.translate("uDisk","check",None)} _ItemPattern=re.compile("[0-9]?(.*)") def uniqueId(self): """ renvoie un identifiant unique. Dans cette classe, cette fonction est synonyme de file() @return un identifiant unique, garanti par le système de fichiers """ return self.file() def headers(locale="C"): """ Méthode statique, pour avoir des titres de colonne. renvoie des titres pour les items obtenus par __getitem__. @param locale la locale, pour traduire les titres éventuellement. Valeur par défaut : "C" @return une liste de titres de colonnes """ result= list(uDisk2._specialItems.keys())+ list(uDisk2._itemNames.keys()) return sorted(result) headers = staticmethod(headers) def __str__(self): """ Fournit une représentation imprimable @return une représentation imprimable de l'instance """ return self.title()+self.valuableProperties() def title(self): """ Permet d'obtenir un identifiant unique de disque @return le chemin dbus de l'instance """ return self.path def isDosFat(self): """ Permet de reconnaitre les partitions DOS-FAT @return True dans le cas d'une partition FAT16 ou FAT32 """ return self.fstype=="vfat" def isMounted(self): """ @return True si le disque ou la partion est montée """ return bool(self.mp) def valuableProperties(self,indent=4): """ Facilite l'accès aux propriétés intéressantes d'une instance @return une chaîne indentée avec les propriétés intéressantes, une par ligne """ prefix="\n"+" "*indent r="" props=["mp", "parent", "fstype", "stickid", "uuid", "vendor", "model", "devStuff", "free", "capacity", "label"] for prop in props: r+=prefix+"%s = %s" %(prop, getattr(self,prop)) return r def mountPoint(self): """ @return le point de montage """ return self.mp def unNumberProp(self,n): """ retire le numéro des en-têtes pour en faire un nom de propriété valide pour interroger dbus @param n un numéro de propriété qui se réfère aux headers @return une propriété renvoyée par dbus, dans un format imprimable """ m=uDisk2._ItemPattern.match(self.headers()[n]) try: return getattr(self, m.group(1)) except: return "" def __getitem__(self,n): """ Renvoie un élément de listage de données internes au disque @param n un nombre @return un élément si n>0, et le drapeau self.selected si n==0. Les noms des éléments sont dans la liste itemNames utilisée dans la fonction statique headers """ propListe=self.headers() if n==0: return self.selected elif n <= len(propListe): return self.unNumberProp(n-1) def ensureMounted(self): """ Permet de s'assurer qu'une partition ou un disque sera bien monté @result le chemin du point de montage """ mount_paths=self.mp if mount_paths==None: # le cas où la notion de montage est hors-sujet return "" leftTries=5 while len(mount_paths)==0 and leftTries >0: leftTries = leftTries - 1 path=self.path if len(path)>0: subprocess.call("udisks --mount %s > /dev/null" %path,shell=True) paths=self.mp print("STILL TO DEBUG: is the mount OK? is self.mp updated?") if paths: return paths else: time.sleep(0.5) else: time.sleep(0.5) if leftTries==0: raise Exception ("Could not mount the VFAT after 5 tries.") else: return mount_paths class Available (UDisksBackend): """ une classe pour représenter la collection des disques USB connectés les attributs publics sont : - \b access le type d'accès qu'on veut pour les items - \b targets la collection de disques USB, organisée en un dictionnaire de disques : les clés sont les disques, qui renvoient à un ensemble de partitions du disque - \b firstFats une liste composée de la première partion DOS-FAT de chaque disque USB. """ def __init__(self, access="disk", diskClass=uDisk2): """ Le constructeur @param access définit le type d'accès souhaité. Par défaut, c'est "disk" c'est à dire qu'on veut la liste des disques USB. Autres valeurs possibles : "firstFat" pour les premières partitions vfat. @param diskClass la classe de disques à créer """ UDisksBackend.__init__(self, diskClass=diskClass) self.access=access self.detect_devices() self.finishInit() def finishInit(self): """ Fin de l'initialisation """ self.mountFirstFats() def mountFirstFats(self): """ fabrique la liste des partitions FAT, monte les partitions FAT si elles ne le sont pas """ self.firstFats = self.getFirstFats() if self.access=="firstFat": for p in self.firstFats: uDisk2(p,self).ensureMounted() def __trunc__(self): """ @return le nombre de medias connectés """ return len(self.firstFats) def compare(self, other): """ Sert à comparer deux collections de disques, par exemple une collection passée et une collection présente. @param other une instance de Available @return vrai si other semble être la même collection de disques USB """ result=self.summary()==other.summary() return result def contains(self, ud): """ Permet de déterminer si un disque est dans la collection @param ud une instance de uDisk @return vrai si le uDisk ud est dans la collection """ return ud.path in self.targets def disks(self): """ Récolte les enregistrements de niveau supérieur de self.targets @return la liste des chemins vers les disque USB détectés """ return [d for d in self.targets if not self.targets[d].parent] def parts(self, d): """ Récolte les partitions d'un disque @param d le chemin vers un disque @return la liste des partitions de ce disque """ return [p for p in self.targets if self.targets[p].parent==d] def disks_ud(self): """ Récolte les enregistrements de niveau supérieur de self.targets @return la liste des objects uDisk2 détectés """ return [self.targets[d] for d in self.targets if not self.targets[d].parent] def parts_ud(self, d): """ Récolte les partitions d'un disque @param d le chemin vers un disque @return la liste des objets uDisk2 qui sont des partitions de ce disque """ return [self.targets[p] for p in self.targets if self.targets[p].parent==d] def parts_summary(self, d): """ Fait un court résumé des partitions d'un disque @param d le disque, donné soit sous forme udev soit comme chemin uDisks2 @result une liste ordonnée de descriptions courtes """ def short(partition_ud): """ Renvoie une description courte d'une partition ; abrège le label s'il est trop long. @param partition_ud une partition @return une chaîne """ dev=os.path.basename(partition_ud.path) label=partition_ud.label label1=label.split(" ")[0] if len(label) > 11: label=label1[:8]+"..." if partition_ud.label: return "{}({})".format(dev, label) return dev d=os.path.join( "/org/freedesktop/UDisks2/block_devices", os.path.basename(d)) return sorted([short(p) for p in self.parts_ud(d)]) def summary(self): """ Fournit une représentation imprimable d'un résumé @return une représentation imprimable d'un résumé de la collection """ r= "Available USB disks\n" r+= "===================\n" for d in sorted(self.disks()): r+="%s\n" %(self.targets[d].devStuff) partlist=self.parts(d) if len(partlist)>0: r+=" Partitions :\n" for part in partlist: r+=" %s\n" %(self.targets[part].devStuff,) return r def __str__(self): """ Fournit une représentation imprimable @return une représentation imprimable de la collection """ r= "Available USB disks\n" r+= "===================\n" for d in self.disks(): r+="%s\n" %d partlist=self.parts(d) if len(partlist)>0: r+=" Partitions :\n" for part in sorted(partlist): r+=" %s\n" %(self.targets[part].devStuff) r+=self.targets[part].valuableProperties(12)+"\n" return r def disksDict(self): """ @return Renvoie un dictionnaire disque => partitions """ result={} for d in self.disks(): result[d]=self.parts(d) return result def __getitem__(self, n): """ Renvoye le nième disque. Le fonctionnement dépend du paramètre self.access @param n un numéro @return le nième disque USB connecté sous forme d'instance de uDisk2 """ if self.access=="disk": path=self.targets.keys()[n] elif self.access=="firstFat": path=self.firstFats[n] return self.targets[path] def __len__(self): """ Renseigne sur la longueur de la collection. Le fonctionnement dépend du paramètre self.access @return la longueur de la collection de disques renvoyée """ if self.access=="disk": return len(self.targets) elif self.access=="firstFat": return len(self.firstFats) def getFirstFats(self): """ Facilite l'accès aux partitions de type DOS-FAT, et a des effets de bord : * marque la première vfat dans chaque instance de disque * construit une liste des chemins uDisk des FATs @return une liste de partitions, constituée de la première partition de type FAT de chaque disque USB connecté """ result=[] disks=[d for d in self.targets if not self.targets[d].parent] for d in disks: parts=[p for p in self.targets if self.targets[p].parent==d] for p in parts: if self.targets[p].fstype=="vfat": result.append(p) # inscrit l'information dans l'instance du disque, par effet de bord self.targets[d].firstFat=self.targets[p] return result def hasDev(self, dev): """ @param dev un chemin comme /org/freedesktop/UDisks/devices/sdb3 @return True si la partition est dans la liste des partions disponibles """ s=str(dev) for p in self.fatPaths: if p.split("/")[-1]==s: return True return False ##################### fin de la définition de la calsse uDisk2 ################ live-clone-1.5.1/wizards.py000066400000000000000000000473761356647605500156520ustar00rootroot00000000000000""" Defines wizards related to actions of live-clone """ from PyQt5.QtWidgets import QWizard, QWizardPage, QLineEdit, QVBoxLayout, \ QRadioButton, QPlainTextEdit, QTreeView, QWidget, QCheckBox, \ QMessageBox, QPushButton, QFileDialog from PyQt5.QtGui import QStandardItemModel, QStandardItem from PyQt5.QtCore import Qt from tools import MountPoint, FileTreeSelectorModel from monitor import Monitor, CloneMonitor from subprocess import Popen, PIPE, call from datetime import datetime import os, re def createVfatExt4Partitions(device, size="4G"): """ create a VFAT and a EXT4 partition on a device. first find the number of the first VFAT partition, and erase any partition with this number or a greater number. Then create a VFAT partiton with size `size`, and a EXT4 partition to use all the space remaining on the device. Finally format both partitons according to their types @param device a string, like "/dev/sdc" @param size a string, defaults to "4G" @return the number of the last created partition (i.e. the EXT4 partition's number) """ cmd="fdisk -l {}".format(device) p=Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True) out, err= p.communicate() out=out.decode("utf-8") FATlines=[] for l in out.split("\n"): m=re.match(r"^(/dev/\S+)\s.*FAT",l) if m: # remember the FAT partition and unmount it FATlines.append(m.group(1)) call(f"umount {m.group(1)}", shell=True) else: m=re.match(r"^(/dev/\S+)\s.*",l) if m: # unmount other partitions too call(f"umount {m.group(1)}", shell=True) assert (FATlines) # there *must* be a first VFAT partition m=re.match(r"/dev/\D+(\d+)",FATlines[0]) fatNum=int(m.group(1)) inputs=f"""\ d n p {fatNum} +4G t 0c n p {fatNum+1} w """ p=Popen(f"fdisk {device}", shell=True, stdout=PIPE, stderr=PIPE, stdin=PIPE) p.stdin.write(inputs.encode("utf-8")) message,err=p.communicate() call(f"sleep 6; partprobe {device}", shell=True) persistenceNum = fatNum+1 call(f"mkfs.vfat -n DATA {device}{fatNum}", shell=True) call(f"mkfs.ext4 -L persistence -F {device}{persistenceNum}", shell=True) return persistenceNum def new_packages(d, persistenceNum): """ Work out a list of newer packages installed in the persistence zone of a debian-live Disk @param d a disk given as a /dev/sdx string @param persistenceNum the number of the persistence partition @return a text with on package by line """ with MountPoint(d+"1") as base, MountPoint(d+str(persistenceNum)) as pers: cmd="""find "{pers}/rw/var/lib/dpkg/info" -name "*.list" -newer "{base}/live/filesystem.packages" | sed -e "s%{pers}/rw/var/lib/dpkg/info/%%" -e 's/.list$//' -e 's/:.*//'""".format(base=base, pers=pers) p=Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True) out, err= p.communicate() return out.decode("utf-8") class ToolWizard(QWizard): """ The wizard associated to the "Tools" button of live-clone """ def __init__(self, mw): """ the constructor @param mw a MyMain (<= QMainWindow) instance """ QWizard.__init__(self, mw) self.setWindowTitle(self.tr("Repair and/or manage a Freeduc USB stick")) page1=QWizardPage(self) page1.setTitle(self.tr("Select one disk")) page1.setSubTitle(self.tr("Which disk do you want to repair or to save?")) target=QLineEdit(page1) target.hide() page1.registerField("target*", target) layout=QVBoxLayout() radios={} def setTarget(checked): for r in radios: if r.isChecked(): page1.setField("target", r.text()) return for d in mw.not_self_keys(format="udev"): rb=QRadioButton(d, parent=page1) rb.toggled.connect(setTarget) layout.addWidget(rb) radios[rb]=d page1.setLayout(layout) self.addPage(page1) ## assert page1.field("target") page2=QWizardPage(self) disk=self.field("target") persistenceNum=4 # default number for the persistence partition page2.setTitle(self.tr("List of additional packages in {}").format(disk)) page2.setSubTitle(self.tr("Here is the list of packages which you can restore later. You can edit the text before saving it.")) layout=QVBoxLayout() ed=QPlainTextEdit(page2) layout.addWidget(ed) newpackages=True def page2init(foo=None): nonlocal newpackages nonlocal persistenceNum disk=self.field("target") ## find the persistence partition if any diskname=disk.replace("/dev/","") cmd="ls -l /dev/disk/by-label| grep persistence | grep "+diskname p=Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True) out, err= p.communicate() if out: persistenceNum=out.decode("utf8").strip()[-1] else: newpackages=False return # no persistence, no need to develop the wizard further # we know the number of the persistence partition newpackages=new_packages(disk, persistenceNum) if not newpackages: packages=self.tr("There are no new packages installed in the persistence partition") packages=self.tr("""\ ADDITIONAL PACKAGES =================== """) + "{}\n{}\n".format(disk,len(disk)*"-") + packages c=ed.textCursor() c.insertText(packages) ed.moveCursor(c.Start) ed.ensureCursorVisible() return page2.setLayout(layout) page2.initializePage=page2init def page2Validate(foo=None): if not newpackages: return True proposed_fname = "packages-{}.md".format( datetime.now().strftime("%Y-%m-%d--%H-%M") ) fname, _ = QFileDialog.getSaveFileName( self, self.tr("Save Packages File"), proposed_fname, self.tr("Markdow files (*.md);;Plain text files (*.txt);;Any file (*)") ) if fname: with open(fname,"w") as outfile: outfile.write(ed.toPlainText()) if "SUDO_UID" in os.environ and "SUDO_GID" in os.environ: ## it is possible to downgrade the owner of the file os.chown( fname, int(os.environ["SUDO_UID"]), int(os.environ["SUDO_GID"]) ) return True page2.validatePage=page2Validate self.addPage(page2) page3=QWizardPage(self) page3.setTitle(self.tr("Select personal data to save")) page3.setSubTitle(self.tr('Please check the tree of data which you want to backup. If you check the topmost node "user", all and every personal data is chosen, including Mozilla cache and desktop preferences. You may prefer to check subtrees. The subtrees are taken in account only when no node is checked above.')) layout=QVBoxLayout() tree=QTreeView(page3) layout.addWidget(tree) mp=None model=None exists=False def page3Init(foo=None): nonlocal mp, model, exists mp=MountPoint(self.field("target")+str(persistenceNum)) mp.enter_() if mp: rootpath=os.path.join(str(mp), "rw", "home") exists = os.path.exists(rootpath) if exists: model = FileTreeSelectorModel(rootpath=rootpath) model.setRootPath(rootpath) tree.setModel(model) tree.setRootIndex(model.parent_index) tree.setAnimated(False) tree.setIndentation(20) tree.setSortingEnabled(True) else: ## there are no personal data model = QStandardItemModel() model.setHorizontalHeaderLabels( [self.tr('Nothing is available')]) tree.setModel(model) tree.setUniformRowHeights(True) node1 = QStandardItem( self.tr('No personal data in the persistence partition')) model.appendRow(node1) return def page3validate(foo=None): nonlocal mp, exists if not exists: return True to_save=[] def cb(i, stack): if model.checkState(i)==Qt.Checked: pathdata=[index.data() for index in stack+[i]] to_save.append(os.path.join(*pathdata)) return i=model.parent_index model.traverseDirectoryWhileUnchecked(i,callback=cb) ### ask for a tgz file name and make a tarball into it proposed_fname = "DATA-{}.tgz".format( datetime.now().strftime("%Y-%m-%d--%H-%M") ) fname="" if to_save: fname, _ = QFileDialog.getSaveFileName( self, self.tr("Save personal data archive"), proposed_fname, self.tr("TAR-GZIP archives (*.tgz,*.tar.gz);;Any file (*)") ) if fname: ### launch the command asynchronously with a Monitor command = "/usr/bin/tar" args=[ "czvf", fname ] + [os.path.join(str(mp), "rw", p) for p in to_save] ### add a new tab and a monitor n=mw.ui.tabWidget.count() title=self.tr("Save personal persistence data to {}").format(fname) newWidget=QWidget() mw.ui.tabWidget.addTab( QWidget(), self.tr("Save to {}").format(fname) ) rindex=mw.rindexFromDev(self.field("target")) if rindex==None: return True # rindex is defined, it bears the row number for the device def makeFinishCallback(): return lambda: mp.exit_() m=Monitor( command, args, mw, n, rindex, finishCallback=makeFinishCallback(), environ=os.environ, createfiles=[fname], actionMessage=self.tr("save-data"), buttonMessage=self.tr("Close the log of the archive"), ) mw.monitors[m]=self.field("target") m.start() return True page3.initializePage=page3Init page3.validatePage=page3validate page3.setLayout(layout) self.addPage(page3) page4=QWizardPage(self) page4.setTitle(self.tr("Select personal data to save")) page4.setSubTitle(self.tr('Now, you have carefully backuped sensistive data, you may erase the persistence; however, you can still cancel it.')) def page4validate(foo=None): if self.field("ok1") and self.field("ok2"): pers=self.field("target")+str(persistenceNum) call ("umount {}".format(pers), shell=True) def page4CallBackMaker(): def callback(): nonlocal persistenceNum must_format = False # do we have to format the device? # first check whether the persistence partition exists with MountPoint(self.field("target")+str(persistenceNum)) as mp: if not mp.capacity: must_format = True # format the device if necessary if must_format: persistenceNum = createVfatExt4Partitions(self.field("target")) # then create the persistence.conf file with MountPoint(self.field("target")+str(persistenceNum)) as mp: confFile=os.path.join(str(mp),"persistence.conf") call("echo '/ union' > {}".format(confFile), shell=True) QMessageBox.information( self, self.tr("Persistence erased"), self.tr("Persistence data have been erased from {}").format(self.field("target")+str(persistenceNum)) ) return return callback command="mkfs" args= [ "-F", "-L", "persistence", "-t", "ext4", pers ] n=mw.ui.tabWidget.count() title=self.tr("Format the partition {}").format(pers) newWidget=QWidget() mw.ui.tabWidget.addTab( QWidget(), self.tr("Format the partition {}").format(pers) ) rindex=mw.rindexFromDev(self.field("target")) if rindex==None: return True m=Monitor(command, args, mw, n, rindex, actionMessage="Formating", finishCallback=page4CallBackMaker() ) mw.monitors[m]=self.field("target") m.start() return True layout=QVBoxLayout() request1CB=QCheckBox(self.tr("Yes, I am sure that I want to erase the persistence.")) request2CB=QCheckBox(self.tr("Yes again, I am completely sure!")) page4.registerField("ok1", request1CB) page4.registerField("ok2", request2CB) layout.addWidget(request1CB) layout.addWidget(request2CB) page4.setLayout(layout) page4.validatePage=page4validate self.addPage(page4) return class CloneWizard(QWizard): """ The wizard associated to the "Clone" button of live-clone """ def __init__(self, mw): """ the constructor @param mw a MyMain (<= QMainWindow) instance """ QWizard.__init__(self, mw) self.setWindowTitle(self.tr("Clone a Freeduc system to USB drives")) page1=QWizardPage(self) page1.setTitle(self.tr("Select the target disks")) page1.setSubTitle(self.tr("Please check the disks where you want to clone the system. Warning: all data exiting on those disks will be erased, you can still Escape from this process.")) selectedDisks=QLineEdit() selectedDisks.setReadOnly(True) selectedDisks.hide() # not visible, it bears juste a calculated field page1.registerField("selectedDisks*", selectedDisks) boxes={} def updateSelectedDisks(checkState=-1): """ callback for changes in checkboxes """ selected=[d for b,d in boxes.items() \ if b.checkState()==Qt.Checked] sel=",".join(selected) page1.setField("selectedDisks", sel) if checkState==-1: #called before the wizard is initialized selectedDisks.setText(sel) return layout=QVBoxLayout() for disk in mw.not_self_keys(format="udev"): shortParts=mw.lesCles.parts_summary(disk) chb=QCheckBox("{} [{}]".format( disk, ", ".join(shortParts)) ) boxes[chb]=disk chb.stateChanged.connect(updateSelectedDisks) layout.addWidget(chb) layout.addWidget(selectedDisks) page1.setLayout(layout) self.addPage(page1) sourceEdit=QLineEdit() sourceEdit.setReadOnly(True) page2=QWizardPage(self) page2.registerField("source*", sourceEdit) ownClone=os.path.exists("/usr/lib/live/mount/persistence") def page2init(foo=None): if ownClone: sourceEdit.setText("AUTOCLONE (Freeduc disks can clone themselves natively)") return page2.initializePage=page2init page2.setTitle(self.tr("Source of the core system")) if ownClone: page2.setSubTitle(self.tr("The program is running from a Freeduc GNU-Linux system")) else: page2.setSubTitle(self.tr("The program is running from a plain GNU-Linux system")) layout=QVBoxLayout() page2.setLayout(layout) def chooseISO(event=None): source, _ = QFileDialog.getOpenFileName( caption = self.tr("Choose an image to clone"), filter = self.tr("ISO Images (*.iso);;All files (*)") ) page2.setField("source", source) chooseButton=QPushButton("Choose the source of the core system") chooseButton.clicked.connect(chooseISO) layout.addWidget(chooseButton) layout.addWidget(sourceEdit) def page2validate(foo=None): command="/usr/bin/python3" source=page2.field("source") if source.startswith("AUTOCLONE"): source="own" for device in self.field("selectedDisks").split(","): rindex=mw.rindexFromDev(device) if rindex==None: return True args=[ "{}/makeLiveStick.py".format(mw.wd), "--no-persistence", "--source", source, device ] ### add a new tab and a monitor n=mw.ui.tabWidget.count() title=self.tr("Cloning to {}").format(device) mw.ui.tabWidget.addTab( QWidget(), self.tr("Cloning to {}").format(device) ) m=CloneMonitor(command, args, mw, n, rindex, environ=os.environ) mw.monitors[m]=device m.start() return True page2.validatePage=page2validate self.addPage(page2) return class RunWizard(QWizard): """ wizard for the runButton of live-clone """ def __init__(self, mw, devices, available): """ the constructor @param mw a MyMain (<= QMainWindow) instance @param devices a list of paths to USB devices @param available an Available instance """ QWizard.__init__(self, mw) disks=sorted([d for d in devices]) self.setWindowTitle(self.tr("Run a disk in a virtual machine")) page1=QWizardPage(self) page1.setTitle(self.tr("Select one disk")) page1.setSubTitle(self.tr("Which disk do you want to launch in a virtual machine?")) layout=QVBoxLayout() radios={} first=True for d in disks: rb=QRadioButton(d, parent=page1) if first: rb.setChecked(True) first=False layout.addWidget(rb) radios[rb]=d disks=QLineEdit(page1) disks.setReadOnly(True) disks.hide() def page1validate(foo=None): foundDisks=[] for rb in radios: if rb.isChecked(): foundDisks.append(radios[rb]) disks.setText(",".join(foundDisks)) return bool(foundDisks) page1.validatePage=page1validate page1.registerField("disks", disks) page1.setLayout(layout) self.addPage(page1) return